aboutsummaryrefslogtreecommitdiffstats
path: root/fs/notify/fsnotify.c
diff options
context:
space:
mode:
authorEric Paris <eparis@redhat.com>2010-07-28 10:18:39 -0400
committerEric Paris <eparis@redhat.com>2010-07-28 10:18:54 -0400
commitce8f76fb7320297ccbe7c950fd9a2d727dd6a5a0 (patch)
treefb870e9564bfef438e46ba3c39be2999e246b179 /fs/notify/fsnotify.c
parent613a807fe7c793ceb7d6f059773527a5a6c84a96 (diff)
fsnotify: pass both the vfsmount mark and inode mark
should_send_event() and handle_event() will both need to look up the inode event if they get a vfsmount event. Lets just pass both at the same time since we have them both after walking the lists in lockstep. Signed-off-by: Eric Paris <eparis@redhat.com>
Diffstat (limited to 'fs/notify/fsnotify.c')
-rw-r--r--fs/notify/fsnotify.c70
1 files changed, 48 insertions, 22 deletions
diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c
index cdaa51cb698c..090b64c3b4f9 100644
--- a/fs/notify/fsnotify.c
+++ b/fs/notify/fsnotify.c
@@ -141,28 +141,51 @@ void __fsnotify_parent(struct file *file, struct dentry *dentry, __u32 mask)
141EXPORT_SYMBOL_GPL(__fsnotify_parent); 141EXPORT_SYMBOL_GPL(__fsnotify_parent);
142 142
143static int send_to_group(struct inode *to_tell, struct vfsmount *mnt, 143static int send_to_group(struct inode *to_tell, struct vfsmount *mnt,
144 struct fsnotify_mark *mark, 144 struct fsnotify_mark *inode_mark,
145 __u32 mask, void *data, 145 struct fsnotify_mark *vfsmount_mark,
146 __u32 mask, void *data,
146 int data_is, u32 cookie, 147 int data_is, u32 cookie,
147 const unsigned char *file_name, 148 const unsigned char *file_name,
148 struct fsnotify_event **event) 149 struct fsnotify_event **event)
149{ 150{
150 struct fsnotify_group *group = mark->group; 151 struct fsnotify_group *group = inode_mark->group;
151 __u32 test_mask = (mask & ~FS_EVENT_ON_CHILD); 152 __u32 inode_test_mask = (mask & ~FS_EVENT_ON_CHILD);
153 __u32 vfsmount_test_mask = (mask & ~FS_EVENT_ON_CHILD);
152 154
153 pr_debug("%s: group=%p to_tell=%p mnt=%p mark=%p mask=%x data=%p" 155 pr_debug("%s: group=%p to_tell=%p mnt=%p mark=%p mask=%x data=%p"
154 " data_is=%d cookie=%d event=%p\n", __func__, group, to_tell, 156 " data_is=%d cookie=%d event=%p\n", __func__, group, to_tell,
155 mnt, mark, mask, data, data_is, cookie, *event); 157 mnt, inode_mark, mask, data, data_is, cookie, *event);
158
159 /* clear ignored on inode modification */
160 if (mask & FS_MODIFY) {
161 if (inode_mark &&
162 !(inode_mark->flags & FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY))
163 inode_mark->ignored_mask = 0;
164 if (vfsmount_mark &&
165 !(vfsmount_mark->flags & FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY))
166 vfsmount_mark->ignored_mask = 0;
167 }
156 168
157 if ((mask & FS_MODIFY) && 169 /* does the inode mark tell us to do something? */
158 !(mark->flags & FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY)) 170 if (inode_mark) {
159 mark->ignored_mask = 0; 171 inode_test_mask &= inode_mark->mask;
172 inode_test_mask &= ~inode_mark->ignored_mask;
173 }
160 174
161 if (!(test_mask & mark->mask & ~mark->ignored_mask)) 175 /* does the vfsmount_mark tell us to do something? */
176 if (vfsmount_mark) {
177 vfsmount_test_mask &= vfsmount_mark->mask;
178 vfsmount_test_mask &= ~vfsmount_mark->ignored_mask;
179 if (inode_mark)
180 vfsmount_test_mask &= ~inode_mark->ignored_mask;
181 }
182
183 if (!inode_test_mask && !vfsmount_test_mask)
162 return 0; 184 return 0;
163 185
164 if (group->ops->should_send_event(group, to_tell, mnt, mark, mask, 186 if (group->ops->should_send_event(group, to_tell, mnt, inode_mark,
165 data, data_is) == false) 187 vfsmount_mark, mask, data,
188 data_is) == false)
166 return 0; 189 return 0;
167 190
168 if (!*event) { 191 if (!*event) {
@@ -172,7 +195,7 @@ static int send_to_group(struct inode *to_tell, struct vfsmount *mnt,
172 if (!*event) 195 if (!*event)
173 return -ENOMEM; 196 return -ENOMEM;
174 } 197 }
175 return group->ops->handle_event(group, mark, *event); 198 return group->ops->handle_event(group, inode_mark, vfsmount_mark, *event);
176} 199}
177 200
178/* 201/*
@@ -213,14 +236,16 @@ int fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is,
213 236
214 if ((mask & FS_MODIFY) || 237 if ((mask & FS_MODIFY) ||
215 (test_mask & to_tell->i_fsnotify_mask)) 238 (test_mask & to_tell->i_fsnotify_mask))
216 inode_node = to_tell->i_fsnotify_marks.first; 239 inode_node = srcu_dereference(to_tell->i_fsnotify_marks.first,
240 &fsnotify_mark_srcu);
217 else 241 else
218 inode_node = NULL; 242 inode_node = NULL;
219 243
220 if (mnt) { 244 if (mnt) {
221 if ((mask & FS_MODIFY) || 245 if ((mask & FS_MODIFY) ||
222 (test_mask & mnt->mnt_fsnotify_mask)) 246 (test_mask & mnt->mnt_fsnotify_mask))
223 vfsmount_node = mnt->mnt_fsnotify_marks.first; 247 vfsmount_node = srcu_dereference(mnt->mnt_fsnotify_marks.first,
248 &fsnotify_mark_srcu);
224 else 249 else
225 vfsmount_node = NULL; 250 vfsmount_node = NULL;
226 } else { 251 } else {
@@ -245,26 +270,27 @@ int fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is,
245 270
246 if (inode_group < vfsmount_group) { 271 if (inode_group < vfsmount_group) {
247 /* handle inode */ 272 /* handle inode */
248 send_to_group(to_tell, NULL, inode_mark, mask, data, 273 send_to_group(to_tell, NULL, inode_mark, NULL, mask, data,
249 data_is, cookie, file_name, &event); 274 data_is, cookie, file_name, &event);
250 used_inode = true; 275 used_inode = true;
251 } else if (vfsmount_group < inode_group) { 276 } else if (vfsmount_group < inode_group) {
252 send_to_group(to_tell, mnt, vfsmount_mark, mask, data, 277 send_to_group(to_tell, mnt, NULL, vfsmount_mark, mask, data,
253 data_is, cookie, file_name, &event); 278 data_is, cookie, file_name, &event);
254 used_vfsmount = true; 279 used_vfsmount = true;
255 } else { 280 } else {
256 send_to_group(to_tell, mnt, vfsmount_mark, mask, data, 281 send_to_group(to_tell, mnt, inode_mark, vfsmount_mark,
257 data_is, cookie, file_name, &event); 282 mask, data, data_is, cookie, file_name,
283 &event);
258 used_vfsmount = true; 284 used_vfsmount = true;
259 send_to_group(to_tell, NULL, inode_mark, mask, data,
260 data_is, cookie, file_name, &event);
261 used_inode = true; 285 used_inode = true;
262 } 286 }
263 287
264 if (used_inode) 288 if (used_inode)
265 inode_node = inode_node->next; 289 inode_node = srcu_dereference(inode_node->next,
290 &fsnotify_mark_srcu);
266 if (used_vfsmount) 291 if (used_vfsmount)
267 vfsmount_node = vfsmount_node->next; 292 vfsmount_node = srcu_dereference(vfsmount_node->next,
293 &fsnotify_mark_srcu);
268 } 294 }
269 295
270 srcu_read_unlock(&fsnotify_mark_srcu, idx); 296 srcu_read_unlock(&fsnotify_mark_srcu, idx);