Commit 02436668d98385f5b5d9ffb695a37dadf98ed8a8

Authored by Eric Paris
1 parent 43709a288e

fsnotify: remove global fsnotify groups lists

The global fsnotify groups lists were invented as a way to increase the
performance of fsnotify by shortcutting events which were not interesting.
With the changes to walk the object lists rather than global groups lists
these shortcuts are not useful.

Signed-off-by: Eric Paris <eparis@redhat.com>

Showing 5 changed files with 2 additions and 143 deletions Side-by-side Diff

fs/notify/fsnotify.c
... ... @@ -219,11 +219,6 @@
219 219 /* global tests shouldn't care about events on child only the specific event */
220 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 222 if (mask & FS_MODIFY)
228 223 __fsnotify_flush_ignored_mask(to_tell, data, data_is);
229 224  
fs/notify/fsnotify.h
... ... @@ -6,11 +6,6 @@
6 6 #include <linux/srcu.h>
7 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 9 /* destroy all events sitting in this groups notification queue */
15 10 extern void fsnotify_flush_notify(struct fsnotify_group *group);
16 11  
... ... @@ -28,10 +23,6 @@
28 23 struct fsnotify_group *group, struct vfsmount *mnt,
29 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 26 /* final kfree of a group */
36 27 extern void fsnotify_final_destroy_group(struct fsnotify_group *group);
37 28  
... ... @@ -28,67 +28,6 @@
28 28  
29 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 32 * Final freeing of a group
94 33 */
95 34  
... ... @@ -124,51 +63,12 @@
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 66 * Drop a reference to a group. Free it if it's through.
157 67 */
158 68 void fsnotify_put_group(struct fsnotify_group *group)
159 69 {
160   - if (!atomic_dec_and_mutex_lock(&group->refcnt, &fsnotify_grp_mutex))
161   - return;
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);
  70 + if (atomic_dec_and_test(&group->refcnt))
  71 + fsnotify_destroy_group(group);
172 72 }
173 73  
174 74 /*
... ... @@ -194,9 +94,6 @@
194 94 INIT_LIST_HEAD(&group->notification_list);
195 95 init_waitqueue_head(&group->notification_waitq);
196 96 group->max_events = UINT_MAX;
197   -
198   - INIT_LIST_HEAD(&group->inode_group_list);
199   - INIT_LIST_HEAD(&group->vfsmount_group_list);
200 97  
201 98 spin_lock_init(&group->mark_lock);
202 99 INIT_LIST_HEAD(&group->marks_list);
... ... @@ -223,15 +223,6 @@
223 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 226 * LOCKING ORDER!!!!
236 227 * mark->lock
237 228 * group->mark_lock
include/linux/fsnotify_backend.h
... ... @@ -109,17 +109,6 @@
109 109 */
110 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 112 * How the refcnt is used is up to each group. When the refcnt hits 0
124 113 * fsnotify will clean up all of the resources associated with this group.
125 114 * As an example, the dnotify group will always have a refcnt=1 and that
... ... @@ -144,10 +133,6 @@
144 133 * past the point of no return when freeing
145 134 * a group */
146 135 struct list_head marks_list; /* all inode marks for this group */
147   -
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 136  
152 137 /* groups can define private fields here or use the void *private */
153 138 union {