diff mbox series

[v2,03/14] fsnotify: add empty fsnotify_{unlink,rmdir}() hooks

Message ID CAOQ4uxi+ZcBgSKUrQr8QiWHB=N+udE0F1+Ry-wrCMV_jWkLLDA@mail.gmail.com (mailing list archive)
State New, archived
Headers show
Series None | expand

Commit Message

Amir Goldstein May 16, 2019, 3:30 p.m. UTC
Christoph,

From my patch series, this is really the only patch that is a
dependency to the patch you received earlier today:
"fsnotify: call fsnotify_rmdir() hook from configfs"

What you should know for wider context is that currently
users can sign up for inotify notifications on configfs.
If they do that with current kernel they will get notified when
directory is removed not via vfs_rmdir() or via
configfs_unregister_{group,subsystem}().

For reasons outside the scope of configfs, we intend to stop
calling fsnotify hook from d_delete(). In order to preserve existing
behavior (whether some users depends on it or not I do not know),
we add explicit fsnotify hooks in configfs_unregister_{group,subsystem}().

For most pseduo filesystems that use simple_rmdir(), I chose a different
approach of calling a new helper simple_remove(), where the new fsnotify
hook is placed. For configfs, I could not use the same technique because
configfs_remove_dir() is also called from execution path of vfs_rmdir(), where
the new fsnotify hook is already called.

Hope this context is sufficient for you to review the configfs patch and provide
an ACK, so Jan or Al can carry the configfs patch.

If you like me to post you the entire series, I can do that.

Thanks,
Amir.

---------- Forwarded message ---------
From: Amir Goldstein <amir73il@gmail.com>
Date: Thu, May 16, 2019 at 1:26 PM
Subject: [PATCH v2 03/14] fsnotify: add empty fsnotify_{unlink,rmdir}() hooks
To: Jan Kara <jack@suse.cz>
Cc: Matthew Bobrowski <mbobrowski@mbobrowski.org>,
<linux-fsdevel@vger.kernel.org>


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@gmail.com>
---
 fs/libfs.c               | 11 ++++++++---
 fs/namei.c               |  2 ++
 include/linux/fsnotify.h | 26 ++++++++++++++++++++++++++
 3 files changed, 36 insertions(+), 3 deletions(-)

  * 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
diff mbox series

Patch

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() */
+}
+
 /*