summaryrefslogtreecommitdiffstats
path: root/fs/notify/fsnotify.c
diff options
context:
space:
mode:
authorAmir Goldstein <amir73il@gmail.com>2020-12-02 14:07:07 +0200
committerJan Kara <jack@suse.cz>2020-12-03 14:58:35 +0100
commit950cc0d2bef078e1f6459900ca4d4b2a2e0e3c37 (patch)
treebf5632aebfd01ec14639eff7755999ea1cfd3d9a /fs/notify/fsnotify.c
parent92890123749bafc317bbfacbe0a62ce08d78efb7 (diff)
downloadlinux-950cc0d2bef078e1f6459900ca4d4b2a2e0e3c37.tar.bz2
fsnotify: generalize handle_inode_event()
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>
Diffstat (limited to 'fs/notify/fsnotify.c')
-rw-r--r--fs/notify/fsnotify.c31
1 files changed, 24 insertions, 7 deletions
diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c
index 8d3ad5ef2925..c5c68bcbaadf 100644
--- a/fs/notify/fsnotify.c
+++ b/fs/notify/fsnotify.c
@@ -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,