diff options
-rw-r--r-- | fs/notify/fanotify/fanotify_user.c | 12 | ||||
-rw-r--r-- | fs/notify/inode_mark.c | 8 | ||||
-rw-r--r-- | fs/notify/mark.c | 21 | ||||
-rw-r--r-- | fs/notify/vfsmount_mark.c | 5 | ||||
-rw-r--r-- | include/linux/fanotify.h | 1 | ||||
-rw-r--r-- | include/linux/fsnotify_backend.h | 6 |
6 files changed, 46 insertions, 7 deletions
diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c index 3e275f17e7b7..9fe760baf69f 100644 --- a/fs/notify/fanotify/fanotify_user.c +++ b/fs/notify/fanotify/fanotify_user.c | |||
@@ -514,9 +514,10 @@ SYSCALL_DEFINE(fanotify_mark)(int fanotify_fd, unsigned int flags, | |||
514 | 514 | ||
515 | if (flags & ~FAN_ALL_MARK_FLAGS) | 515 | if (flags & ~FAN_ALL_MARK_FLAGS) |
516 | return -EINVAL; | 516 | return -EINVAL; |
517 | switch (flags & (FAN_MARK_ADD | FAN_MARK_REMOVE)) { | 517 | switch (flags & (FAN_MARK_ADD | FAN_MARK_REMOVE | FAN_MARK_FLUSH)) { |
518 | case FAN_MARK_ADD: | 518 | case FAN_MARK_ADD: |
519 | case FAN_MARK_REMOVE: | 519 | case FAN_MARK_REMOVE: |
520 | case FAN_MARK_FLUSH: | ||
520 | break; | 521 | break; |
521 | default: | 522 | default: |
522 | return -EINVAL; | 523 | return -EINVAL; |
@@ -545,7 +546,7 @@ SYSCALL_DEFINE(fanotify_mark)(int fanotify_fd, unsigned int flags, | |||
545 | group = filp->private_data; | 546 | group = filp->private_data; |
546 | 547 | ||
547 | /* create/update an inode mark */ | 548 | /* create/update an inode mark */ |
548 | switch (flags & (FAN_MARK_ADD | FAN_MARK_REMOVE)) { | 549 | switch (flags & (FAN_MARK_ADD | FAN_MARK_REMOVE | FAN_MARK_FLUSH)) { |
549 | case FAN_MARK_ADD: | 550 | case FAN_MARK_ADD: |
550 | if (flags & FAN_MARK_MOUNT) | 551 | if (flags & FAN_MARK_MOUNT) |
551 | ret = fanotify_add_vfsmount_mark(group, mnt, mask, flags); | 552 | ret = fanotify_add_vfsmount_mark(group, mnt, mask, flags); |
@@ -558,6 +559,13 @@ SYSCALL_DEFINE(fanotify_mark)(int fanotify_fd, unsigned int flags, | |||
558 | else | 559 | else |
559 | ret = fanotify_remove_inode_mark(group, inode, mask, flags); | 560 | ret = fanotify_remove_inode_mark(group, inode, mask, flags); |
560 | break; | 561 | break; |
562 | case FAN_MARK_FLUSH: | ||
563 | if (flags & FAN_MARK_MOUNT) | ||
564 | fsnotify_clear_vfsmount_marks_by_group(group); | ||
565 | else | ||
566 | fsnotify_clear_inode_marks_by_group(group); | ||
567 | fsnotify_recalc_group_mask(group); | ||
568 | break; | ||
561 | default: | 569 | default: |
562 | ret = -EINVAL; | 570 | ret = -EINVAL; |
563 | } | 571 | } |
diff --git a/fs/notify/inode_mark.c b/fs/notify/inode_mark.c index 4292f9e23ae8..0c0a48b1659f 100644 --- a/fs/notify/inode_mark.c +++ b/fs/notify/inode_mark.c | |||
@@ -104,6 +104,14 @@ void fsnotify_clear_marks_by_inode(struct inode *inode) | |||
104 | } | 104 | } |
105 | 105 | ||
106 | /* | 106 | /* |
107 | * Given a group clear all of the inode marks associated with that group. | ||
108 | */ | ||
109 | void fsnotify_clear_inode_marks_by_group(struct fsnotify_group *group) | ||
110 | { | ||
111 | fsnotify_clear_marks_by_group_flags(group, FSNOTIFY_MARK_FLAG_INODE); | ||
112 | } | ||
113 | |||
114 | /* | ||
107 | * given a group and inode, find the mark associated with that combination. | 115 | * given a group and inode, find the mark associated with that combination. |
108 | * if found take a reference to that mark and return it, else return NULL | 116 | * if found take a reference to that mark and return it, else return NULL |
109 | */ | 117 | */ |
diff --git a/fs/notify/mark.c b/fs/notify/mark.c index cb1d822f227f..1e824e64441d 100644 --- a/fs/notify/mark.c +++ b/fs/notify/mark.c | |||
@@ -270,18 +270,21 @@ err: | |||
270 | } | 270 | } |
271 | 271 | ||
272 | /* | 272 | /* |
273 | * Given a group, destroy all of the marks associated with that group. | 273 | * clear any marks in a group in which mark->flags & flags is true |
274 | */ | 274 | */ |
275 | void fsnotify_clear_marks_by_group(struct fsnotify_group *group) | 275 | void fsnotify_clear_marks_by_group_flags(struct fsnotify_group *group, |
276 | unsigned int flags) | ||
276 | { | 277 | { |
277 | struct fsnotify_mark *lmark, *mark; | 278 | struct fsnotify_mark *lmark, *mark; |
278 | LIST_HEAD(free_list); | 279 | LIST_HEAD(free_list); |
279 | 280 | ||
280 | spin_lock(&group->mark_lock); | 281 | spin_lock(&group->mark_lock); |
281 | list_for_each_entry_safe(mark, lmark, &group->marks_list, g_list) { | 282 | list_for_each_entry_safe(mark, lmark, &group->marks_list, g_list) { |
282 | list_add(&mark->free_g_list, &free_list); | 283 | if (mark->flags & flags) { |
283 | list_del_init(&mark->g_list); | 284 | list_add(&mark->free_g_list, &free_list); |
284 | fsnotify_get_mark(mark); | 285 | list_del_init(&mark->g_list); |
286 | fsnotify_get_mark(mark); | ||
287 | } | ||
285 | } | 288 | } |
286 | spin_unlock(&group->mark_lock); | 289 | spin_unlock(&group->mark_lock); |
287 | 290 | ||
@@ -291,6 +294,14 @@ void fsnotify_clear_marks_by_group(struct fsnotify_group *group) | |||
291 | } | 294 | } |
292 | } | 295 | } |
293 | 296 | ||
297 | /* | ||
298 | * Given a group, destroy all of the marks associated with that group. | ||
299 | */ | ||
300 | void fsnotify_clear_marks_by_group(struct fsnotify_group *group) | ||
301 | { | ||
302 | fsnotify_clear_marks_by_group_flags(group, (unsigned int)-1); | ||
303 | } | ||
304 | |||
294 | void fsnotify_duplicate_mark(struct fsnotify_mark *new, struct fsnotify_mark *old) | 305 | void fsnotify_duplicate_mark(struct fsnotify_mark *new, struct fsnotify_mark *old) |
295 | { | 306 | { |
296 | assert_spin_locked(&old->lock); | 307 | assert_spin_locked(&old->lock); |
diff --git a/fs/notify/vfsmount_mark.c b/fs/notify/vfsmount_mark.c index 1b61d0a942de..8f1aa02f4f02 100644 --- a/fs/notify/vfsmount_mark.c +++ b/fs/notify/vfsmount_mark.c | |||
@@ -51,6 +51,11 @@ void fsnotify_clear_marks_by_mount(struct vfsmount *mnt) | |||
51 | } | 51 | } |
52 | } | 52 | } |
53 | 53 | ||
54 | void fsnotify_clear_vfsmount_marks_by_group(struct fsnotify_group *group) | ||
55 | { | ||
56 | fsnotify_clear_marks_by_group_flags(group, FSNOTIFY_MARK_FLAG_VFSMOUNT); | ||
57 | } | ||
58 | |||
54 | /* | 59 | /* |
55 | * Recalculate the mask of events relevant to a given vfsmount locked. | 60 | * Recalculate the mask of events relevant to a given vfsmount locked. |
56 | */ | 61 | */ |
diff --git a/include/linux/fanotify.h b/include/linux/fanotify.h index e43934d0b74c..385896c9f828 100644 --- a/include/linux/fanotify.h +++ b/include/linux/fanotify.h | |||
@@ -32,6 +32,7 @@ | |||
32 | #define FAN_MARK_MOUNT 0x00000010 | 32 | #define FAN_MARK_MOUNT 0x00000010 |
33 | #define FAN_MARK_IGNORED_MASK 0x00000020 | 33 | #define FAN_MARK_IGNORED_MASK 0x00000020 |
34 | #define FAN_MARK_IGNORED_SURV_MODIFY 0x00000040 | 34 | #define FAN_MARK_IGNORED_SURV_MODIFY 0x00000040 |
35 | #define FAN_MARK_FLUSH 0x00000080 | ||
35 | 36 | ||
36 | #define FAN_ALL_MARK_FLAGS (FAN_MARK_ADD |\ | 37 | #define FAN_ALL_MARK_FLAGS (FAN_MARK_ADD |\ |
37 | FAN_MARK_REMOVE |\ | 38 | FAN_MARK_REMOVE |\ |
diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h index 8ca19df8a171..be4a36ed2008 100644 --- a/include/linux/fsnotify_backend.h +++ b/include/linux/fsnotify_backend.h | |||
@@ -384,6 +384,12 @@ extern int fsnotify_add_mark(struct fsnotify_mark *mark, struct fsnotify_group * | |||
384 | struct inode *inode, struct vfsmount *mnt, int allow_dups); | 384 | struct inode *inode, struct vfsmount *mnt, int allow_dups); |
385 | /* given a mark, flag it to be freed when all references are dropped */ | 385 | /* given a mark, flag it to be freed when all references are dropped */ |
386 | extern void fsnotify_destroy_mark(struct fsnotify_mark *mark); | 386 | extern void fsnotify_destroy_mark(struct fsnotify_mark *mark); |
387 | /* run all the marks in a group, and clear all of the vfsmount marks */ | ||
388 | extern void fsnotify_clear_vfsmount_marks_by_group(struct fsnotify_group *group); | ||
389 | /* run all the marks in a group, and clear all of the inode marks */ | ||
390 | extern void fsnotify_clear_inode_marks_by_group(struct fsnotify_group *group); | ||
391 | /* run all the marks in a group, and clear all of the marks where mark->flags & flags is true*/ | ||
392 | extern void fsnotify_clear_marks_by_group_flags(struct fsnotify_group *group, unsigned int flags); | ||
387 | /* run all the marks in a group, and flag them to be freed */ | 393 | /* run all the marks in a group, and flag them to be freed */ |
388 | extern void fsnotify_clear_marks_by_group(struct fsnotify_group *group); | 394 | extern void fsnotify_clear_marks_by_group(struct fsnotify_group *group); |
389 | extern void fsnotify_get_mark(struct fsnotify_mark *mark); | 395 | extern void fsnotify_get_mark(struct fsnotify_mark *mark); |