aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/notify/fsnotify.c5
-rw-r--r--fs/notify/fsnotify.h9
-rw-r--r--fs/notify/group.c107
-rw-r--r--fs/notify/mark.c9
-rw-r--r--include/linux/fsnotify_backend.h15
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 */
10extern struct list_head fsnotify_inode_groups;
11/* all groups which receive vfsmount fsnotify events */
12extern 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 */
15extern void fsnotify_flush_notify(struct fsnotify_group *group); 10extern 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 */
32extern void fsnotify_add_inode_group(struct fsnotify_group *group);
33/* add a group to the vfsmount group list */
34extern void fsnotify_add_vfsmount_group(struct fsnotify_group *group);
35/* final kfree of a group */ 26/* final kfree of a group */
36extern void fsnotify_final_destroy_group(struct fsnotify_group *group); 27extern 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 */
32static DEFINE_MUTEX(fsnotify_grp_mutex);
33/* all groups registered to receive inode filesystem notifications */
34LIST_HEAD(fsnotify_inode_groups);
35/* all groups registered to receive mount point filesystem notifications */
36LIST_HEAD(fsnotify_vfsmount_groups);
37
38void 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 }
59out:
60 group->on_vfsmount_group_list = 1;
61
62 mutex_unlock(&fsnotify_grp_mutex);
63}
64
65void 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 }
86out:
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 */
131static 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 */
148void 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 */
158void fsnotify_put_group(struct fsnotify_group *group) 68void 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 */
110struct fsnotify_group { 110struct 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;