Skip to content

Commit c8f3446

Browse files
amir73iljankara
authored andcommitted
inotify: report both events on parent and child with single callback
fsnotify usually calls inotify_handle_event() once for watching parent to report event with child's name and once for watching child to report event without child's name. Do the same thing with a single callback instead of two callbacks when marks iterator contains both inode and child entries. Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Amir Goldstein <[email protected]> Signed-off-by: Jan Kara <[email protected]>
1 parent 62cb0af commit c8f3446

File tree

1 file changed

+35
-9
lines changed

1 file changed

+35
-9
lines changed

fs/notify/inotify/inotify_fsnotify.c

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -55,23 +55,18 @@ static int inotify_merge(struct list_head *list,
5555
return event_compare(last_event, event);
5656
}
5757

58-
int inotify_handle_event(struct fsnotify_group *group, u32 mask,
59-
const void *data, int data_type, struct inode *dir,
60-
const struct qstr *file_name, u32 cookie,
61-
struct fsnotify_iter_info *iter_info)
58+
static int inotify_one_event(struct fsnotify_group *group, u32 mask,
59+
struct fsnotify_mark *inode_mark,
60+
const struct path *path,
61+
const struct qstr *file_name, u32 cookie)
6262
{
63-
const struct path *path = fsnotify_data_path(data, data_type);
64-
struct fsnotify_mark *inode_mark = fsnotify_iter_inode_mark(iter_info);
6563
struct inotify_inode_mark *i_mark;
6664
struct inotify_event_info *event;
6765
struct fsnotify_event *fsn_event;
6866
int ret;
6967
int len = 0;
7068
int alloc_len = sizeof(struct inotify_event_info);
7169

72-
if (WARN_ON(fsnotify_iter_vfsmount_mark(iter_info)))
73-
return 0;
74-
7570
if ((inode_mark->mask & FS_EXCL_UNLINK) &&
7671
path && d_unlinked(path->dentry))
7772
return 0;
@@ -135,6 +130,37 @@ int inotify_handle_event(struct fsnotify_group *group, u32 mask,
135130
return 0;
136131
}
137132

133+
int inotify_handle_event(struct fsnotify_group *group, u32 mask,
134+
const void *data, int data_type, struct inode *dir,
135+
const struct qstr *file_name, u32 cookie,
136+
struct fsnotify_iter_info *iter_info)
137+
{
138+
const struct path *path = fsnotify_data_path(data, data_type);
139+
struct fsnotify_mark *inode_mark = fsnotify_iter_inode_mark(iter_info);
140+
struct fsnotify_mark *child_mark = fsnotify_iter_child_mark(iter_info);
141+
int ret = 0;
142+
143+
if (WARN_ON(fsnotify_iter_vfsmount_mark(iter_info)))
144+
return 0;
145+
146+
/*
147+
* Some events cannot be sent on both parent and child marks
148+
* (e.g. IN_CREATE). Those events are always sent on inode_mark.
149+
* For events that are possible on both parent and child (e.g. IN_OPEN),
150+
* event is sent on inode_mark with name if the parent is watching and
151+
* is sent on child_mark without name if child is watching.
152+
* If both parent and child are watching, report the event with child's
153+
* name here and report another event without child's name below.
154+
*/
155+
if (inode_mark)
156+
ret = inotify_one_event(group, mask, inode_mark, path,
157+
file_name, cookie);
158+
if (ret || !child_mark)
159+
return ret;
160+
161+
return inotify_one_event(group, mask, child_mark, path, NULL, 0);
162+
}
163+
138164
static void inotify_freeing_mark(struct fsnotify_mark *fsn_mark, struct fsnotify_group *group)
139165
{
140166
inotify_ignored_and_remove_idr(fsn_mark, group);

0 commit comments

Comments
 (0)