Commit b54cecf5 authored by Amir Goldstein's avatar Amir Goldstein Committed by Jan Kara

fsnotify: pass dir argument to handle_event() callback

The 'inode' argument to handle_event(), sometimes referred to as
'to_tell' is somewhat obsolete.
It is a remnant from the times when a group could only have an inode mark
associated with an event.

We now pass an iter_info array to the callback, with all marks associated
with an event.

Most backends ignore this argument, with two exceptions:
1. dnotify uses it for sanity check that event is on directory
2. fanotify uses it to report fid of directory on directory entry
   modification events

Remove the 'inode' argument and add a 'dir' argument.
The callback function signature is deliberately changed, because
the meaning of the argument has changed and the arguments have
been documented.

The 'dir' argument is set to when 'file_name' is specified and it is
referring to the directory that the 'file_name' entry belongs to.
Signed-off-by: default avatarAmir Goldstein <amir73il@gmail.com>
Signed-off-by: default avatarJan Kara <jack@suse.cz>
parent 9c61f3b5
...@@ -598,9 +598,9 @@ static struct notifier_block nfsd_file_lease_notifier = { ...@@ -598,9 +598,9 @@ static struct notifier_block nfsd_file_lease_notifier = {
}; };
static int static int
nfsd_file_fsnotify_handle_event(struct fsnotify_group *group, nfsd_file_fsnotify_handle_event(struct fsnotify_group *group, u32 mask,
struct inode *to_tell, const void *data, int data_type,
u32 mask, const void *data, int data_type, struct inode *dir,
const struct qstr *file_name, u32 cookie, const struct qstr *file_name, u32 cookie,
struct fsnotify_iter_info *iter_info) struct fsnotify_iter_info *iter_info)
{ {
......
...@@ -70,9 +70,9 @@ static void dnotify_recalc_inode_mask(struct fsnotify_mark *fsn_mark) ...@@ -70,9 +70,9 @@ static void dnotify_recalc_inode_mask(struct fsnotify_mark *fsn_mark)
* destroy the dnotify struct if it was not registered to receive multiple * destroy the dnotify struct if it was not registered to receive multiple
* events. * events.
*/ */
static int dnotify_handle_event(struct fsnotify_group *group, static int dnotify_handle_event(struct fsnotify_group *group, u32 mask,
struct inode *inode, const void *data, int data_type,
u32 mask, const void *data, int data_type, struct inode *dir,
const struct qstr *file_name, u32 cookie, const struct qstr *file_name, u32 cookie,
struct fsnotify_iter_info *iter_info) struct fsnotify_iter_info *iter_info)
{ {
...@@ -84,7 +84,7 @@ static int dnotify_handle_event(struct fsnotify_group *group, ...@@ -84,7 +84,7 @@ static int dnotify_handle_event(struct fsnotify_group *group,
__u32 test_mask = mask & ~FS_EVENT_ON_CHILD; __u32 test_mask = mask & ~FS_EVENT_ON_CHILD;
/* not a dir, dnotify doesn't care */ /* not a dir, dnotify doesn't care */
if (!S_ISDIR(inode->i_mode)) if (!dir && !(mask & FS_ISDIR))
return 0; return 0;
if (WARN_ON(fsnotify_iter_vfsmount_mark(iter_info))) if (WARN_ON(fsnotify_iter_vfsmount_mark(iter_info)))
......
...@@ -335,11 +335,11 @@ static void fanotify_encode_fh(struct fanotify_fh *fh, struct inode *inode, ...@@ -335,11 +335,11 @@ static void fanotify_encode_fh(struct fanotify_fh *fh, struct inode *inode,
* FS_ATTRIB reports the child inode even if reported on a watched parent. * 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. * FS_CREATE reports the modified dir inode and not the created inode.
*/ */
static struct inode *fanotify_fid_inode(struct inode *to_tell, u32 event_mask, static struct inode *fanotify_fid_inode(u32 event_mask, const void *data,
const void *data, int data_type) int data_type, struct inode *dir)
{ {
if (event_mask & ALL_FSNOTIFY_DIRENT_EVENTS) if (event_mask & ALL_FSNOTIFY_DIRENT_EVENTS)
return to_tell; return dir;
return fsnotify_data_inode(data, data_type); return fsnotify_data_inode(data, data_type);
} }
...@@ -416,14 +416,14 @@ static struct fanotify_event *fanotify_alloc_name_event(struct inode *id, ...@@ -416,14 +416,14 @@ static struct fanotify_event *fanotify_alloc_name_event(struct inode *id,
} }
static struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group, static struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group,
struct inode *inode, u32 mask, u32 mask, const void *data,
const void *data, int data_type, int data_type, struct inode *dir,
const struct qstr *file_name, const struct qstr *file_name,
__kernel_fsid_t *fsid) __kernel_fsid_t *fsid)
{ {
struct fanotify_event *event = NULL; struct fanotify_event *event = NULL;
gfp_t gfp = GFP_KERNEL_ACCOUNT; gfp_t gfp = GFP_KERNEL_ACCOUNT;
struct inode *id = fanotify_fid_inode(inode, mask, data, data_type); struct inode *id = fanotify_fid_inode(mask, data, data_type, dir);
const struct path *path = fsnotify_data_path(data, data_type); const struct path *path = fsnotify_data_path(data, data_type);
/* /*
...@@ -507,9 +507,9 @@ static __kernel_fsid_t fanotify_get_fsid(struct fsnotify_iter_info *iter_info) ...@@ -507,9 +507,9 @@ static __kernel_fsid_t fanotify_get_fsid(struct fsnotify_iter_info *iter_info)
return fsid; return fsid;
} }
static int fanotify_handle_event(struct fsnotify_group *group, static int fanotify_handle_event(struct fsnotify_group *group, u32 mask,
struct inode *inode, const void *data, int data_type,
u32 mask, const void *data, int data_type, struct inode *dir,
const struct qstr *file_name, u32 cookie, const struct qstr *file_name, u32 cookie,
struct fsnotify_iter_info *iter_info) struct fsnotify_iter_info *iter_info)
{ {
...@@ -546,8 +546,7 @@ static int fanotify_handle_event(struct fsnotify_group *group, ...@@ -546,8 +546,7 @@ static int fanotify_handle_event(struct fsnotify_group *group,
if (!mask) if (!mask)
return 0; return 0;
pr_debug("%s: group=%p inode=%p mask=%x\n", __func__, group, inode, pr_debug("%s: group=%p mask=%x\n", __func__, group, mask);
mask);
if (fanotify_is_perm_event(mask)) { if (fanotify_is_perm_event(mask)) {
/* /*
...@@ -565,7 +564,7 @@ static int fanotify_handle_event(struct fsnotify_group *group, ...@@ -565,7 +564,7 @@ static int fanotify_handle_event(struct fsnotify_group *group,
return 0; return 0;
} }
event = fanotify_alloc_event(group, inode, mask, data, data_type, event = fanotify_alloc_event(group, mask, data, data_type, dir,
file_name, &fsid); file_name, &fsid);
ret = -ENOMEM; ret = -ENOMEM;
if (unlikely(!event)) { if (unlikely(!event)) {
......
...@@ -185,11 +185,9 @@ int __fsnotify_parent(struct dentry *dentry, __u32 mask, const void *data, ...@@ -185,11 +185,9 @@ int __fsnotify_parent(struct dentry *dentry, __u32 mask, const void *data,
} }
EXPORT_SYMBOL_GPL(__fsnotify_parent); EXPORT_SYMBOL_GPL(__fsnotify_parent);
static int send_to_group(struct inode *to_tell, static int send_to_group(__u32 mask, const void *data, int data_type,
__u32 mask, const void *data, struct inode *dir, const struct qstr *file_name,
int data_is, u32 cookie, u32 cookie, struct fsnotify_iter_info *iter_info)
const struct qstr *file_name,
struct fsnotify_iter_info *iter_info)
{ {
struct fsnotify_group *group = NULL; struct fsnotify_group *group = NULL;
__u32 test_mask = (mask & ALL_FSNOTIFY_EVENTS); __u32 test_mask = (mask & ALL_FSNOTIFY_EVENTS);
...@@ -225,15 +223,14 @@ static int send_to_group(struct inode *to_tell, ...@@ -225,15 +223,14 @@ static int send_to_group(struct inode *to_tell,
} }
} }
pr_debug("%s: group=%p to_tell=%p mask=%x marks_mask=%x marks_ignored_mask=%x" pr_debug("%s: group=%p mask=%x marks_mask=%x marks_ignored_mask=%x data=%p data_type=%d dir=%p cookie=%d\n",
" data=%p data_is=%d cookie=%d\n", __func__, group, mask, marks_mask, marks_ignored_mask,
__func__, group, to_tell, mask, marks_mask, marks_ignored_mask, data, data_type, dir, cookie);
data, data_is, cookie);
if (!(test_mask & marks_mask & ~marks_ignored_mask)) if (!(test_mask & marks_mask & ~marks_ignored_mask))
return 0; return 0;
return group->ops->handle_event(group, to_tell, mask, data, data_is, return group->ops->handle_event(group, mask, data, data_type, dir,
file_name, cookie, iter_info); file_name, cookie, iter_info);
} }
...@@ -317,12 +314,13 @@ static void fsnotify_iter_next(struct fsnotify_iter_info *iter_info) ...@@ -317,12 +314,13 @@ static void fsnotify_iter_next(struct fsnotify_iter_info *iter_info)
* out to all of the registered fsnotify_group. Those groups can then use the * out to all of the registered fsnotify_group. Those groups can then use the
* notification event in whatever means they feel necessary. * notification event in whatever means they feel necessary.
*/ */
int fsnotify(struct inode *to_tell, __u32 mask, const void *data, int data_is, int fsnotify(struct inode *to_tell, __u32 mask, const void *data, int data_type,
const struct qstr *file_name, u32 cookie) const struct qstr *file_name, u32 cookie)
{ {
const struct path *path = fsnotify_data_path(data, data_is); const struct path *path = fsnotify_data_path(data, data_type);
struct fsnotify_iter_info iter_info = {}; struct fsnotify_iter_info iter_info = {};
struct super_block *sb = to_tell->i_sb; struct super_block *sb = to_tell->i_sb;
struct inode *dir = file_name ? to_tell : NULL;
struct mount *mnt = NULL; struct mount *mnt = NULL;
int ret = 0; int ret = 0;
__u32 test_mask, marks_mask; __u32 test_mask, marks_mask;
...@@ -375,8 +373,8 @@ int fsnotify(struct inode *to_tell, __u32 mask, const void *data, int data_is, ...@@ -375,8 +373,8 @@ int fsnotify(struct inode *to_tell, __u32 mask, const void *data, int data_is,
* That's why this traversal is so complicated... * That's why this traversal is so complicated...
*/ */
while (fsnotify_iter_select_report_types(&iter_info)) { while (fsnotify_iter_select_report_types(&iter_info)) {
ret = send_to_group(to_tell, mask, data, data_is, cookie, ret = send_to_group(mask, data, data_type, dir, file_name,
file_name, &iter_info); cookie, &iter_info);
if (ret && (mask & ALL_FSNOTIFY_PERM_EVENTS)) if (ret && (mask & ALL_FSNOTIFY_PERM_EVENTS))
goto out; goto out;
......
...@@ -24,9 +24,9 @@ static inline struct inotify_event_info *INOTIFY_E(struct fsnotify_event *fse) ...@@ -24,9 +24,9 @@ static inline struct inotify_event_info *INOTIFY_E(struct fsnotify_event *fse)
extern void inotify_ignored_and_remove_idr(struct fsnotify_mark *fsn_mark, extern void inotify_ignored_and_remove_idr(struct fsnotify_mark *fsn_mark,
struct fsnotify_group *group); struct fsnotify_group *group);
extern int inotify_handle_event(struct fsnotify_group *group, extern int inotify_handle_event(struct fsnotify_group *group, u32 mask,
struct inode *inode, const void *data, int data_type,
u32 mask, const void *data, int data_type, struct inode *dir,
const struct qstr *file_name, u32 cookie, const struct qstr *file_name, u32 cookie,
struct fsnotify_iter_info *iter_info); struct fsnotify_iter_info *iter_info);
......
...@@ -55,9 +55,8 @@ static int inotify_merge(struct list_head *list, ...@@ -55,9 +55,8 @@ static int inotify_merge(struct list_head *list,
return event_compare(last_event, event); return event_compare(last_event, event);
} }
int inotify_handle_event(struct fsnotify_group *group, int inotify_handle_event(struct fsnotify_group *group, u32 mask,
struct inode *inode, const void *data, int data_type, struct inode *dir,
u32 mask, const void *data, int data_type,
const struct qstr *file_name, u32 cookie, const struct qstr *file_name, u32 cookie,
struct fsnotify_iter_info *iter_info) struct fsnotify_iter_info *iter_info)
{ {
...@@ -82,7 +81,7 @@ int inotify_handle_event(struct fsnotify_group *group, ...@@ -82,7 +81,7 @@ int inotify_handle_event(struct fsnotify_group *group,
alloc_len += len + 1; alloc_len += len + 1;
} }
pr_debug("%s: group=%p inode=%p mask=%x\n", __func__, group, inode, pr_debug("%s: group=%p mark=%p mask=%x\n", __func__, group, inode_mark,
mask); mask);
i_mark = container_of(inode_mark, struct inotify_inode_mark, i_mark = container_of(inode_mark, struct inotify_inode_mark,
......
...@@ -490,8 +490,8 @@ void inotify_ignored_and_remove_idr(struct fsnotify_mark *fsn_mark, ...@@ -490,8 +490,8 @@ void inotify_ignored_and_remove_idr(struct fsnotify_mark *fsn_mark,
fsn_mark); fsn_mark);
/* Queue ignore event for the watch */ /* Queue ignore event for the watch */
inotify_handle_event(group, NULL, FS_IN_IGNORED, NULL, inotify_handle_event(group, FS_IN_IGNORED, NULL, FSNOTIFY_EVENT_NONE,
FSNOTIFY_EVENT_NONE, NULL, 0, &iter_info); NULL, NULL, 0, &iter_info);
i_mark = container_of(fsn_mark, struct inotify_inode_mark, fsn_mark); i_mark = container_of(fsn_mark, struct inotify_inode_mark, fsn_mark);
/* remove this mark from the idr */ /* remove this mark from the idr */
......
...@@ -108,6 +108,17 @@ struct mem_cgroup; ...@@ -108,6 +108,17 @@ struct mem_cgroup;
* these operations for each relevant group. * these operations for each relevant group.
* *
* handle_event - main call for a group to handle an fs event * 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
* @iter_info: array of marks from this group that are interested in the event
*
* free_group_priv - called when a group refcnt hits 0 to clean up the private union * 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 * freeing_mark - called when a mark is being destroyed for some reason. The group
* MUST be holding a reference on each mark and that reference must be * MUST be holding a reference on each mark and that reference must be
...@@ -115,9 +126,8 @@ struct mem_cgroup; ...@@ -115,9 +126,8 @@ struct mem_cgroup;
* userspace messages that marks have been removed. * userspace messages that marks have been removed.
*/ */
struct fsnotify_ops { struct fsnotify_ops {
int (*handle_event)(struct fsnotify_group *group, int (*handle_event)(struct fsnotify_group *group, u32 mask,
struct inode *inode, const void *data, int data_type, struct inode *dir,
u32 mask, const void *data, int data_type,
const struct qstr *file_name, u32 cookie, const struct qstr *file_name, u32 cookie,
struct fsnotify_iter_info *iter_info); struct fsnotify_iter_info *iter_info);
void (*free_group_priv)(struct fsnotify_group *group); void (*free_group_priv)(struct fsnotify_group *group);
......
...@@ -152,11 +152,11 @@ static void audit_autoremove_mark_rule(struct audit_fsnotify_mark *audit_mark) ...@@ -152,11 +152,11 @@ static void audit_autoremove_mark_rule(struct audit_fsnotify_mark *audit_mark)
} }
/* Update mark data in audit rules based on fsnotify events. */ /* Update mark data in audit rules based on fsnotify events. */
static int audit_mark_handle_event(struct fsnotify_group *group, static int audit_mark_handle_event(struct fsnotify_group *group, u32 mask,
struct inode *to_tell, const void *data, int data_type,
u32 mask, const void *data, int data_type, struct inode *dir,
const struct qstr *dname, u32 cookie, const struct qstr *dname, u32 cookie,
struct fsnotify_iter_info *iter_info) struct fsnotify_iter_info *iter_info)
{ {
struct fsnotify_mark *inode_mark = fsnotify_iter_inode_mark(iter_info); struct fsnotify_mark *inode_mark = fsnotify_iter_inode_mark(iter_info);
struct audit_fsnotify_mark *audit_mark; struct audit_fsnotify_mark *audit_mark;
......
...@@ -1037,9 +1037,9 @@ static void evict_chunk(struct audit_chunk *chunk) ...@@ -1037,9 +1037,9 @@ static void evict_chunk(struct audit_chunk *chunk)
audit_schedule_prune(); audit_schedule_prune();
} }
static int audit_tree_handle_event(struct fsnotify_group *group, static int audit_tree_handle_event(struct fsnotify_group *group, u32 mask,
struct inode *to_tell, const void *data, int data_type,
u32 mask, const void *data, int data_type, struct inode *dir,
const struct qstr *file_name, u32 cookie, const struct qstr *file_name, u32 cookie,
struct fsnotify_iter_info *iter_info) struct fsnotify_iter_info *iter_info)
{ {
......
...@@ -464,9 +464,9 @@ void audit_remove_watch_rule(struct audit_krule *krule) ...@@ -464,9 +464,9 @@ void audit_remove_watch_rule(struct audit_krule *krule)
} }
/* Update watch data in audit rules based on fsnotify events. */ /* Update watch data in audit rules based on fsnotify events. */
static int audit_watch_handle_event(struct fsnotify_group *group, static int audit_watch_handle_event(struct fsnotify_group *group, u32 mask,
struct inode *to_tell, const void *data, int data_type,
u32 mask, const void *data, int data_type, struct inode *dir,
const struct qstr *dname, u32 cookie, const struct qstr *dname, u32 cookie,
struct fsnotify_iter_info *iter_info) struct fsnotify_iter_info *iter_info)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment