diff options
Diffstat (limited to 'fs/notify/group.c')
-rw-r--r-- | fs/notify/group.c | 107 |
1 files changed, 2 insertions, 105 deletions
diff --git a/fs/notify/group.c b/fs/notify/group.c index fc0d966b270f..d309f38449cb 100644 --- a/fs/notify/group.c +++ b/fs/notify/group.c | |||
@@ -28,67 +28,6 @@ | |||
28 | 28 | ||
29 | #include <asm/atomic.h> | 29 | #include <asm/atomic.h> |
30 | 30 | ||
31 | /* protects writes to fsnotify_groups and fsnotify_mask */ | ||
32 | static DEFINE_MUTEX(fsnotify_grp_mutex); | ||
33 | /* all groups registered to receive inode filesystem notifications */ | ||
34 | LIST_HEAD(fsnotify_inode_groups); | ||
35 | /* all groups registered to receive mount point filesystem notifications */ | ||
36 | LIST_HEAD(fsnotify_vfsmount_groups); | ||
37 | |||
38 | void fsnotify_add_vfsmount_group(struct fsnotify_group *group) | ||
39 | { | ||
40 | struct fsnotify_group *group_iter; | ||
41 | |||
42 | mutex_lock(&fsnotify_grp_mutex); | ||
43 | |||
44 | if (!group->on_vfsmount_group_list) { | ||
45 | list_for_each_entry(group_iter, &fsnotify_vfsmount_groups, | ||
46 | vfsmount_group_list) { | ||
47 | /* insert in front of this one? */ | ||
48 | if (group < group_iter) { | ||
49 | /* list_add_tail() insert in front of group_iter */ | ||
50 | list_add_tail_rcu(&group->inode_group_list, | ||
51 | &group_iter->inode_group_list); | ||
52 | goto out; | ||
53 | } | ||
54 | } | ||
55 | |||
56 | /* apparently we need to be the last entry */ | ||
57 | list_add_tail_rcu(&group->vfsmount_group_list, &fsnotify_vfsmount_groups); | ||
58 | } | ||
59 | out: | ||
60 | group->on_vfsmount_group_list = 1; | ||
61 | |||
62 | mutex_unlock(&fsnotify_grp_mutex); | ||
63 | } | ||
64 | |||
65 | void fsnotify_add_inode_group(struct fsnotify_group *group) | ||
66 | { | ||
67 | struct fsnotify_group *group_iter; | ||
68 | |||
69 | mutex_lock(&fsnotify_grp_mutex); | ||
70 | |||
71 | /* add to global group list */ | ||
72 | if (!group->on_inode_group_list) { | ||
73 | list_for_each_entry(group_iter, &fsnotify_inode_groups, | ||
74 | inode_group_list) { | ||
75 | if (group < group_iter) { | ||
76 | /* list_add_tail() insert in front of group_iter */ | ||
77 | list_add_tail_rcu(&group->inode_group_list, | ||
78 | &group_iter->inode_group_list); | ||
79 | goto out; | ||
80 | } | ||
81 | } | ||
82 | |||
83 | /* apparently we need to be the last entry */ | ||
84 | list_add_tail_rcu(&group->inode_group_list, &fsnotify_inode_groups); | ||
85 | } | ||
86 | out: | ||
87 | group->on_inode_group_list = 1; | ||
88 | |||
89 | mutex_unlock(&fsnotify_grp_mutex); | ||
90 | } | ||
91 | |||
92 | /* | 31 | /* |
93 | * Final freeing of a group | 32 | * Final freeing of a group |
94 | */ | 33 | */ |
@@ -124,51 +63,12 @@ static void fsnotify_destroy_group(struct fsnotify_group *group) | |||
124 | } | 63 | } |
125 | 64 | ||
126 | /* | 65 | /* |
127 | * Remove this group from the global list of groups that will get events | ||
128 | * this can be done even if there are still references and things still using | ||
129 | * this group. This just stops the group from getting new events. | ||
130 | */ | ||
131 | static void __fsnotify_evict_group(struct fsnotify_group *group) | ||
132 | { | ||
133 | BUG_ON(!mutex_is_locked(&fsnotify_grp_mutex)); | ||
134 | |||
135 | if (group->on_inode_group_list) | ||
136 | list_del_rcu(&group->inode_group_list); | ||
137 | group->on_inode_group_list = 0; | ||
138 | if (group->on_vfsmount_group_list) | ||
139 | list_del_rcu(&group->vfsmount_group_list); | ||
140 | group->on_vfsmount_group_list = 0; | ||
141 | } | ||
142 | |||
143 | /* | ||
144 | * Called when a group is no longer interested in getting events. This can be | ||
145 | * used if a group is misbehaving or if for some reason a group should no longer | ||
146 | * get any filesystem events. | ||
147 | */ | ||
148 | void fsnotify_evict_group(struct fsnotify_group *group) | ||
149 | { | ||
150 | mutex_lock(&fsnotify_grp_mutex); | ||
151 | __fsnotify_evict_group(group); | ||
152 | mutex_unlock(&fsnotify_grp_mutex); | ||
153 | } | ||
154 | |||
155 | /* | ||
156 | * Drop a reference to a group. Free it if it's through. | 66 | * Drop a reference to a group. Free it if it's through. |
157 | */ | 67 | */ |
158 | void fsnotify_put_group(struct fsnotify_group *group) | 68 | void fsnotify_put_group(struct fsnotify_group *group) |
159 | { | 69 | { |
160 | if (!atomic_dec_and_mutex_lock(&group->refcnt, &fsnotify_grp_mutex)) | 70 | if (atomic_dec_and_test(&group->refcnt)) |
161 | return; | 71 | fsnotify_destroy_group(group); |
162 | |||
163 | /* | ||
164 | * OK, now we know that there's no other users *and* we hold mutex, | ||
165 | * so no new references will appear | ||
166 | */ | ||
167 | __fsnotify_evict_group(group); | ||
168 | |||
169 | mutex_unlock(&fsnotify_grp_mutex); | ||
170 | |||
171 | fsnotify_destroy_group(group); | ||
172 | } | 72 | } |
173 | 73 | ||
174 | /* | 74 | /* |
@@ -195,9 +95,6 @@ struct fsnotify_group *fsnotify_alloc_group(const struct fsnotify_ops *ops) | |||
195 | init_waitqueue_head(&group->notification_waitq); | 95 | init_waitqueue_head(&group->notification_waitq); |
196 | group->max_events = UINT_MAX; | 96 | group->max_events = UINT_MAX; |
197 | 97 | ||
198 | INIT_LIST_HEAD(&group->inode_group_list); | ||
199 | INIT_LIST_HEAD(&group->vfsmount_group_list); | ||
200 | |||
201 | spin_lock_init(&group->mark_lock); | 98 | spin_lock_init(&group->mark_lock); |
202 | INIT_LIST_HEAD(&group->marks_list); | 99 | INIT_LIST_HEAD(&group->marks_list); |
203 | 100 | ||