fsnotify: generalize handle_inode_event()
authorAmir Goldstein <amir73il@gmail.com>
Wed, 2 Dec 2020 12:07:07 +0000 (14:07 +0200)
committerJan Kara <jack@suse.cz>
Thu, 3 Dec 2020 13:58:35 +0000 (14:58 +0100)
The handle_inode_event() interface was added as (quoting comment):
"a simple variant of handle_event() for groups that only have inode
marks and don't have ignore mask".

In other words, all backends except fanotify.  The inotify backend
also falls under this category, but because it required extra arguments
it was left out of the initial pass of backends conversion to the
simple interface.

This results in code duplication between the generic helper
fsnotify_handle_event() and the inotify_handle_event() callback
which also happen to be buggy code.

Generalize the handle_inode_event() arguments and add the check for
FS_EXCL_UNLINK flag to the generic helper, so inotify backend could
be converted to use the simple interface.

Link: https://lore.kernel.org/r/20201202120713.702387-2-amir73il@gmail.com
CC: stable@vger.kernel.org
Fixes: b9a1b9772509 ("fsnotify: create method handle_inode_event() in fsnotify_operations")
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
Signed-off-by: Jan Kara <jack@suse.cz>
fs/nfsd/filecache.c
fs/notify/dnotify/dnotify.c
fs/notify/fsnotify.c
include/linux/fsnotify_backend.h
kernel/audit_fsnotify.c
kernel/audit_tree.c
kernel/audit_watch.c

index 3c6c2f7d1688b43d844019761396e7d9b5046ce1..5849c1bd88f17a485eac84752d5ec1c6addb1d1d 100644 (file)
@@ -600,7 +600,7 @@ static struct notifier_block nfsd_file_lease_notifier = {
 static int
 nfsd_file_fsnotify_handle_event(struct fsnotify_mark *mark, u32 mask,
                                struct inode *inode, struct inode *dir,
-                               const struct qstr *name)
+                               const struct qstr *name, u32 cookie)
 {
        trace_nfsd_file_fsnotify_handle_event(inode, mask);
 
index 5dcda8f20c04f9eaa5d917c9324f2ef8e43fa4dc..e45ca6ecba959163b8b4b7b32787c5b1e61e701c 100644 (file)
@@ -72,7 +72,7 @@ static void dnotify_recalc_inode_mask(struct fsnotify_mark *fsn_mark)
  */
 static int dnotify_handle_event(struct fsnotify_mark *inode_mark, u32 mask,
                                struct inode *inode, struct inode *dir,
-                               const struct qstr *name)
+                               const struct qstr *name, u32 cookie)
 {
        struct dnotify_mark *dn_mark;
        struct dnotify_struct *dn;
index 8d3ad5ef292587085132a1fa7751f30daeb89efc..c5c68bcbaadf015f847b0e23b97b87394478d19d 100644 (file)
@@ -232,6 +232,26 @@ notify:
 }
 EXPORT_SYMBOL_GPL(__fsnotify_parent);
 
