summaryrefslogtreecommitdiffstats
path: root/fs/notify
diff options
context:
space:
mode:
authorAmir Goldstein <amir73il@gmail.com>2019-01-10 12:04:44 -0500
committerJan Kara <jack@suse.cz>2019-02-07 10:47:32 -0500
commite7fce6d94cc1f7d7ccb6e79dbf7062baec45e142 (patch)
treee26b42b47340198645dd309435db97aa4eb53d3f /fs/notify
parent235328d1fa4251c6dcb32351219bb553a58838d2 (diff)
fanotify: report FAN_ONDIR to listener with FAN_REPORT_FID
dirent modification events (create/delete/move) do not carry the child entry name/inode information. Instead, we report FAN_ONDIR for mkdir/rmdir so user can differentiate them from creat/unlink. This is consistent with inotify reporting IN_ISDIR with dirent events and is useful for implementing recursive directory tree watcher. We avoid merging dirent events referring to subdirs with dirent events referring to non subdirs, otherwise, user won't be able to tell from a mask FAN_CREATE|FAN_DELETE|FAN_ONDIR if it describes mkdir+unlink pair or rmdir+create pair of events. For backward compatibility and consistency, do not report FAN_ONDIR to user in legacy fanotify mode (reporting fd) and report FAN_ONDIR to user in FAN_REPORT_FID mode for all event types. Cc: <linux-api@vger.kernel.org> Signed-off-by: Amir Goldstein <amir73il@gmail.com> Signed-off-by: Jan Kara <jack@suse.cz>
Diffstat (limited to 'fs/notify')
-rw-r--r--fs/notify/fanotify/fanotify.c34
1 files changed, 31 insertions, 3 deletions
diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c
index 158c69acb04d..4ff84bc5772e 100644
--- a/fs/notify/fanotify/fanotify.c
+++ b/fs/notify/fanotify/fanotify.c
@@ -34,7 +34,16 @@ static bool should_merge(struct fsnotify_event *old_fsn,
34 return old->path.mnt == new->path.mnt && 34 return old->path.mnt == new->path.mnt &&
35 old->path.dentry == new->path.dentry; 35 old->path.dentry == new->path.dentry;
36 } else if (fanotify_event_has_fid(old)) { 36 } else if (fanotify_event_has_fid(old)) {
37 return fanotify_fid_equal(&old->fid, &new->fid, old->fh_len); 37 /*
38 * We want to merge many dirent events in the same dir (i.e.
39 * creates/unlinks/renames), but we do not want to merge dirent
40 * events referring to subdirs with dirent events referring to
41 * non subdirs, otherwise, user won't be able to tell from a
42 * mask FAN_CREATE|FAN_DELETE|FAN_ONDIR if it describes mkdir+
43 * unlink pair or rmdir+create pair of events.
44 */
45 return (old->mask & FS_ISDIR) == (new->mask & FS_ISDIR) &&
46 fanotify_fid_equal(&old->fid, &new->fid, old->fh_len);
38 } 47 }
39 48
40 /* Do not merge events if we failed to encode fid */ 49 /* Do not merge events if we failed to encode fid */
@@ -112,6 +121,7 @@ static u32 fanotify_group_event_mask(struct fsnotify_group *group,
112 int data_type) 121 int data_type)
113{ 122{
114 __u32 marks_mask = 0, marks_ignored_mask = 0; 123 __u32 marks_mask = 0, marks_ignored_mask = 0;
124 __u32 test_mask, user_mask = FANOTIFY_OUTGOING_EVENTS;
115 const struct path *path = data; 125 const struct path *path = data;
116 struct fsnotify_mark *mark; 126 struct fsnotify_mark *mark;
117 int type; 127 int type;
@@ -145,12 +155,30 @@ static u32 fanotify_group_event_mask(struct fsnotify_group *group,
145 marks_ignored_mask |= mark->ignored_mask; 155 marks_ignored_mask |= mark->ignored_mask;
146 } 156 }
147 157
158 test_mask = event_mask & marks_mask & ~marks_ignored_mask;
159
160 /*
161 * dirent modification events (create/delete/move) do not carry the
162 * child entry name/inode information. Instead, we report FAN_ONDIR
163 * for mkdir/rmdir so user can differentiate them from creat/unlink.
164 *
165 * For backward compatibility and consistency, do not report FAN_ONDIR
166 * to user in legacy fanotify mode (reporting fd) and report FAN_ONDIR
167 * to user in FAN_REPORT_FID mode for all event types.
168 */
169 if (FAN_GROUP_FLAG(group, FAN_REPORT_FID)) {
170 /* Do not report FAN_ONDIR without any event */
171 if (!(test_mask & ~FAN_ONDIR))
172 return 0;
173 } else {
174 user_mask &= ~FAN_ONDIR;
175 }
176
148 if (event_mask & FS_ISDIR && 177 if (event_mask & FS_ISDIR &&
149 !(marks_mask & FS_ISDIR & ~marks_ignored_mask)) 178 !(marks_mask & FS_ISDIR & ~marks_ignored_mask))
150 return 0; 179 return 0;
151 180
152 return event_mask & FANOTIFY_OUTGOING_EVENTS & marks_mask & 181 return test_mask & user_mask;
153 ~marks_ignored_mask;
154} 182}
155 183
156static int fanotify_encode_fid(struct fanotify_event *event, 184static int fanotify_encode_fid(struct fanotify_event *event,