aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Paris <eparis@redhat.com>2010-10-28 17:21:59 -0400
committerEric Paris <eparis@redhat.com>2010-10-28 17:22:16 -0400
commit8fcd65280abc4699510f1853ede31f43e8a3783a (patch)
tree9ef20b7c3ee0a4130d88922d7d4115beaa0c9dc0
parentb29866aab8489487f11cc4506590ac31bdbae22a (diff)
fanotify: ignore events on directories unless specifically requested
fanotify has a very limited number of events it sends on directories. The usefulness of these events is yet to be seen and still we send them. This is particularly painful for mount marks where one might receive many of these useless events. As such this patch will drop events on IS_DIR() inodes unless they were explictly requested with FAN_ON_DIR. This means that a mark on a directory without FAN_EVENT_ON_CHILD or FAN_ON_DIR is meaningless and will result in no events ever (although it will still be allowed since detecting it is hard) Signed-off-by: Eric Paris <eparis@redhat.com>
-rw-r--r--fs/notify/fanotify/fanotify.c5
-rw-r--r--fs/notify/fanotify/fanotify_user.c12
-rw-r--r--include/linux/fanotify.h10
3 files changed, 25 insertions, 2 deletions
diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c
index 8d98e1f5817b..b04f88eed09e 100644
--- a/fs/notify/fanotify/fanotify.c
+++ b/fs/notify/fanotify/fanotify.c
@@ -131,6 +131,7 @@ static int fanotify_handle_event(struct fsnotify_group *group,
131 BUILD_BUG_ON(FAN_Q_OVERFLOW != FS_Q_OVERFLOW); 131 BUILD_BUG_ON(FAN_Q_OVERFLOW != FS_Q_OVERFLOW);
132 BUILD_BUG_ON(FAN_OPEN_PERM != FS_OPEN_PERM); 132 BUILD_BUG_ON(FAN_OPEN_PERM != FS_OPEN_PERM);
133 BUILD_BUG_ON(FAN_ACCESS_PERM != FS_ACCESS_PERM); 133 BUILD_BUG_ON(FAN_ACCESS_PERM != FS_ACCESS_PERM);
134 BUILD_BUG_ON(FAN_ONDIR != FS_ISDIR);
134 135
135 pr_debug("%s: group=%p event=%p\n", __func__, group, event); 136 pr_debug("%s: group=%p event=%p\n", __func__, group, event);
136 137
@@ -195,6 +196,10 @@ static bool fanotify_should_send_event(struct fsnotify_group *group,
195 BUG(); 196 BUG();
196 } 197 }
197 198
199 if (S_ISDIR(path->dentry->d_inode->i_mode) &&
200 (marks_ignored_mask & FS_ISDIR))
201 return false;
202
198 if (event_mask & marks_mask & ~marks_ignored_mask) 203 if (event_mask & marks_mask & ~marks_ignored_mask)
199 return true; 204 return true;
200 205
diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c
index a7d9369482d5..ff1a908c9708 100644
--- a/fs/notify/fanotify/fanotify_user.c
+++ b/fs/notify/fanotify/fanotify_user.c
@@ -570,6 +570,12 @@ static __u32 fanotify_mark_add_to_mask(struct fsnotify_mark *fsn_mark,
570 if (flags & FAN_MARK_IGNORED_SURV_MODIFY) 570 if (flags & FAN_MARK_IGNORED_SURV_MODIFY)
571 fsn_mark->flags |= FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY; 571 fsn_mark->flags |= FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY;
572 } 572 }
573
574 if (!(flags & FAN_MARK_ONDIR)) {
575 __u32 tmask = fsn_mark->ignored_mask | FAN_ONDIR;
576 fsnotify_set_mark_ignored_mask_locked(fsn_mark, tmask);
577 }
578
573 spin_unlock(&fsn_mark->lock); 579 spin_unlock(&fsn_mark->lock);
574 580
575 return mask & ~oldmask; 581 return mask & ~oldmask;
@@ -766,6 +772,12 @@ SYSCALL_DEFINE(fanotify_mark)(int fanotify_fd, unsigned int flags,
766 default: 772 default:
767 return -EINVAL; 773 return -EINVAL;
768 } 774 }
775
776 if (mask & FAN_ONDIR) {
777 flags |= FAN_MARK_ONDIR;
778 mask &= ~FAN_ONDIR;
779 }
780
769#ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS 781#ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
770 if (mask & ~(FAN_ALL_EVENTS | FAN_ALL_PERM_EVENTS | FAN_EVENT_ON_CHILD)) 782 if (mask & ~(FAN_ALL_EVENTS | FAN_ALL_PERM_EVENTS | FAN_EVENT_ON_CHILD))
771#else 783#else
diff --git a/include/linux/fanotify.h b/include/linux/fanotify.h
index 7592a366a57b..5e0400a80c33 100644
--- a/include/linux/fanotify.h
+++ b/include/linux/fanotify.h
@@ -10,13 +10,15 @@
10#define FAN_CLOSE_NOWRITE 0x00000010 /* Writtable file closed */ 10#define FAN_CLOSE_NOWRITE 0x00000010 /* Writtable file closed */
11#define FAN_OPEN 0x00000020 /* File was opened */ 11#define FAN_OPEN 0x00000020 /* File was opened */
12 12
13#define FAN_EVENT_ON_CHILD 0x08000000 /* interested in child events */
14
15#define FAN_Q_OVERFLOW 0x00004000 /* Event queued overflowed */ 13#define FAN_Q_OVERFLOW 0x00004000 /* Event queued overflowed */
16 14
17#define FAN_OPEN_PERM 0x00010000 /* File open in perm check */ 15#define FAN_OPEN_PERM 0x00010000 /* File open in perm check */
18#define FAN_ACCESS_PERM 0x00020000 /* File accessed in perm check */ 16#define FAN_ACCESS_PERM 0x00020000 /* File accessed in perm check */
19 17
18#define FAN_ONDIR 0x40000000 /* event occurred against dir */
19
20#define FAN_EVENT_ON_CHILD 0x08000000 /* interested in child events */
21
20/* helper events */ 22/* helper events */
21#define FAN_CLOSE (FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE) /* close */ 23#define FAN_CLOSE (FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE) /* close */
22 24
@@ -47,6 +49,10 @@
47#define FAN_MARK_IGNORED_MASK 0x00000020 49#define FAN_MARK_IGNORED_MASK 0x00000020
48#define FAN_MARK_IGNORED_SURV_MODIFY 0x00000040 50#define FAN_MARK_IGNORED_SURV_MODIFY 0x00000040
49#define FAN_MARK_FLUSH 0x00000080 51#define FAN_MARK_FLUSH 0x00000080
52#ifdef __KERNEL__
53/* not valid from userspace, only kernel internal */
54#define FAN_MARK_ONDIR 0x00000100
55#endif
50 56
51#define FAN_ALL_MARK_FLAGS (FAN_MARK_ADD |\ 57#define FAN_ALL_MARK_FLAGS (FAN_MARK_ADD |\
52 FAN_MARK_REMOVE |\ 58 FAN_MARK_REMOVE |\