aboutsummaryrefslogtreecommitdiffstats
path: root/fs/notify/group.c
diff options
context:
space:
mode:
authorEric Paris <eparis@redhat.com>2009-12-17 21:24:23 -0500
committerEric Paris <eparis@redhat.com>2010-07-28 09:58:52 -0400
commit7131485a93679ff9a543b74df280cfd119eb03ca (patch)
treed5d635cb37f77ef7ff8942e15de4c45f3fded940 /fs/notify/group.c
parent4ca763523e040dc61191d4866a82981a5d30a4e9 (diff)
fsnotify: mount point listeners list and global mask
currently all of the notification systems implemented select which inodes they care about and receive messages only about those inodes (or the children of those inodes.) This patch begins to flesh out fsnotify support for the concept of listeners that want to hear notification for an inode accessed below a given monut point. This patch implements a second list of fsnotify groups to hold these types of groups and a second global mask to hold the events of interest for this type of group. The reason we want a second group list and mask is because the inode based notification should_send_event support which makes each group look for a mark on the given inode. With one nfsmount listener that means that every group would have to take the inode->i_lock, look for their mark, not find one, and return for every operation. By seperating vfsmount from inode listeners only when there is a inode listener will the inode groups have to look for their mark and take the inode lock. vfsmount listeners will have to grab the lock and look for a mark but there should be fewer of them, and one vfsmount listener won't cause the i_lock to be grabbed and released for every fsnotify group on every io operation. Signed-off-by: Eric Paris <eparis@redhat.com>
Diffstat (limited to 'fs/notify/group.c')
-rw-r--r--fs/notify/group.c33
1 files changed, 29 insertions, 4 deletions
diff --git a/fs/notify/group.c b/fs/notify/group.c
index 34fccbd2809c..aa4654fe6ec2 100644
--- a/fs/notify/group.c
+++ b/fs/notify/group.c
@@ -32,10 +32,14 @@
32static DEFINE_MUTEX(fsnotify_grp_mutex); 32static DEFINE_MUTEX(fsnotify_grp_mutex);
33/* protects reads while running the fsnotify_groups list */ 33/* protects reads while running the fsnotify_groups list */
34struct srcu_struct fsnotify_grp_srcu; 34struct srcu_struct fsnotify_grp_srcu;
35/* all groups registered to receive filesystem notifications */ 35/* all groups registered to receive inode filesystem notifications */
36LIST_HEAD(fsnotify_inode_groups); 36LIST_HEAD(fsnotify_inode_groups);
37/* all groups registered to receive mount point filesystem notifications */
38LIST_HEAD(fsnotify_vfsmount_groups);
37/* bitwise OR of all events (FS_*) interesting to some group on this system */ 39/* bitwise OR of all events (FS_*) interesting to some group on this system */
38__u32 fsnotify_inode_mask; 40__u32 fsnotify_inode_mask;
41/* bitwise OR of all events (FS_*) interesting to some group on this system */
42__u32 fsnotify_vfsmount_mask;
39 43
40/* 44/*
41 * When a new group registers or changes it's set of interesting events 45 * When a new group registers or changes it's set of interesting events
@@ -44,14 +48,20 @@ __u32 fsnotify_inode_mask;
44void fsnotify_recalc_global_mask(void) 48void fsnotify_recalc_global_mask(void)
45{ 49{
46 struct fsnotify_group *group; 50 struct fsnotify_group *group;
47 __u32 mask = 0; 51 __u32 inode_mask = 0;
52 __u32 vfsmount_mask = 0;
48 int idx; 53 int idx;
49 54
50 idx = srcu_read_lock(&fsnotify_grp_srcu); 55 idx = srcu_read_lock(&fsnotify_grp_srcu);
51 list_for_each_entry_rcu(group, &fsnotify_inode_groups, inode_group_list) 56 list_for_each_entry_rcu(group, &fsnotify_inode_groups, inode_group_list)
52 mask |= group->mask; 57 inode_mask |= group->mask;
58 list_for_each_entry_rcu(group, &fsnotify_vfsmount_groups, vfsmount_group_list)
59 vfsmount_mask |= group->mask;
60
53 srcu_read_unlock(&fsnotify_grp_srcu, idx); 61 srcu_read_unlock(&fsnotify_grp_srcu, idx);
54 fsnotify_inode_mask = mask; 62
63 fsnotify_inode_mask = inode_mask;
64 fsnotify_vfsmount_mask = vfsmount_mask;
55} 65}
56 66
57/* 67/*
@@ -77,6 +87,17 @@ void fsnotify_recalc_group_mask(struct fsnotify_group *group)
77 fsnotify_recalc_global_mask(); 87 fsnotify_recalc_global_mask();
78} 88}
79 89
90void fsnotify_add_vfsmount_group(struct fsnotify_group *group)
91{
92 mutex_lock(&fsnotify_grp_mutex);
93
94 if (!group->on_vfsmount_group_list)
95 list_add_tail_rcu(&group->vfsmount_group_list, &fsnotify_vfsmount_groups);
96 group->on_vfsmount_group_list = 1;
97
98 mutex_unlock(&fsnotify_grp_mutex);
99}
100
80void fsnotify_add_inode_group(struct fsnotify_group *group) 101void fsnotify_add_inode_group(struct fsnotify_group *group)
81{ 102{
82 mutex_lock(&fsnotify_grp_mutex); 103 mutex_lock(&fsnotify_grp_mutex);
@@ -132,6 +153,9 @@ static void __fsnotify_evict_group(struct fsnotify_group *group)
132 if (group->on_inode_group_list) 153 if (group->on_inode_group_list)
133 list_del_rcu(&group->inode_group_list); 154 list_del_rcu(&group->inode_group_list);
134 group->on_inode_group_list = 0; 155 group->on_inode_group_list = 0;
156 if (group->on_vfsmount_group_list)
157 list_del_rcu(&group->vfsmount_group_list);
158 group->on_vfsmount_group_list = 0;
135} 159}
136 160
137/* 161/*
@@ -197,6 +221,7 @@ struct fsnotify_group *fsnotify_alloc_group(const struct fsnotify_ops *ops)
197 group->max_events = UINT_MAX; 221 group->max_events = UINT_MAX;
198 222
199 INIT_LIST_HEAD(&group->inode_group_list); 223 INIT_LIST_HEAD(&group->inode_group_list);
224 INIT_LIST_HEAD(&group->vfsmount_group_list);
200 225
201 spin_lock_init(&group->mark_lock); 226 spin_lock_init(&group->mark_lock);
202 INIT_LIST_HEAD(&group->mark_entries); 227 INIT_LIST_HEAD(&group->mark_entries);