diff options
author | Eric Paris <eparis@redhat.com> | 2010-07-28 10:18:39 -0400 |
---|---|---|
committer | Eric Paris <eparis@redhat.com> | 2010-07-28 10:18:54 -0400 |
commit | 84a5b68e8da1490906c11129756490a556ae2c19 (patch) | |
tree | 684be31165523f21dc844a6a56e84e23c04dba61 /fs | |
parent | 02436668d98385f5b5d9ffb695a37dadf98ed8a8 (diff) |
fsnotify: rework ignored mark flushing
currently ignored_mark clearing is done in a seperate list traversal
before the actual list traversal to send events. There is no need for
this. Do them at the same time.
Signed-off-by: Eric Paris <eparis@redhat.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/notify/fsnotify.c | 60 |
1 files changed, 11 insertions, 49 deletions
diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c index 1dd1fde1da08..0bb4aeb8e00f 100644 --- a/fs/notify/fsnotify.c +++ b/fs/notify/fsnotify.c | |||
@@ -140,36 +140,6 @@ void __fsnotify_parent(struct file *file, struct dentry *dentry, __u32 mask) | |||
140 | } | 140 | } |
141 | EXPORT_SYMBOL_GPL(__fsnotify_parent); | 141 | EXPORT_SYMBOL_GPL(__fsnotify_parent); |
142 | 142 | ||
143 | void __fsnotify_flush_ignored_mask(struct inode *inode, void *data, int data_is) | ||
144 | { | ||
145 | struct fsnotify_mark *mark; | ||
146 | struct hlist_node *node; | ||
147 | int idx; | ||
148 | |||
149 | idx = srcu_read_lock(&fsnotify_mark_srcu); | ||
150 | |||
151 | if (!hlist_empty(&inode->i_fsnotify_marks)) { | ||
152 | hlist_for_each_entry_rcu(mark, node, &inode->i_fsnotify_marks, i.i_list) { | ||
153 | if (!(mark->flags & FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY)) | ||
154 | mark->ignored_mask = 0; | ||
155 | } | ||
156 | } | ||
157 | |||
158 | if (data_is == FSNOTIFY_EVENT_FILE) { | ||
159 | struct vfsmount *mnt; | ||
160 | |||
161 | mnt = ((struct file *)data)->f_path.mnt; | ||
162 | if (mnt && !hlist_empty(&mnt->mnt_fsnotify_marks)) { | ||
163 | hlist_for_each_entry_rcu(mark, node, &mnt->mnt_fsnotify_marks, m.m_list) { | ||
164 | if (!(mark->flags & FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY)) | ||
165 | mark->ignored_mask = 0; | ||
166 | } | ||
167 | } | ||
168 | } | ||
169 | |||
170 | srcu_read_unlock(&fsnotify_mark_srcu, idx); | ||
171 | } | ||
172 | |||
173 | static int send_to_group(struct fsnotify_group *group, struct inode *to_tell, | 143 | static int send_to_group(struct fsnotify_group *group, struct inode *to_tell, |
174 | struct vfsmount *mnt, struct fsnotify_mark *mark, | 144 | struct vfsmount *mnt, struct fsnotify_mark *mark, |
175 | __u32 mask, void *data, int data_is, u32 cookie, | 145 | __u32 mask, void *data, int data_is, u32 cookie, |
@@ -193,14 +163,6 @@ static int send_to_group(struct fsnotify_group *group, struct inode *to_tell, | |||
193 | return group->ops->handle_event(group, mark, *event); | 163 | return group->ops->handle_event(group, mark, *event); |
194 | } | 164 | } |
195 | 165 | ||
196 | static bool needed_by_vfsmount(__u32 test_mask, struct vfsmount *mnt) | ||
197 | { | ||
198 | if (!mnt) | ||
199 | return false; | ||
200 | |||
201 | return (test_mask & mnt->mnt_fsnotify_mask); | ||
202 | } | ||
203 | |||
204 | /* | 166 | /* |
205 | * This is the main call to fsnotify. The VFS calls into hook specific functions | 167 | * This is the main call to fsnotify. The VFS calls into hook specific functions |
206 | * in linux/fsnotify.h. Those functions then in turn call here. Here will call | 168 | * in linux/fsnotify.h. Those functions then in turn call here. Here will call |
@@ -219,26 +181,21 @@ int fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is, | |||
219 | /* global tests shouldn't care about events on child only the specific event */ | 181 | /* global tests shouldn't care about events on child only the specific event */ |
220 | __u32 test_mask = (mask & ~FS_EVENT_ON_CHILD); | 182 | __u32 test_mask = (mask & ~FS_EVENT_ON_CHILD); |
221 | 183 | ||
222 | if (mask & FS_MODIFY) | ||
223 | __fsnotify_flush_ignored_mask(to_tell, data, data_is); | ||
224 | |||
225 | if (data_is == FSNOTIFY_EVENT_FILE) | 184 | if (data_is == FSNOTIFY_EVENT_FILE) |
226 | mnt = ((struct file *)data)->f_path.mnt; | 185 | mnt = ((struct file *)data)->f_path.mnt; |
227 | 186 | ||
228 | /* if this inode's directed listeners don't care and nothing on the vfsmount | ||
229 | * listeners list cares, nothing to do */ | ||
230 | if (!(test_mask & to_tell->i_fsnotify_mask) && | ||
231 | !needed_by_vfsmount(test_mask, mnt)) | ||
232 | return 0; | ||
233 | |||
234 | idx = srcu_read_lock(&fsnotify_mark_srcu); | 187 | idx = srcu_read_lock(&fsnotify_mark_srcu); |
235 | 188 | ||
236 | if (test_mask & to_tell->i_fsnotify_mask) { | 189 | if ((test_mask & to_tell->i_fsnotify_mask) || (mask & FS_MODIFY)) { |
237 | hlist_for_each_entry_rcu(mark, node, &to_tell->i_fsnotify_marks, i.i_list) { | 190 | hlist_for_each_entry_rcu(mark, node, &to_tell->i_fsnotify_marks, i.i_list) { |
238 | 191 | ||
239 | pr_debug("%s: inode_loop: mark=%p mark->mask=%x mark->ignored_mask=%x\n", | 192 | pr_debug("%s: inode_loop: mark=%p mark->mask=%x mark->ignored_mask=%x\n", |
240 | __func__, mark, mark->mask, mark->ignored_mask); | 193 | __func__, mark, mark->mask, mark->ignored_mask); |
241 | 194 | ||
195 | if ((mask & FS_MODIFY) && | ||
196 | !(mark->flags & FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY)) | ||
197 | mark->ignored_mask = 0; | ||
198 | |||
242 | if (test_mask & mark->mask & ~mark->ignored_mask) { | 199 | if (test_mask & mark->mask & ~mark->ignored_mask) { |
243 | group = mark->group; | 200 | group = mark->group; |
244 | if (!group) | 201 | if (!group) |
@@ -252,12 +209,17 @@ int fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is, | |||
252 | } | 209 | } |
253 | } | 210 | } |
254 | 211 | ||
255 | if (mnt && (test_mask & mnt->mnt_fsnotify_mask)) { | 212 | if (mnt && ((test_mask & mnt->mnt_fsnotify_mask) || |
213 | (mask & FS_MODIFY))) { | ||
256 | hlist_for_each_entry_rcu(mark, node, &mnt->mnt_fsnotify_marks, m.m_list) { | 214 | hlist_for_each_entry_rcu(mark, node, &mnt->mnt_fsnotify_marks, m.m_list) { |
257 | 215 | ||
258 | pr_debug("%s: mnt_loop: mark=%p mark->mask=%x mark->ignored_mask=%x\n", | 216 | pr_debug("%s: mnt_loop: mark=%p mark->mask=%x mark->ignored_mask=%x\n", |
259 | __func__, mark, mark->mask, mark->ignored_mask); | 217 | __func__, mark, mark->mask, mark->ignored_mask); |
260 | 218 | ||
219 | if ((mask & FS_MODIFY) && | ||
220 | !(mark->flags & FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY)) | ||
221 | mark->ignored_mask = 0; | ||
222 | |||
261 | if (test_mask & mark->mask & ~mark->ignored_mask) { | 223 | if (test_mask & mark->mask & ~mark->ignored_mask) { |
262 | group = mark->group; | 224 | group = mark->group; |
263 | if (!group) | 225 | if (!group) |