4
votes

I want to implement a tree traversal function which prints all the contents of a given directory in kernel . I know how to do this in user space, but my requirement is to have that in kernel space. For that, I am looking into vfs_readdir function and a bit confused regarding its usage. Say I will be calling my traversal function from other kernel module which means that request won’t be coming through user space. Now the question is how to call vfs_readdir and use that information to recursively parse given directory. From definition of vfs_readdir extern int vfs_readdir(struct file *, filldir_t, void *);

I can get struct file * from the file path using functions like filp_open() and as per my understanding filldir_t is a function pointer to call back function which fills the user provided buffer pointed by void *. But in my case, I don’t need to pass any information to user back. What should i pass in void * place? Looking into filldir function definition

static int filldir(void * __buf, const char * name, int namlen, loff_t offset, ino_t ino, unsigned int d_type);

From where are the parameters to this function are coming. My assumption is that vfs_readdir in turn calls something like file->f_op_readdir(file,but,filler); Does this internally does something and fills in parameters to call callback function ? Now this is one level. What should I do to recursively print all files in a given directory. I guess I need to do something in my own callback function.But I have only some information regarding the file that are passed through this call back functions like name of file,inode number etc . How would I know if it is regular file or directory using this information . I mean I don't have dentry or inode data structures regarding the file. Any suggestions how to do that? In addition, If I want to delete a file in callback function, can I do that by using inode numbers(thats what i have in callback apart from names) how should I do that?

1
Welcome to the Stack Exchange network! You should upvote helpful answers to your - or any - questions. The best answers should be accepted to give the answerers the credit and to inform others that your issue is resolved. See How does accepting an answer work?. - Anthony Geoghegan

1 Answers

4
votes

vfs_readdir is called, e.g., from readdir syscall implementation. It uses fillonedir as callback, which in turn can easy be understanded: its first argument is just last argument of vfs_readdir, all other arguments(name, namelen, offset, ino, d_type) are copied into user space as is.

Note, that callback for vfs_readdir is executed with inode mutex locked(inode->i_mutex). Probably you shoudn't open subdirectory incide that callback. Instead, save name of the subdirectory somewhere, and open it after vfs_readdir call. This is very similar to the way how you traverse directories tree in the user space.

Note, that since version 3.11 kernel uses another way for iterate entries in directory: iterate_dir. Its second argument combines both callback and callback-specific argument for it, and also include current position in the file. Aside from the first parameter, callback accepts same parameters as before.

As for ino argument, you cannot use it for open given inode(kernel just has no mechanism for open files by inode number). Use filp_open or similar.