aboutsummaryrefslogtreecommitdiffstats
path: root/fs/notify/group.c
diff options
context:
space:
mode:
authorEric Paris <eparis@redhat.com>2010-07-28 10:18:38 -0400
committerEric Paris <eparis@redhat.com>2010-07-28 10:18:52 -0400
commit75c1be487a690db43da2c1234fcacd84c982803c (patch)
treeb38ce47f157d3b0eff7ac6eb4756a4b390ac35ae /fs/notify/group.c
parent700307a29ad61090dcf1d45f8f4a135f5e9211ae (diff)
fsnotify: srcu to protect read side of inode and vfsmount locks
Currently reading the inode->i_fsnotify_marks or vfsmount->mnt_fsnotify_marks lists are protected by a spinlock on both the read and the write side. This patch protects the read side of those lists with a new single srcu. Signed-off-by: Eric Paris <eparis@redhat.com>
Diffstat (limited to 'fs/notify/group.c')
-rw-r--r--fs/notify/group.c16
1 files changed, 5 insertions, 11 deletions
diff --git a/fs/notify/group.c b/fs/notify/group.c
index 7ac65ed4735..48d3a6d6e47 100644
--- a/fs/notify/group.c
+++ b/fs/notify/group.c
@@ -30,8 +30,6 @@
30 30
31/* protects writes to fsnotify_groups and fsnotify_mask */ 31/* protects writes to fsnotify_groups and fsnotify_mask */
32static DEFINE_MUTEX(fsnotify_grp_mutex); 32static DEFINE_MUTEX(fsnotify_grp_mutex);
33/* protects reads while running the fsnotify_groups list */
34struct srcu_struct fsnotify_grp_srcu;
35/* all groups registered to receive inode filesystem notifications */ 33/* all groups registered to receive inode filesystem notifications */
36LIST_HEAD(fsnotify_inode_groups); 34LIST_HEAD(fsnotify_inode_groups);
37/* all groups registered to receive mount point filesystem notifications */ 35/* all groups registered to receive mount point filesystem notifications */
@@ -50,18 +48,17 @@ void fsnotify_recalc_global_mask(void)
50 struct fsnotify_group *group; 48 struct fsnotify_group *group;
51 __u32 inode_mask = 0; 49 __u32 inode_mask = 0;
52 __u32 vfsmount_mask = 0; 50 __u32 vfsmount_mask = 0;
53 int idx;
54 51
55 idx = srcu_read_lock(&fsnotify_grp_srcu); 52 mutex_lock(&fsnotify_grp_mutex);
56 list_for_each_entry_rcu(group, &fsnotify_inode_groups, inode_group_list) 53 list_for_each_entry_rcu(group, &fsnotify_inode_groups, inode_group_list)
57 inode_mask |= group->mask; 54 inode_mask |= group->mask;
58 list_for_each_entry_rcu(group, &fsnotify_vfsmount_groups, vfsmount_group_list) 55 list_for_each_entry_rcu(group, &fsnotify_vfsmount_groups, vfsmount_group_list)
59 vfsmount_mask |= group->mask; 56 vfsmount_mask |= group->mask;
60
61 srcu_read_unlock(&fsnotify_grp_srcu, idx);
62 57
63 fsnotify_inode_mask = inode_mask; 58 fsnotify_inode_mask = inode_mask;
64 fsnotify_vfsmount_mask = vfsmount_mask; 59 fsnotify_vfsmount_mask = vfsmount_mask;
60
61 mutex_unlock(&fsnotify_grp_mutex);
65} 62}
66 63
67/* 64/*
@@ -168,6 +165,8 @@ static void fsnotify_destroy_group(struct fsnotify_group *group)
168 /* clear all inode marks for this group */ 165 /* clear all inode marks for this group */
169 fsnotify_clear_marks_by_group(group); 166 fsnotify_clear_marks_by_group(group);
170 167
168 synchronize_srcu(&fsnotify_mark_srcu);
169
171 /* past the point of no return, matches the initial value of 1 */ 170 /* past the point of no return, matches the initial value of 1 */
172 if (atomic_dec_and_test(&group->num_marks)) 171 if (atomic_dec_and_test(&group->num_marks))
173 fsnotify_final_destroy_group(group); 172 fsnotify_final_destroy_group(group);
@@ -216,12 +215,7 @@ void fsnotify_put_group(struct fsnotify_group *group)
216 */ 215 */
217 __fsnotify_evict_group(group); 216 __fsnotify_evict_group(group);
218 217
219 /*
220 * now it's off the list, so the only thing we might care about is
221 * srcu access....
222 */
223 mutex_unlock(&fsnotify_grp_mutex); 218 mutex_unlock(&fsnotify_grp_mutex);
224 synchronize_srcu(&fsnotify_grp_srcu);
225 219
226 /* and now it is really dead. _Nothing_ could be seeing it */ 220 /* and now it is really dead. _Nothing_ could be seeing it */
227 fsnotify_recalc_global_mask(); 221 fsnotify_recalc_global_mask();