aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Paris <eparis@redhat.com>2009-12-17 21:24:34 -0500
committerEric Paris <eparis@redhat.com>2010-07-28 09:59:00 -0400
commit4d92604cc90aa18bbbe0f6e23b7a9fdb612836d3 (patch)
treec04b26fb38a8524fa5e204cb9e40870afa9823f9
parentc9778a98e7440fb73e0d27b8155a688663a0d493 (diff)
fanotify: clear all fanotify marks
fanotify listeners may want to clear all marks. They may want to do this to destroy all of their inode marks which have nothing but ignores. Realistically this is useful for av vendors who update policy and want to clear all of their cached allows. Signed-off-by: Eric Paris <eparis@redhat.com>
-rw-r--r--fs/notify/fanotify/fanotify_user.c12
-rw-r--r--fs/notify/inode_mark.c8
-rw-r--r--fs/notify/mark.c21
-rw-r--r--fs/notify/vfsmount_mark.c5
-rw-r--r--include/linux/fanotify.h1
-rw-r--r--include/linux/fsnotify_backend.h6
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 */
109void 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 */
275void fsnotify_clear_marks_by_group(struct fsnotify_group *group) 275void 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 */
300void fsnotify_clear_marks_by_group(struct fsnotify_group *group)
301{
302 fsnotify_clear_marks_by_group_flags(group, (unsigned int)-1);
303}
304
294void fsnotify_duplicate_mark(struct fsnotify_mark *new, struct fsnotify_mark *old) 305void 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
54void 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 */
386extern void fsnotify_destroy_mark(struct fsnotify_mark *mark); 386extern void fsnotify_destroy_mark(struct fsnotify_mark *mark);
387/* run all the marks in a group, and clear all of the vfsmount marks */
388extern 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 */
390extern 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*/
392extern 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 */
388extern void fsnotify_clear_marks_by_group(struct fsnotify_group *group); 394extern void fsnotify_clear_marks_by_group(struct fsnotify_group *group);
389extern void fsnotify_get_mark(struct fsnotify_mark *mark); 395extern void fsnotify_get_mark(struct fsnotify_mark *mark);