diff options
author | Eric Paris <eparis@redhat.com> | 2010-07-28 10:18:38 -0400 |
---|---|---|
committer | Eric Paris <eparis@redhat.com> | 2010-07-28 10:18:52 -0400 |
commit | 75c1be487a690db43da2c1234fcacd84c982803c (patch) | |
tree | b38ce47f157d3b0eff7ac6eb4756a4b390ac35ae /fs/notify/group.c | |
parent | 700307a29ad61090dcf1d45f8f4a135f5e9211ae (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.c | 16 |
1 files changed, 5 insertions, 11 deletions
diff --git a/fs/notify/group.c b/fs/notify/group.c index 7ac65ed4735b..48d3a6d6e47a 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 */ |
32 | static DEFINE_MUTEX(fsnotify_grp_mutex); | 32 | static DEFINE_MUTEX(fsnotify_grp_mutex); |
33 | /* protects reads while running the fsnotify_groups list */ | ||
34 | struct srcu_struct fsnotify_grp_srcu; | ||
35 | /* all groups registered to receive inode filesystem notifications */ | 33 | /* all groups registered to receive inode filesystem notifications */ |
36 | LIST_HEAD(fsnotify_inode_groups); | 34 | LIST_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(); |