diff options
author | Amir Goldstein <amir73il@gmail.com> | 2018-04-20 19:10:51 -0400 |
---|---|---|
committer | Jan Kara <jack@suse.cz> | 2018-05-18 08:58:22 -0400 |
commit | d9a6f30bb89309a7f2473028a00b83b020049cb4 (patch) | |
tree | 0ea2cfa88eec367ab6c45cb592fb51014d81176b | |
parent | 5b0457ad021f3f7e3d9f4b84e7c3080748f383f8 (diff) |
fsnotify: introduce marks iteration helpers
Introduce helpers fsnotify_iter_select_report_types() and
fsnotify_iter_next() to abstract the inode/vfsmount marks merged
list iteration.
This is a preparation patch before generalizing mark list
iteration to more mark object types (i.e. super block marks).
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
Signed-off-by: Jan Kara <jack@suse.cz>
-rw-r--r-- | fs/notify/fsnotify.c | 74 |
1 files changed, 49 insertions, 25 deletions
diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c index 9a63cf07f858..98e91037b11d 100644 --- a/fs/notify/fsnotify.c +++ b/fs/notify/fsnotify.c | |||
@@ -261,6 +261,53 @@ static struct fsnotify_mark *fsnotify_next_mark(struct fsnotify_mark *mark) | |||
261 | } | 261 | } |
262 | 262 | ||
263 | /* | 263 | /* |
264 | * iter_info is a multi head priority queue of marks. | ||
265 | * Pick a subset of marks from queue heads, all with the | ||
266 | * same group and set the report_mask for selected subset. | ||
267 | * Returns the report_mask of the selected subset. | ||
268 | */ | ||
269 | static unsigned int fsnotify_iter_select_report_types( | ||
270 | struct fsnotify_iter_info *iter_info) | ||
271 | { | ||
272 | struct fsnotify_mark *inode_mark = iter_info->inode_mark; | ||
273 | struct fsnotify_mark *vfsmount_mark = iter_info->vfsmount_mark; | ||
274 | int cmp; | ||
275 | |||
276 | if (!inode_mark && !vfsmount_mark) | ||
277 | return 0; | ||
278 | |||
279 | if (inode_mark && vfsmount_mark) { | ||
280 | cmp = fsnotify_compare_groups(inode_mark->group, | ||
281 | vfsmount_mark->group); | ||
282 | } else { | ||
283 | cmp = inode_mark ? -1 : 1; | ||
284 | } | ||
285 | |||
286 | iter_info->report_mask = 0; | ||
287 | if (cmp <= 0) | ||
288 | iter_info->report_mask |= FSNOTIFY_OBJ_TYPE_INODE_FL; | ||
289 | if (cmp >= 0) | ||
290 | iter_info->report_mask |= FSNOTIFY_OBJ_TYPE_VFSMOUNT_FL; | ||
291 | |||
292 | return iter_info->report_mask; | ||
293 | } | ||
294 | |||
295 | /* | ||
296 | * Pop from iter_info multi head queue, the marks that were iterated in the | ||
297 | * current iteration step. | ||
298 | */ | ||
299 | static void fsnotify_iter_next(struct fsnotify_iter_info *iter_info) | ||
300 | { | ||
301 | if (iter_info->report_mask & FSNOTIFY_OBJ_TYPE_INODE_FL) | ||
302 | iter_info->inode_mark = | ||
303 | fsnotify_next_mark(iter_info->inode_mark); | ||
304 | |||
305 | if (iter_info->report_mask & FSNOTIFY_OBJ_TYPE_VFSMOUNT_FL) | ||
306 | iter_info->vfsmount_mark = | ||
307 | fsnotify_next_mark(iter_info->vfsmount_mark); | ||
308 | } | ||
309 | |||
310 | /* | ||
264 | * This is the main call to fsnotify. The VFS calls into hook specific functions | 311 | * This is the main call to fsnotify. The VFS calls into hook specific functions |
265 | * in linux/fsnotify.h. Those functions then in turn call here. Here will call | 312 | * in linux/fsnotify.h. Those functions then in turn call here. Here will call |
266 | * out to all of the registered fsnotify_group. Those groups can then use the | 313 | * out to all of the registered fsnotify_group. Those groups can then use the |
@@ -321,37 +368,14 @@ int fsnotify(struct inode *to_tell, __u32 mask, const void *data, int data_is, | |||
321 | * ignore masks are properly reflected for mount mark notifications. | 368 | * ignore masks are properly reflected for mount mark notifications. |
322 | * That's why this traversal is so complicated... | 369 | * That's why this traversal is so complicated... |
323 | */ | 370 | */ |
324 | while (iter_info.inode_mark || iter_info.vfsmount_mark) { | 371 | while (fsnotify_iter_select_report_types(&iter_info)) { |
325 | struct fsnotify_mark *inode_mark = iter_info.inode_mark; | ||
326 | struct fsnotify_mark *vfsmount_mark = iter_info.vfsmount_mark; | ||
327 | int cmp; | ||
328 | |||
329 | if (inode_mark && vfsmount_mark) { | ||
330 | cmp = fsnotify_compare_groups(inode_mark->group, | ||
331 | vfsmount_mark->group); | ||
332 | } else { | ||
333 | cmp = inode_mark ? -1 : 1; | ||
334 | } | ||
335 | |||
336 | iter_info.report_mask = 0; | ||
337 | if (cmp <= 0) | ||
338 | iter_info.report_mask |= FSNOTIFY_OBJ_TYPE_INODE_FL; | ||
339 | if (cmp >= 0) | ||
340 | iter_info.report_mask |= FSNOTIFY_OBJ_TYPE_VFSMOUNT_FL; | ||
341 | |||
342 | ret = send_to_group(to_tell, mask, data, data_is, cookie, | 372 | ret = send_to_group(to_tell, mask, data, data_is, cookie, |
343 | file_name, &iter_info); | 373 | file_name, &iter_info); |
344 | 374 | ||
345 | if (ret && (mask & ALL_FSNOTIFY_PERM_EVENTS)) | 375 | if (ret && (mask & ALL_FSNOTIFY_PERM_EVENTS)) |
346 | goto out; | 376 | goto out; |
347 | 377 | ||
348 | if (iter_info.report_mask & FSNOTIFY_OBJ_TYPE_INODE_FL) | 378 | fsnotify_iter_next(&iter_info); |
349 | iter_info.inode_mark = | ||
350 | fsnotify_next_mark(iter_info.inode_mark); | ||
351 | |||
352 | if (iter_info.report_mask & FSNOTIFY_OBJ_TYPE_VFSMOUNT_FL) | ||
353 | iter_info.vfsmount_mark = | ||
354 | fsnotify_next_mark(iter_info.vfsmount_mark); | ||
355 | } | 379 | } |
356 | ret = 0; | 380 | ret = 0; |
357 | out: | 381 | out: |