We would like to move fsnotify_nameremove() calls from d_delete() into a higher layer where the hook makes more sense and so we can consider every d_delete() call site individually. Start by creating empty hook fsnotify_{unlink,rmdir}() and place them in the proper VFS call sites. After all d_delete() call sites will be converted to use the new hook, the new hook will generate the delete events and fsnotify_nameremove() hook will be removed. Signed-off-by: Amir Goldstein <amir73il@xxxxxxxxx> --- fs/libfs.c | 11 ++++++++--- fs/namei.c | 2 ++ include/linux/fsnotify.h | 26 ++++++++++++++++++++++++++ 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/fs/libfs.c b/fs/libfs.c index ca1132f1d5c6..4db61ca8cc94 100644 --- a/fs/libfs.c +++ b/fs/libfs.c @@ -10,6 +10,7 @@ #include <linux/cred.h> #include <linux/mount.h> #include <linux/vfs.h> +#include <linux/fsnotify.h> #include <linux/quotaops.h> #include <linux/mutex.h> #include <linux/namei.h> @@ -367,11 +368,15 @@ int simple_remove(struct inode *dir, struct dentry *dentry) * protect d_delete() from accessing a freed dentry. */ dget(dentry); - if (d_is_dir(dentry)) + if (d_is_dir(dentry)) { ret = simple_rmdir(dir, dentry); - else + if (!ret) + fsnotify_rmdir(dir, dentry); + } else { ret = simple_unlink(dir, dentry); - + if (!ret) + fsnotify_unlink(dir, dentry); + } if (!ret) d_delete(dentry); dput(dentry); diff --git a/fs/namei.c b/fs/namei.c index 20831c2fbb34..209c51a5226c 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -3883,6 +3883,7 @@ int vfs_rmdir(struct inode *dir, struct dentry *dentry) dentry->d_inode->i_flags |= S_DEAD; dont_mount(dentry); detach_mounts(dentry); + fsnotify_rmdir(dir, dentry); out: inode_unlock(dentry->d_inode); @@ -3999,6 +4000,7 @@ int vfs_unlink(struct inode *dir, struct dentry *dentry, struct inode **delegate if (!error) { dont_mount(dentry); detach_mounts(dentry); + fsnotify_unlink(dir, dentry); } } } diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h index 94972e8eb6d1..7f23eddefcd0 100644 --- a/include/linux/fsnotify.h +++ b/include/linux/fsnotify.h @@ -188,6 +188,19 @@ static inline void fsnotify_link(struct inode *dir, struct inode *inode, struct fsnotify(dir, FS_CREATE, inode, FSNOTIFY_EVENT_INODE, &new_dentry->d_name, 0); } +/* + * fsnotify_unlink - 'name' was unlinked + * + * Caller must make sure that dentry->d_name is stable. + */ +static inline void fsnotify_unlink(struct inode *dir, struct dentry *dentry) +{ + /* Expected to be called before d_delete() */ + WARN_ON_ONCE(d_is_negative(dentry)); + + /* TODO: call fsnotify_dirent() */ +} + /* * fsnotify_mkdir - directory 'name' was created */ @@ -198,6 +211,19 @@ static inline void fsnotify_mkdir(struct inode *inode, struct dentry *dentry) fsnotify_dirent(inode, dentry, FS_CREATE | FS_ISDIR); } +/* + * fsnotify_rmdir - directory 'name' was removed + * + * Caller must make sure that dentry->d_name is stable. + */ +static inline void fsnotify_rmdir(struct inode *dir, struct dentry *dentry) +{ + /* Expected to be called before d_delete() */ + WARN_ON_ONCE(d_is_negative(dentry)); + + /* TODO: call fsnotify_dirent() */ +} + /* * fsnotify_access - file was read */ -- 2.17.1