diff options
-rw-r--r-- | fs/notify/fsnotify.c | 5 | ||||
-rw-r--r-- | fs/notify/fsnotify.h | 9 | ||||
-rw-r--r-- | fs/notify/group.c | 107 | ||||
-rw-r--r-- | fs/notify/mark.c | 9 | ||||
-rw-r--r-- | include/linux/fsnotify_backend.h | 15 |
5 files changed, 2 insertions, 143 deletions
diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c index 9ba29ee747cf..1dd1fde1da08 100644 --- a/fs/notify/fsnotify.c +++ b/fs/notify/fsnotify.c | |||
@@ -219,11 +219,6 @@ 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 */ | 219 | /* global tests shouldn't care about events on child only the specific event */ |
220 | __u32 test_mask = (mask & ~FS_EVENT_ON_CHILD); | 220 | __u32 test_mask = (mask & ~FS_EVENT_ON_CHILD); |
221 | 221 | ||
222 | /* if no fsnotify listeners, nothing to do */ | ||
223 | if (list_empty(&fsnotify_inode_groups) && | ||
224 | list_empty(&fsnotify_vfsmount_groups)) | ||
225 | return 0; | ||
226 | |||
227 | if (mask & FS_MODIFY) | 222 | if (mask & FS_MODIFY) |
228 | __fsnotify_flush_ignored_mask(to_tell, data, data_is); | 223 | __fsnotify_flush_ignored_mask(to_tell, data, data_is); |
229 | 224 | ||
diff --git a/fs/notify/fsnotify.h b/fs/notify/fsnotify.h index b41dbf5a125c..85e7d2b431d9 100644 --- a/fs/notify/fsnotify.h +++ b/fs/notify/fsnotify.h | |||
@@ -6,11 +6,6 @@ | |||
6 | #include <linux/srcu.h> | 6 | #include <linux/srcu.h> |
7 | #include <linux/types.h> | 7 | #include <linux/types.h> |
8 | 8 | ||
9 | /* all groups which receive inode fsnotify events */ | ||
10 | extern struct list_head fsnotify_inode_groups; | ||
11 | /* all groups which receive vfsmount fsnotify events */ | ||
12 | extern struct list_head fsnotify_vfsmount_groups; | ||
13 | |||
14 | /* destroy all events sitting in this groups notification queue */ | 9 | /* destroy all events sitting in this groups notification queue */ |
15 | extern void fsnotify_flush_notify(struct fsnotify_group *group); | 10 | extern void fsnotify_flush_notify(struct fsnotify_group *group); |
16 | 11 | ||
@@ -28,10 +23,6 @@ extern int fsnotify_add_vfsmount_mark(struct fsnotify_mark *mark, | |||
28 | struct fsnotify_group *group, struct vfsmount *mnt, | 23 | struct fsnotify_group *group, struct vfsmount *mnt, |
29 | int allow_dups); | 24 | int allow_dups); |
30 | 25 | ||
31 | /* add a group to the inode group list */ | ||
32 | extern void fsnotify_add_inode_group(struct fsnotify_group *group); | ||
33 | /* add a group to the vfsmount group list */ | ||
34 | extern void fsnotify_add_vfsmount_group(struct fsnotify_group *group); | ||
35 | /* final kfree of a group */ | 26 | /* final kfree of a group */ |
36 | extern void fsnotify_final_destroy_group(struct fsnotify_group *group); | 27 | extern void fsnotify_final_destroy_group(struct fsnotify_group *group); |
37 | 28 | ||
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 | ||
diff --git a/fs/notify/mark.c b/fs/notify/mark.c index 236f29b066ed..325185e514bb 100644 --- a/fs/notify/mark.c +++ b/fs/notify/mark.c | |||
@@ -223,15 +223,6 @@ int fsnotify_add_mark(struct fsnotify_mark *mark, | |||
223 | BUG_ON(!inode && !mnt); | 223 | BUG_ON(!inode && !mnt); |
224 | 224 | ||
225 | /* | 225 | /* |
226 | * if this group isn't being testing for inode type events we need | ||
227 | * to start testing | ||
228 | */ | ||
229 | if (inode && unlikely(list_empty(&group->inode_group_list))) | ||
230 | fsnotify_add_inode_group(group); | ||
231 | else if (mnt && unlikely(list_empty(&group->vfsmount_group_list))) | ||
232 | fsnotify_add_vfsmount_group(group); | ||
233 | |||
234 | /* | ||
235 | * LOCKING ORDER!!!! | 226 | * LOCKING ORDER!!!! |
236 | * mark->lock | 227 | * mark->lock |
237 | * group->mark_lock | 228 | * group->mark_lock |
diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h index c4e7aab87461..2e7cc8c2a151 100644 --- a/include/linux/fsnotify_backend.h +++ b/include/linux/fsnotify_backend.h | |||
@@ -109,17 +109,6 @@ struct fsnotify_ops { | |||
109 | */ | 109 | */ |
110 | struct fsnotify_group { | 110 | struct fsnotify_group { |
111 | /* | 111 | /* |
112 | * global list of all groups receiving events from fsnotify. | ||
113 | * anchored by fsnotify_inode_groups and protected by either fsnotify_grp_mutex | ||
114 | * or fsnotify_grp_srcu depending on write vs read. | ||
115 | */ | ||
116 | struct list_head inode_group_list; | ||
117 | /* | ||
118 | * same as above except anchored by fsnotify_vfsmount_groups | ||
119 | */ | ||
120 | struct list_head vfsmount_group_list; | ||
121 | |||
122 | /* | ||
123 | * How the refcnt is used is up to each group. When the refcnt hits 0 | 112 | * How the refcnt is used is up to each group. When the refcnt hits 0 |
124 | * fsnotify will clean up all of the resources associated with this group. | 113 | * fsnotify will clean up all of the resources associated with this group. |
125 | * As an example, the dnotify group will always have a refcnt=1 and that | 114 | * As an example, the dnotify group will always have a refcnt=1 and that |
@@ -145,10 +134,6 @@ struct fsnotify_group { | |||
145 | * a group */ | 134 | * a group */ |
146 | struct list_head marks_list; /* all inode marks for this group */ | 135 | struct list_head marks_list; /* all inode marks for this group */ |
147 | 136 | ||
148 | /* prevents double list_del of group_list. protected by global fsnotify_grp_mutex */ | ||
149 | bool on_inode_group_list; | ||
150 | bool on_vfsmount_group_list; | ||
151 | |||
152 | /* groups can define private fields here or use the void *private */ | 137 | /* groups can define private fields here or use the void *private */ |
153 | union { | 138 | union { |
154 | void *private; | 139 | void *private; |