+static int fsnotify_handle_inode_event(struct fsnotify_group *group,
+                                      struct fsnotify_mark *inode_mark,
+                                      u32 mask, const void *data, int data_type,
+                                      struct inode *dir, const struct qstr *name,
+                                      u32 cookie)
+{
+       const struct path *path = fsnotify_data_path(data, data_type);
+       struct inode *inode = fsnotify_data_inode(data, data_type);
+       const struct fsnotify_ops *ops = group->ops;
+
+       if (WARN_ON_ONCE(!ops->handle_inode_event))
+               return 0;
+
+       if ((inode_mark->mask & FS_EXCL_UNLINK) &&
+           path && d_unlinked(path->dentry))
+               return 0;
+
+       return ops->handle_inode_event(inode_mark, mask, inode, dir, name, cookie);
+}
+
 static int fsnotify_handle_event(struct fsnotify_group *group, __u32 mask,
                                 const void *data, int data_type,
                                 struct inode *dir, const struct qstr *name,
@@ -239,13 +259,8 @@ static int fsnotify_handle_event(struct fsnotify_group *group, __u32 mask,
 {
        struct fsnotify_mark *inode_mark = fsnotify_iter_inode_mark(iter_info);
        struct fsnotify_mark *child_mark = fsnotify_iter_child_mark(iter_info);
-       struct inode *inode = fsnotify_data_inode(data, data_type);
-       const struct fsnotify_ops *ops = group->ops;
        int ret;
 
-       if (WARN_ON_ONCE(!ops->handle_inode_event))
-               return 0;
-
        if (WARN_ON_ONCE(fsnotify_iter_sb_mark(iter_info)) ||
            WARN_ON_ONCE(fsnotify_iter_vfsmount_mark(iter_info)))
                return 0;
@@ -262,7 +277,8 @@ static int fsnotify_handle_event(struct fsnotify_group *group, __u32 mask,
                name = NULL;
        }
 
-       ret = ops->handle_inode_event(inode_mark, mask, inode, dir, name);
+       ret = fsnotify_handle_inode_event(group, inode_mark, mask, data, data_type,
+                                         dir, name, cookie);
        if (ret || !child_mark)
                return ret;
 
@@ -272,7 +288,8 @@ static int fsnotify_handle_event(struct fsnotify_group *group, __u32 mask,
         * report the event once to parent dir with name and once to child
         * without name.
         */
-       return ops->handle_inode_event(child_mark, mask, inode, NULL, NULL);
+       return fsnotify_handle_inode_event(group, child_mark, mask, data, data_type,
+                                          NULL, NULL, 0);
 }
 
 static int send_to_group(__u32 mask, const void *data, int data_type,
index f8529a3a29234b0a1753c0e5f01d0e3ba0bc1594..4ee3044eedd06b8c3816429b566bc2b95f90064c 100644 (file)
@@ -137,6 +137,7 @@ struct mem_cgroup;
  *             if @file_name is not NULL, this is the directory that
  *             @file_name is relative to.
  * @file_name: optional file name associated with event
+ * @cookie:    inotify rename cookie
  *
  * free_group_priv - called when a group refcnt hits 0 to clean up the private union
  * freeing_mark - called when a mark is being destroyed for some reason.  The group
@@ -151,7 +152,7 @@ struct fsnotify_ops {
                            struct fsnotify_iter_info *iter_info);
        int (*handle_inode_event)(struct fsnotify_mark *mark, u32 mask,
                            struct inode *inode, struct inode *dir,
-                           const struct qstr *file_name);
+                           const struct qstr *file_name, u32 cookie);
        void (*free_group_priv)(struct fsnotify_group *group);
        void (*freeing_mark)(struct fsnotify_mark *mark, struct fsnotify_group *group);
        void (*free_event)(struct fsnotify_event *event);
index bfcfcd61adb64aa5ed55a66a19b5b5754de30966..5b3f01da172bce578d00acbbfcb35fca5a26c9dc 100644 (file)
@@ -154,7 +154,7 @@ static void audit_autoremove_mark_rule(struct audit_fsnotify_mark *audit_mark)
 /* Update mark data in audit rules based on fsnotify events. */
 static int audit_mark_handle_event(struct fsnotify_mark *inode_mark, u32 mask,
                                   struct inode *inode, struct inode *dir,
-                                  const struct qstr *dname)
+                                  const struct qstr *dname, u32 cookie)
 {
        struct audit_fsnotify_mark *audit_mark;
 
index 83e1c07fc99e1e838e781e5245d7778d323c9812..6c91902f4f455a0d83257883712d89b5f7a91f15 100644 (file)
@@ -1037,7 +1037,7 @@ static void evict_chunk(struct audit_chunk *chunk)
 
 static int audit_tree_handle_event(struct fsnotify_mark *mark, u32 mask,
                                   struct inode *inode, struct inode *dir,
-                                  const struct qstr *file_name)
+                                  const struct qstr *file_name, u32 cookie)
 {
        return 0;
 }
index 246e5ba704c00652bc9dc421303c0c8774036004..2acf7ca4915421f71199554b4d638a8b4c714de8 100644 (file)
@@ -466,7 +466,7 @@ void audit_remove_watch_rule(struct audit_krule *krule)
 /* Update watch data in audit rules based on fsnotify events. */
 static int audit_watch_handle_event(struct fsnotify_mark *inode_mark, u32 mask,
                                    struct inode *inode, struct inode *dir,
-                                   const struct qstr *dname)
+                                   const struct qstr *dname, u32 cookie)
 {
        struct audit_parent *parent;