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; |
