With this debugfs API I can create a file in /sys/kernel/debug/parent/name, but it's empty, no matter which data I put in void *data
parameter
struct dentry *debugfs_create_file(const char *name, mode_t mode, struct dentry *parent, void *data, struct file_operations *fops);
According to documentation we need to implement file_operations ourself to handle file open and write. A snippet of code from mine:
static ssize_t myreader(struct file *fp, char __user *user_buffer,
size_t count, loff_t *position)
{
return simple_read_from_buffer(user_buffer, count, position, ker_buf, len);
}
static ssize_t mywriter(struct file *fp, const char __user *user_buffer,
size_t count, loff_t *position)
{
if(count > len )
return -EINVAL;
return simple_write_to_buffer(ker_buf, len, position, user_buffer, count);
}
static const struct file_operations fops_debug = {
.read = myreader,
.write = mywriter,
};
static int __init init_debug(void)
{
dirret = debugfs_create_dir("dell", NULL);
fileret = debugfs_create_file("text", 0644, dirret, "HELLO WORLD", &fops_debug);
debugfs_create_u64("number", 0644, dirret, &intvalue);
return (0);
}
After installing this module to kernel, two files 'text' and 'number' will be created in the folder 'dell'. File 'number' contains the number I passed in as 'intvalue' as expected, but the other file 'text' is empty. It's written in document that data will be stored in the i_private field of the resulting inode structure My expectation: The string "HELLO WORLD" will be written in the file after module is loaded.
I think that the problem should be in the read and write operation functions. Is it possible to create a file with a particular content with the debugfs_create_file method?
CodePudding user response:
To answer your question, whatever you are expecting from your code is correct but it is not going to produce the expected result.
I believe there are other more efficient and correct ways of doing it, but to explain the current behavior:
- You are initializing data as content of file
text
but you are reading from bufferker_buf
inuser_buffer
instead of file pointer usingsimple_read_from_buffer(user_buffer, count, position, ker_buf, len);
- Similarly you are writing to
kern_buf
fromuser_buffer
usingsimple_write_to_buffer(ker_buf, len, position, user_buffer, count);
With the existing code, if you want to achieve what you are trying to do, then you have to copy the string "HELLO WORLD"
to kern_buf
in init_debug()
Something like: strscpy(kern_buf, "HELLO WORLD", strlen("HELLO WORLD") 1);
static int __init init_debug(void)
{
dirret = debugfs_create_dir("dell", NULL);
fileret = debugfs_create_file("text", 0644, dirret, NULL, &fops_debug);
debugfs_create_u64("number", 0644, dirret, &intvalue);
strscpy(kern_buf, "HELLO WORLD", strlen("HELLO WORLD") 1);
return (0);
}
Edit:
Referred some online materials and found out that the void *data
provided to debugfs_create_file()
during initialization gets stored in the i_private
field and can be later retrieved from the i_private
field of the resulting inode structure
.
The inode of the respective file can be fetched from struct file *fp
which is the first argument of read()
or write()
operations.
The struct inode
is a member of struct file
and i_private
is a member of struct inode
To fetch void *data
provided during file creation via debugfs_create_file()
in read()
you can do something similar to as shown below:
static ssize_t myreader(struct file *fp, char __user *user_buffer,
size_t count, loff_t *position)
{
struct inode *l_inode = fp->f_inode;
strscpy(user_buffer, (char *)l_inode->i_private, PAGE_SIZE);
...
}