debugfs.c: extend example with toplevel file, fop and kstrtoull_from_user

This commit is contained in:
Ciro Santilli
2018-04-13 07:56:32 +01:00
parent c1c517a1c7
commit 42e634ffd1
3 changed files with 49 additions and 6 deletions

View File

@@ -18,20 +18,49 @@ Only the more basic fops can be implemented in debugfs, e.g. mmap is never calle
#include <linux/module.h> #include <linux/module.h>
#include <uapi/linux/stat.h> /* S_IRUSR */ #include <uapi/linux/stat.h> /* S_IRUSR */
static struct dentry *dir; static struct dentry *dir, *toplevel_file;
static u32 value = 42; static u32 value = 42;
static ssize_t write(struct file *filp, const char __user *buf, size_t len, loff_t *off)
{
int ret;
unsigned long long res;
/* https://stackoverflow.com/questions/6139493/how-convert-char-to-int-in-linux-kernel */
ret = kstrtoull_from_user(buf, len, 10, &res);
if (ret) {
/* Negative error code. */
return ret;
} else {
value = res;
*off= len;
return len;
}
}
static const struct file_operations fops = {
.owner = THIS_MODULE,
.write = write,
};
static int myinit(void) static int myinit(void)
{ {
struct dentry *file; struct dentry *file;
dir = debugfs_create_dir("lkmc_debugfs", 0); dir = debugfs_create_dir("lkmc_debugfs", 0);
if (!dir) { if (!dir) {
printk(KERN_ALERT "debugfs_create_dir failed"); pr_alert("debugfs_create_dir failed");
return -1; return -1;
} }
file = debugfs_create_u32("myfile", S_IRUSR, dir, &value); file = debugfs_create_u32("myfile", S_IRUSR | S_IWUSR, dir, &value);
if (!file) { if (!file) {
printk(KERN_ALERT "debugfs_create_u32 failed"); pr_alert("debugfs_create_u32 failed");
return -1;
}
/* Created on the toplevel of the debugfs mount,
* and with explicit fops instead of a fixed integer value. */
toplevel_file = debugfs_create_file(
"lkmc_debugfs_file", S_IWUSR, NULL, NULL, &fops);
if (!toplevel_file) {
return -1; return -1;
} }
return 0; return 0;
@@ -40,6 +69,7 @@ static int myinit(void)
static void myexit(void) static void myexit(void)
{ {
debugfs_remove_recursive(dir); debugfs_remove_recursive(dir);
debugfs_remove(toplevel_file);
} }
module_init(myinit) module_init(myinit)

View File

@@ -14,6 +14,9 @@ Hello world module.
static int myinit(void) static int myinit(void)
{ {
pr_info("hello init\n"); pr_info("hello init\n");
/* 0 for success, any negative value means failure,
* E* consts if you want to specify failure cause.
* https://www.linux.com/learn/kernel-newbie-corner-loadable-kernel-modules-coming-and-going */
return 0; return 0;
} }

View File

@@ -1,12 +1,22 @@
#!/bin/sh #!/bin/sh
set -ex set -ex
mkdir -p /debugfs d=/debugfs
mkdir -p "$d"
# We also added a fstab entry that mounts this under /sys/kernel/debug autmoatically. # We also added a fstab entry that mounts this under /sys/kernel/debug autmoatically.
# That is the most common place to mount it. # That is the most common place to mount it.
# The /sys/kernel/debug directory gets created automatically when debugfs is # The /sys/kernel/debug directory gets created automatically when debugfs is
# compiled into the kernel, but it does not get mounted automatically. # compiled into the kernel, but it does not get mounted automatically.
mount -t debugfs none /debugfs mount -t debugfs none /debugfs
insmod /debugfs.ko insmod /debugfs.ko
cd /debugfs/lkmc_debugfs cd "${d}/lkmc_debugfs"
cat myfile cat myfile
# => 42 # => 42
echo 13 > myfile
cat myfile
# => 13
echo 666 > "${d}/lkmc_debugfs_file"
cat myfile
# => 666