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 | |
| 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>
| -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) |
