Skip to content

Commit 62cb0af

Browse files
amir73iljankara
authored andcommitted
dnotify: report both events on parent and child with single callback
For some events (e.g. DN_ATTRIB on sub-directory) fsnotify may call dnotify_handle_event() once for watching parent and once again for the watching sub-directory. 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 f35c415 commit 62cb0af

File tree

1 file changed

+29
-13
lines changed

1 file changed

+29
-13
lines changed

fs/notify/dnotify/dnotify.c

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -70,26 +70,15 @@ static void dnotify_recalc_inode_mask(struct fsnotify_mark *fsn_mark)
7070
* destroy the dnotify struct if it was not registered to receive multiple
7171
* events.
7272
*/
73-
static int dnotify_handle_event(struct fsnotify_group *group, u32 mask,
74-
const void *data, int data_type,
75-
struct inode *dir,
76-
const struct qstr *file_name, u32 cookie,
77-
struct fsnotify_iter_info *iter_info)
73+
static void dnotify_one_event(struct fsnotify_group *group, u32 mask,
74+
struct fsnotify_mark *inode_mark)
7875
{
79-
struct fsnotify_mark *inode_mark = fsnotify_iter_inode_mark(iter_info);
8076
struct dnotify_mark *dn_mark;
8177
struct dnotify_struct *dn;
8278
struct dnotify_struct **prev;
8379
struct fown_struct *fown;
8480
__u32 test_mask = mask & ~FS_EVENT_ON_CHILD;
8581

86-
/* not a dir, dnotify doesn't care */
87-
if (!dir && !(mask & FS_ISDIR))
88-
return 0;
89-
90-
if (WARN_ON(fsnotify_iter_vfsmount_mark(iter_info)))
91-
return 0;
92-
9382
dn_mark = container_of(inode_mark, struct dnotify_mark, fsn_mark);
9483

9584
spin_lock(&inode_mark->lock);
@@ -111,6 +100,33 @@ static int dnotify_handle_event(struct fsnotify_group *group, u32 mask,
111100
}
112101

113102
spin_unlock(&inode_mark->lock);
103+
}
104+
105+
static int dnotify_handle_event(struct fsnotify_group *group, u32 mask,
106+
const void *data, int data_type,
107+
struct inode *dir,
108+
const struct qstr *file_name, u32 cookie,
109+
struct fsnotify_iter_info *iter_info)
110+
{
111+
struct fsnotify_mark *inode_mark = fsnotify_iter_inode_mark(iter_info);
112+
struct fsnotify_mark *child_mark = fsnotify_iter_child_mark(iter_info);
113+
114+
/* not a dir, dnotify doesn't care */
115+
if (!dir && !(mask & FS_ISDIR))
116+
return 0;
117+
118+
if (WARN_ON(fsnotify_iter_vfsmount_mark(iter_info)))
119+
return 0;
120+
121+
/*
122+
* Some events can be sent on both parent dir and subdir marks
123+
* (e.g. DN_ATTRIB). If both parent dir and subdir are watching,
124+
* report the event once to parent dir and once to subdir.
125+
*/
126+
if (inode_mark)
127+
dnotify_one_event(group, mask, inode_mark);
128+
if (child_mark)
129+
dnotify_one_event(group, mask, child_mark);
114130

115131
return 0;
116132
}

0 commit comments

Comments
 (0)