aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Paris <eparis@redhat.com>2009-12-17 21:24:23 -0500
committerEric Paris <eparis@redhat.com>2010-07-28 09:58:52 -0400
commit3a9fb89f4cd04c23e16397befba92efb5d989b74 (patch)
treef60b48c8cf488ad8952601ccbc6192b5f86ec900
parent7131485a93679ff9a543b74df280cfd119eb03ca (diff)
fsnotify: include vfsmount in should_send_event when appropriate
To ensure that a group will not duplicate events when it receives it based on the vfsmount and the inode should_send_event test we should distinguish those two cases. We pass a vfsmount to this function so groups can make their own determinations. Signed-off-by: Eric Paris <eparis@redhat.com>
-rw-r--r--fs/notify/dnotify/dnotify.c4
-rw-r--r--fs/notify/fsnotify.c39
-rw-r--r--fs/notify/inotify/inotify_fsnotify.c3
-rw-r--r--include/linux/fsnotify_backend.h3
-rw-r--r--kernel/audit_tree.c3
-rw-r--r--kernel/audit_watch.c3
6 files changed, 29 insertions, 26 deletions
diff --git a/fs/notify/dnotify/dnotify.c b/fs/notify/dnotify/dnotify.c
index e0a847bd53be..9eddafa4c7ba 100644
--- a/fs/notify/dnotify/dnotify.c
+++ b/fs/notify/dnotify/dnotify.c
@@ -133,8 +133,8 @@ static int dnotify_handle_event(struct fsnotify_group *group,
133 * userspace notification for that pair. 133 * userspace notification for that pair.
134 */ 134 */
135static bool dnotify_should_send_event(struct fsnotify_group *group, 135static bool dnotify_should_send_event(struct fsnotify_group *group,
136 struct inode *inode, __u32 mask, 136 struct inode *inode, struct vfsmount *mnt,
137 void *data, int data_type) 137 __u32 mask, void *data, int data_type)
138{ 138{
139 struct fsnotify_mark_entry *entry; 139 struct fsnotify_mark_entry *entry;
140 bool send; 140 bool send;
diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c
index a61aaa710825..78c440c343a8 100644
--- a/fs/notify/fsnotify.c
+++ b/fs/notify/fsnotify.c
@@ -135,13 +135,12 @@ void __fsnotify_parent(struct file *file, struct dentry *dentry, __u32 mask)
135} 135}
136EXPORT_SYMBOL_GPL(__fsnotify_parent); 136EXPORT_SYMBOL_GPL(__fsnotify_parent);
137 137
138static void send_to_group(__u32 mask, 138static void send_to_group(struct fsnotify_group *group, struct inode *to_tell,
139 struct fsnotify_group *group, 139 struct vfsmount *mnt, __u32 mask, void *data,
140 void *data, int data_is, const char *file_name, 140 int data_is, u32 cookie, const char *file_name,
141 u32 cookie, struct fsnotify_event **event, 141 struct fsnotify_event **event)
142 struct inode *to_tell)
143{ 142{
144 if (!group->ops->should_send_event(group, to_tell, mask, 143 if (!group->ops->should_send_event(group, to_tell, mnt, mask,
145 data, data_is)) 144 data, data_is))
146 return; 145 return;
147 if (!*event) { 146 if (!*event) {
@@ -159,15 +158,9 @@ static void send_to_group(__u32 mask,
159 group->ops->handle_event(group, *event); 158 group->ops->handle_event(group, *event);
160} 159}
161 160
162static bool needed_by_vfsmount(__u32 test_mask, void *data, int data_is) 161static bool needed_by_vfsmount(__u32 test_mask, struct vfsmount *mnt)
163{ 162{
164 struct path *path; 163 if (!mnt)
165
166 if (data_is == FSNOTIFY_EVENT_PATH)
167 path = (struct path *)data;
168 else if (data_is == FSNOTIFY_EVENT_FILE)
169 path = &((struct file *)data)->f_path;
170 else
171 return false; 164 return false;
172 165
173 /* hook in this when mnt->mnt_fsnotify_mask is defined */ 166 /* hook in this when mnt->mnt_fsnotify_mask is defined */
@@ -184,6 +177,7 @@ void fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is, const
184{ 177{
185 struct fsnotify_group *group; 178 struct fsnotify_group *group;
186 struct fsnotify_event *event = NULL; 179 struct fsnotify_event *event = NULL;
180 struct vfsmount *mnt = NULL;
187 int idx; 181 int idx;
188 /* global tests shouldn't care about events on child only the specific event */ 182 /* global tests shouldn't care about events on child only the specific event */
189 __u32 test_mask = (mask & ~FS_EVENT_ON_CHILD); 183 __u32 test_mask = (mask & ~FS_EVENT_ON_CHILD);
@@ -198,10 +192,15 @@ void fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is, const
198 !(test_mask & fsnotify_vfsmount_mask)) 192 !(test_mask & fsnotify_vfsmount_mask))
199 return; 193 return;
200 194
195 if (data_is == FSNOTIFY_EVENT_PATH)
196 mnt = ((struct path *)data)->mnt;
197 else if (data_is == FSNOTIFY_EVENT_FILE)
198 mnt = ((struct file *)data)->f_path.mnt;
199
201 /* if this inode's directed listeners don't care and nothing on the vfsmount 200 /* if this inode's directed listeners don't care and nothing on the vfsmount
202 * listeners list cares, nothing to do */ 201 * listeners list cares, nothing to do */
203 if (!(test_mask & to_tell->i_fsnotify_mask) && 202 if (!(test_mask & to_tell->i_fsnotify_mask) &&
204 !needed_by_vfsmount(test_mask, data, data_is)) 203 !needed_by_vfsmount(test_mask, mnt))
205 return; 204 return;
206 205
207 /* 206 /*
@@ -214,16 +213,16 @@ void fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is, const
214 if (test_mask & to_tell->i_fsnotify_mask) { 213 if (test_mask & to_tell->i_fsnotify_mask) {
215 list_for_each_entry_rcu(group, &fsnotify_inode_groups, inode_group_list) { 214 list_for_each_entry_rcu(group, &fsnotify_inode_groups, inode_group_list) {
216 if (test_mask & group->mask) { 215 if (test_mask & group->mask) {
217 send_to_group(mask, group, data, data_is, 216 send_to_group(group, to_tell, NULL, mask, data, data_is,
218 file_name, cookie, &event, to_tell); 217 cookie, file_name, &event);
219 } 218 }
220 } 219 }
221 } 220 }
222 if (needed_by_vfsmount(test_mask, data, data_is)) { 221 if (needed_by_vfsmount(test_mask, mnt)) {
223 list_for_each_entry_rcu(group, &fsnotify_vfsmount_groups, vfsmount_group_list) { 222 list_for_each_entry_rcu(group, &fsnotify_vfsmount_groups, vfsmount_group_list) {
224 if (test_mask & group->mask) { 223 if (test_mask & group->mask) {
225 send_to_group(mask, group, data, data_is, 224 send_to_group(group, to_tell, mnt, mask, data, data_is,
226 file_name, cookie, &event, to_tell); 225 cookie, file_name, &event);
227 } 226 }
228 } 227 }
229 } 228 }
diff --git a/fs/notify/inotify/inotify_fsnotify.c b/fs/notify/inotify/inotify_fsnotify.c
index 0a0f5d0f0d0a..8075ae708ed4 100644
--- a/fs/notify/inotify/inotify_fsnotify.c
+++ b/fs/notify/inotify/inotify_fsnotify.c
@@ -141,7 +141,8 @@ static void inotify_freeing_mark(struct fsnotify_mark_entry *entry, struct fsnot
141} 141}
142 142
143static bool inotify_should_send_event(struct fsnotify_group *group, struct inode *inode, 143static bool inotify_should_send_event(struct fsnotify_group *group, struct inode *inode,
144 __u32 mask, void *data, int data_type) 144 struct vfsmount *mnt, __u32 mask, void *data,
145 int data_type)
145{ 146{
146 struct fsnotify_mark_entry *entry; 147 struct fsnotify_mark_entry *entry;
147 bool send; 148 bool send;
diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h
index dea48bee057d..c2a04b7e4fca 100644
--- a/include/linux/fsnotify_backend.h
+++ b/include/linux/fsnotify_backend.h
@@ -79,7 +79,8 @@ struct fsnotify_event_private_data;
79 */ 79 */
80struct fsnotify_ops { 80struct fsnotify_ops {
81 bool (*should_send_event)(struct fsnotify_group *group, struct inode *inode, 81 bool (*should_send_event)(struct fsnotify_group *group, struct inode *inode,
82 __u32 mask, void *data, int data_type); 82 struct vfsmount *mnt, __u32 mask, void *data,
83 int data_type);
83 int (*handle_event)(struct fsnotify_group *group, struct fsnotify_event *event); 84 int (*handle_event)(struct fsnotify_group *group, struct fsnotify_event *event);
84 void (*free_group_priv)(struct fsnotify_group *group); 85 void (*free_group_priv)(struct fsnotify_group *group);
85 void (*freeing_mark)(struct fsnotify_mark_entry *entry, struct fsnotify_group *group); 86 void (*freeing_mark)(struct fsnotify_mark_entry *entry, struct fsnotify_group *group);
diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c
index 04f16887406b..ecf0bf260d09 100644
--- a/kernel/audit_tree.c
+++ b/kernel/audit_tree.c
@@ -920,7 +920,8 @@ static void audit_tree_freeing_mark(struct fsnotify_mark_entry *entry, struct fs
920} 920}
921 921
922static bool audit_tree_send_event(struct fsnotify_group *group, struct inode *inode, 922static bool audit_tree_send_event(struct fsnotify_group *group, struct inode *inode,
923 __u32 mask, void *data, int data_type) 923 struct vfsmount *mnt, __u32 mask, void *data,
924 int data_type)
924{ 925{
925 return 0; 926 return 0;
926} 927}
diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c
index 83d5f9674cec..6304ee5d7642 100644
--- a/kernel/audit_watch.c
+++ b/kernel/audit_watch.c
@@ -514,7 +514,8 @@ void audit_remove_watch_rule(struct audit_krule *krule)
514} 514}
515 515
516static bool audit_watch_should_send_event(struct fsnotify_group *group, struct inode *inode, 516static bool audit_watch_should_send_event(struct fsnotify_group *group, struct inode *inode,
517 __u32 mask, void *data, int data_type) 517 struct vfsmount *mnt, __u32 mask, void *data,
518 int data_type)
518{ 519{
519 struct fsnotify_mark_entry *entry; 520 struct fsnotify_mark_entry *entry;
520 bool send; 521 bool send;