2021-07-20 16:12:22

by Gabriel Krisman Bertazi

[permalink] [raw]
Subject: [PATCH v4 08/16] fsnotify: pass arguments of fsnotify() in struct fsnotify_event_info

From: Amir Goldstein <[email protected]>

There are a lot of arguments to fsnotify() and the handle_event() method.
Pass them in a const struct instead of on the argument list.

Apart from being more tidy, this helps with passing error reports to the
backend. __fsnotify_parent() argument list was intentionally left
untouched, because its argument list is still short enough and because
most of the event info arguments are initialized inside
__fsnotify_parent().

Signed-off-by: Amir Goldstein <[email protected]>
[ Fix kernelbot warnings]
[avoid __fsnotify version when not needed]
Signed-off-by: Gabriel Krisman Bertazi <[email protected]>
---
fs/notify/fanotify/fanotify.c | 59 ++++++++++++--------------
fs/notify/fsnotify.c | 73 +++++++++++++++++---------------
include/linux/fsnotify_backend.h | 73 +++++++++++++++++++++++---------
3 files changed, 120 insertions(+), 85 deletions(-)

diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c
index c3eefe3f6494..6875d4d34c0c 100644
--- a/fs/notify/fanotify/fanotify.c
+++ b/fs/notify/fanotify/fanotify.c
@@ -253,21 +253,22 @@ static int fanotify_get_response(struct fsnotify_group *group,
* been included within the event mask, but have not been explicitly
* requested by the user, will not be present in the returned mask.
*/
-static u32 fanotify_group_event_mask(struct fsnotify_group *group,
- struct fsnotify_iter_info *iter_info,
- u32 event_mask, const void *data,
- int data_type, struct inode *dir)
+static u32 fanotify_group_event_mask(
+ struct fsnotify_group *group, u32 event_mask,
+ const struct fsnotify_event_info *event_info,
+ struct fsnotify_iter_info *iter_info)
{
__u32 marks_mask = 0, marks_ignored_mask = 0;
__u32 test_mask, user_mask = FANOTIFY_OUTGOING_EVENTS |
FANOTIFY_EVENT_FLAGS;
- const struct path *path = fsnotify_data_path(data, data_type);
+ const struct path *path = fsnotify_event_info_path(event_info);
unsigned int fid_mode = FAN_GROUP_FLAG(group, FANOTIFY_FID_BITS);
struct fsnotify_mark *mark;
int type;

pr_debug("%s: report_mask=%x mask=%x data=%p data_type=%d\n",
- __func__, iter_info->report_mask, event_mask, data, data_type);
+ __func__, iter_info->report_mask, event_mask,
+ event_info->data, event_info->data_type);

if (!fid_mode) {
/* Do we have path to open a file descriptor? */
@@ -278,7 +279,7 @@ static u32 fanotify_group_event_mask(struct fsnotify_group *group,
return 0;
} else if (!(fid_mode & FAN_REPORT_FID)) {
/* Do we have a directory inode to report? */
- if (!dir && !(event_mask & FS_ISDIR))
+ if (!event_info->dir && !(event_mask & FS_ISDIR))
return 0;
}

@@ -427,13 +428,13 @@ static int fanotify_encode_fh(struct fanotify_fh *fh, struct inode *inode,
* FS_ATTRIB reports the child inode even if reported on a watched parent.
* FS_CREATE reports the modified dir inode and not the created inode.
*/
-static struct inode *fanotify_fid_inode(u32 event_mask, const void *data,
- int data_type, struct inode *dir)
+static struct inode *fanotify_fid_inode(u32 event_mask,
+ const struct fsnotify_event_info *event_info)
{
if (event_mask & ALL_FSNOTIFY_DIRENT_EVENTS)
- return dir;
+ return event_info->dir;

- return fsnotify_data_inode(data, data_type);
+ return fsnotify_event_info_inode(event_info);
}

/*
@@ -444,18 +445,18 @@ static struct inode *fanotify_fid_inode(u32 event_mask, const void *data,
* reported to parent.
* Otherwise, do not report dir fid.
*/
-static struct inode *fanotify_dfid_inode(u32 event_mask, const void *data,
- int data_type, struct inode *dir)
+static struct inode *fanotify_dfid_inode(u32 event_mask,
+ const struct fsnotify_event_info *event_info)
{
- struct inode *inode = fsnotify_data_inode(data, data_type);
+ struct inode *inode = fsnotify_event_info_inode(event_info);

if (event_mask & ALL_FSNOTIFY_DIRENT_EVENTS)
- return dir;
+ return event_info->dir;

if (S_ISDIR(inode->i_mode))
return inode;

- return dir;
+ return event_info->dir;
}

static struct fanotify_event *fanotify_alloc_path_event(const struct path *path,
@@ -563,17 +564,17 @@ static struct fanotify_event *fanotify_alloc_name_event(struct inode *id,
return &fne->fae;
}

-static struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group,
- u32 mask, const void *data,
- int data_type, struct inode *dir,
- const struct qstr *file_name,
- __kernel_fsid_t *fsid)
+static struct fanotify_event *fanotify_alloc_event(
+ struct fsnotify_group *group, u32 mask,
+ const struct fsnotify_event_info *event_info,
+ __kernel_fsid_t *fsid)
{
struct fanotify_event *event = NULL;
gfp_t gfp = GFP_KERNEL_ACCOUNT;
- struct inode *id = fanotify_fid_inode(mask, data, data_type, dir);
- struct inode *dirid = fanotify_dfid_inode(mask, data, data_type, dir);
- const struct path *path = fsnotify_data_path(data, data_type);
+ struct inode *id = fanotify_fid_inode(mask, event_info);
+ struct inode *dirid = fanotify_dfid_inode(mask, event_info);
+ const struct path *path = fsnotify_event_info_path(event_info);
+ const struct qstr *file_name = event_info->name;
unsigned int fid_mode = FAN_GROUP_FLAG(group, FANOTIFY_FID_BITS);
struct mem_cgroup *old_memcg;
struct inode *child = NULL;
@@ -712,9 +713,7 @@ static void fanotify_insert_event(struct fsnotify_group *group,
}

static int fanotify_handle_event(struct fsnotify_group *group, u32 mask,
- const void *data, int data_type,
- struct inode *dir,
- const struct qstr *file_name, u32 cookie,
+ const struct fsnotify_event_info *event_info,
struct fsnotify_iter_info *iter_info)
{
int ret = 0;
@@ -744,8 +743,7 @@ static int fanotify_handle_event(struct fsnotify_group *group, u32 mask,

BUILD_BUG_ON(HWEIGHT32(ALL_FANOTIFY_EVENT_BITS) != 19);

- mask = fanotify_group_event_mask(group, iter_info, mask, data,
- data_type, dir);
+ mask = fanotify_group_event_mask(group, mask, event_info, iter_info);
if (!mask)
return 0;

@@ -767,8 +765,7 @@ static int fanotify_handle_event(struct fsnotify_group *group, u32 mask,
return 0;
}

- event = fanotify_alloc_event(group, mask, data, data_type, dir,
- file_name, &fsid);
+ event = fanotify_alloc_event(group, mask, event_info, &fsid);
ret = -ENOMEM;
if (unlikely(!event)) {
/*
diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c
index 30d422b8c0fc..7c783c9df1dd 100644
--- a/fs/notify/fsnotify.c
+++ b/fs/notify/fsnotify.c
@@ -240,13 +240,11 @@ int __fsnotify_parent(struct dentry *dentry, __u32 mask, const void *data,
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)
+ struct fsnotify_mark *inode_mark, u32 mask,
+ const struct fsnotify_event_info *event_info)
{
- const struct path *path = fsnotify_data_path(data, data_type);
- struct inode *inode = fsnotify_data_inode(data, data_type);
+ const struct path *path = fsnotify_event_info_path(event_info);
+ struct inode *inode = fsnotify_event_info_inode(event_info);
const struct fsnotify_ops *ops = group->ops;

if (WARN_ON_ONCE(!ops->handle_inode_event))
@@ -260,16 +258,17 @@ static int fsnotify_handle_inode_event(struct fsnotify_group *group,
if (!(mask & inode_mark->mask & ALL_FSNOTIFY_EVENTS))
return 0;

- return ops->handle_inode_event(inode_mark, mask, inode, dir, name, cookie);
+ return ops->handle_inode_event(inode_mark, mask, inode, event_info->dir,
+ event_info->name, event_info->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,
- u32 cookie, struct fsnotify_iter_info *iter_info)
+ const struct fsnotify_event_info *event_info,
+ struct fsnotify_iter_info *iter_info)
{
struct fsnotify_mark *inode_mark = fsnotify_iter_inode_mark(iter_info);
struct fsnotify_mark *parent_mark = fsnotify_iter_parent_mark(iter_info);
+ struct fsnotify_event_info child_event_info;
int ret;

if (WARN_ON_ONCE(fsnotify_iter_sb_mark(iter_info)) ||
@@ -284,8 +283,8 @@ static int fsnotify_handle_event(struct fsnotify_group *group, __u32 mask,
* interested in this event?
*/
if (parent_mark->mask & FS_EVENT_ON_CHILD) {
- ret = fsnotify_handle_inode_event(group, parent_mark, mask,
- data, data_type, dir, name, 0);
+ ret = fsnotify_handle_inode_event(group, parent_mark,
+ mask, event_info);
if (ret)
return ret;
}
@@ -302,18 +301,22 @@ static int fsnotify_handle_event(struct fsnotify_group *group, __u32 mask,
* The child watcher is expecting an event without a file name
* and without the FS_EVENT_ON_CHILD flag.
*/
+ if (WARN_ON_ONCE(!event_info->inode))
+ return 0;
+
mask &= ~FS_EVENT_ON_CHILD;
- dir = NULL;
- name = NULL;
+ child_event_info = *event_info;
+ child_event_info.dir = NULL;
+ child_event_info.name = NULL;
+ event_info = &child_event_info;
}

- return fsnotify_handle_inode_event(group, inode_mark, mask, data, data_type,
- dir, name, cookie);
+ return fsnotify_handle_inode_event(group, inode_mark, mask, event_info);
}

-static int send_to_group(__u32 mask, const void *data, int data_type,
- struct inode *dir, const struct qstr *file_name,
- u32 cookie, struct fsnotify_iter_info *iter_info)
+static int send_to_group(__u32 mask,
+ const struct fsnotify_event_info *event_info,
+ struct fsnotify_iter_info *iter_info)
{
struct fsnotify_group *group = NULL;
__u32 test_mask = (mask & ALL_FSNOTIFY_EVENTS);
@@ -351,18 +354,18 @@ static int send_to_group(__u32 mask, const void *data, int data_type,

pr_debug("%s: group=%p mask=%x marks_mask=%x marks_ignored_mask=%x data=%p data_type=%d dir=%p cookie=%d\n",
__func__, group, mask, marks_mask, marks_ignored_mask,
- data, data_type, dir, cookie);
+ event_info->data, event_info->data_type, event_info->dir,
+ event_info->cookie);

if (!(test_mask & marks_mask & ~marks_ignored_mask))
return 0;

if (group->ops->handle_event) {
- return group->ops->handle_event(group, mask, data, data_type, dir,
- file_name, cookie, iter_info);
+ return group->ops->handle_event(group, mask, event_info,
+ iter_info);
}

- return fsnotify_handle_event(group, mask, data, data_type, dir,
- file_name, cookie, iter_info);
+ return fsnotify_handle_event(group, mask, event_info, iter_info);
}

static struct fsnotify_mark *fsnotify_first_mark(struct fsnotify_mark_connector **connp)
@@ -448,21 +451,22 @@ static void fsnotify_iter_next(struct fsnotify_iter_info *iter_info)
* in whatever means they feel necessary.
*
* @mask: event type and flags
+ * Input args in struct fsnotify_event_info:
* @data: object that event happened on
* @data_type: type of object for fanotify_data_XXX() accessors
* @dir: optional directory associated with event -
- * if @file_name is not NULL, this is the directory that
- * @file_name is relative to
- * @file_name: optional file name associated with event
+ * if @name is not NULL, this is the directory that
+ * @name is relative to
+ * @name: optional file name associated with event
* @inode: optional inode associated with event -
* either @dir or @inode must be non-NULL.
* if both are non-NULL event may be reported to both.
* @cookie: inotify rename cookie
*/
-int fsnotify(__u32 mask, const void *data, int data_type, struct inode *dir,
- const struct qstr *file_name, struct inode *inode, u32 cookie)
+int __fsnotify(__u32 mask, const struct fsnotify_event_info *event_info)
{
- const struct path *path = fsnotify_data_path(data, data_type);
+ const struct path *path = fsnotify_event_info_path(event_info);
+ struct inode *inode = event_info->inode;
struct fsnotify_iter_info iter_info = {};
struct super_block *sb;
struct mount *mnt = NULL;
@@ -475,13 +479,13 @@ int fsnotify(__u32 mask, const void *data, int data_type, struct inode *dir,

if (!inode) {
/* Dirent event - report on TYPE_INODE to dir */
- inode = dir;
+ inode = event_info->dir;
} else if (mask & FS_EVENT_ON_CHILD) {
/*
* Event on child - report on TYPE_PARENT to dir if it is
* watching children and on TYPE_INODE to child.
*/
- parent = dir;
+ parent = event_info->dir;
}
sb = inode->i_sb;

@@ -538,8 +542,7 @@ int fsnotify(__u32 mask, const void *data, int data_type, struct inode *dir,
* That's why this traversal is so complicated...
*/
while (fsnotify_iter_select_report_types(&iter_info)) {
- ret = send_to_group(mask, data, data_type, dir, file_name,
- cookie, &iter_info);
+ ret = send_to_group(mask, event_info, &iter_info);

if (ret && (mask & ALL_FSNOTIFY_PERM_EVENTS))
goto out;
@@ -552,7 +555,7 @@ int fsnotify(__u32 mask, const void *data, int data_type, struct inode *dir,

return ret;
}
-EXPORT_SYMBOL_GPL(fsnotify);
+EXPORT_SYMBOL_GPL(__fsnotify);

static __init int fsnotify_init(void)
{
diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h
index 2b5fb9327a77..3c6fb43276ba 100644
--- a/include/linux/fsnotify_backend.h
+++ b/include/linux/fsnotify_backend.h
@@ -112,6 +112,28 @@ struct fsnotify_iter_info;

struct mem_cgroup;

+/*
+ * Event info args passed to fsnotify() and to backends on handle_event():
+ * @data: object that event happened on
+ * @data_type: type of object for fanotify_data_XXX() accessors
+ * @dir: optional directory associated with event -
+ * if @name is not NULL, this is the directory that
+ * @name is relative to
+ * @name: optional file name associated with event
+ * @inode: optional inode associated with event -
+ * either @dir or @inode must be non-NULL.
+ * if both are non-NULL event may be reported to both.
+ * @cookie: inotify rename cookie
+ */
+struct fsnotify_event_info {
+ const void *data;
+ int data_type;
+ struct inode *dir;
+ const struct qstr *name;
+ struct inode *inode;
+ u32 cookie;
+};
+
/*
* Each group much define these ops. The fsnotify infrastructure will call
* these operations for each relevant group.
@@ -119,13 +141,7 @@ struct mem_cgroup;
* handle_event - main call for a group to handle an fs event
* @group: group to notify
* @mask: event type and flags
- * @data: object that event happened on
- * @data_type: type of object for fanotify_data_XXX() accessors
- * @dir: optional directory associated with event -
- * 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
+ * @event_info: information attached to the event
* @iter_info: array of marks from this group that are interested in the event
*
* handle_inode_event - simple variant of handle_event() for groups that only
@@ -147,8 +163,7 @@ struct mem_cgroup;
*/
struct fsnotify_ops {
int (*handle_event)(struct fsnotify_group *group, u32 mask,
- const void *data, int data_type, struct inode *dir,
- const struct qstr *file_name, u32 cookie,
+ const struct fsnotify_event_info *event_info,
struct fsnotify_iter_info *iter_info);
int (*handle_inode_event)(struct fsnotify_mark *mark, u32 mask,
struct inode *inode, struct inode *dir,
@@ -262,6 +277,12 @@ static inline struct inode *fsnotify_data_inode(const void *data, int data_type)
}
}

+static inline struct inode *fsnotify_event_info_inode(
+ const struct fsnotify_event_info *event_info)
+{
+ return fsnotify_data_inode(event_info->data, event_info->data_type);
+}
+
static inline const struct path *fsnotify_data_path(const void *data,
int data_type)
{
@@ -273,6 +294,12 @@ static inline const struct path *fsnotify_data_path(const void *data,
}
}

+static inline const struct path *fsnotify_event_info_path(
+ const struct fsnotify_event_info *event_info)
+{
+ return fsnotify_data_path(event_info->data, event_info->data_type);
+}
+
enum fsnotify_obj_type {
FSNOTIFY_OBJ_TYPE_INODE,
FSNOTIFY_OBJ_TYPE_PARENT,
@@ -422,11 +449,11 @@ struct fsnotify_mark {
/* called from the vfs helpers */

/* main fsnotify call to send events */
-extern int fsnotify(__u32 mask, const void *data, int data_type,
- struct inode *dir, const struct qstr *name,
- struct inode *inode, u32 cookie);
-extern int __fsnotify_parent(struct dentry *dentry, __u32 mask, const void *data,
- int data_type);
+extern int __fsnotify(__u32 mask,
+ const struct fsnotify_event_info *event_info);
+extern int __fsnotify_parent(struct dentry *dentry, __u32 mask,
+ const void *data, int data_type);
+
extern void __fsnotify_inode_delete(struct inode *inode);
extern void __fsnotify_vfsmount_delete(struct vfsmount *mnt);
extern void fsnotify_sb_delete(struct super_block *sb);
@@ -605,16 +632,14 @@ static inline void fsnotify_init_event(struct fsnotify_event *event)
}

#else
-
-static inline int fsnotify(__u32 mask, const void *data, int data_type,
- struct inode *dir, const struct qstr *name,
- struct inode *inode, u32 cookie)
+static inline int __fsnotify(__u32 mask,
+ const struct fsnotify_event_info *event_info)
{
return 0;
}

static inline int __fsnotify_parent(struct dentry *dentry, __u32 mask,
- const void *data, int data_type)
+ const void *data, int data_type)
{
return 0;
}
@@ -641,6 +666,16 @@ static inline void fsnotify_unmount_inodes(struct super_block *sb)

#endif /* CONFIG_FSNOTIFY */

+static inline int fsnotify(__u32 mask, const void *data, int data_type,
+ struct inode *dir, const struct qstr *name,
+ struct inode *inode, u32 cookie)
+{
+ return __fsnotify(mask, &(struct fsnotify_event_info) {
+ .data = (data), .data_type = (data_type), .dir = (dir),
+ .name = (name), .inode = (inode), .cookie = (cookie)
+ });
+}
+
#endif /* __KERNEL __ */

#endif /* __LINUX_FSNOTIFY_BACKEND_H */
--
2.32.0