aboutsummaryrefslogtreecommitdiffstats
path: root/fs/notify
diff options
context:
space:
mode:
authorEric Paris <eparis@redhat.com>2009-12-17 21:24:34 -0500
committerEric Paris <eparis@redhat.com>2010-07-28 09:59:01 -0400
commitcb2d429faf2cae62d3c51e28099a181d5fe8c244 (patch)
tree401bc8d85e7228f868775269e6d97c3150f9a3a7 /fs/notify
parent4d92604cc90aa18bbbe0f6e23b7a9fdb612836d3 (diff)
fsnotify: add group priorities
This introduces an ordering to fsnotify groups. With purely asynchronous notification based "things" implementing fsnotify (inotify, dnotify) ordering isn't particularly important. But if people want to use fsnotify for the basis of sycronous notification or blocking notification ordering becomes important. eg. A Hierarchical Storage Management listener would need to get its event before an AV scanner could get its event (since the HSM would need to bring the data in for the AV scanner to scan.) Typically asynchronous notification would want to run after the AV scanner made any relevant access decisions so as to not send notification about an event that was denied. Signed-off-by: Eric Paris <eparis@redhat.com>
Diffstat (limited to 'fs/notify')
-rw-r--r--fs/notify/fanotify/fanotify_user.c4
-rw-r--r--fs/notify/group.c40
2 files changed, 40 insertions, 4 deletions
diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c
index 9fe760baf69f..84d3e2047de3 100644
--- a/fs/notify/fanotify/fanotify_user.c
+++ b/fs/notify/fanotify/fanotify_user.c
@@ -463,8 +463,6 @@ SYSCALL_DEFINE3(fanotify_init, unsigned int, flags, unsigned int, event_f_flags,
463 463
464 if (event_f_flags) 464 if (event_f_flags)
465 return -EINVAL; 465 return -EINVAL;
466 if (priority)
467 return -EINVAL;
468 466
469 if (!capable(CAP_SYS_ADMIN)) 467 if (!capable(CAP_SYS_ADMIN))
470 return -EACCES; 468 return -EACCES;
@@ -483,6 +481,8 @@ SYSCALL_DEFINE3(fanotify_init, unsigned int, flags, unsigned int, event_f_flags,
483 if (IS_ERR(group)) 481 if (IS_ERR(group))
484 return PTR_ERR(group); 482 return PTR_ERR(group);
485 483
484 group->priority = priority;
485
486 fd = anon_inode_getfd("[fanotify]", &fanotify_fops, group, f_flags); 486 fd = anon_inode_getfd("[fanotify]", &fanotify_fops, group, f_flags);
487 if (fd < 0) 487 if (fd < 0)
488 goto out_put_group; 488 goto out_put_group;
diff --git a/fs/notify/group.c b/fs/notify/group.c
index 9e9eb406afdd..ada913fd4f7f 100644
--- a/fs/notify/group.c
+++ b/fs/notify/group.c
@@ -89,10 +89,27 @@ void fsnotify_recalc_group_mask(struct fsnotify_group *group)
89 89
90void fsnotify_add_vfsmount_group(struct fsnotify_group *group) 90void fsnotify_add_vfsmount_group(struct fsnotify_group *group)
91{ 91{
92 struct fsnotify_group *group_iter;
93 unsigned int priority = group->priority;
94
92 mutex_lock(&fsnotify_grp_mutex); 95 mutex_lock(&fsnotify_grp_mutex);
93 96
94 if (!group->on_vfsmount_group_list) 97 if (!group->on_vfsmount_group_list) {
98 list_for_each_entry(group_iter, &fsnotify_vfsmount_groups,
99 vfsmount_group_list) {
100 /* insert in front of this one? */
101 if (priority < group_iter->priority) {
102 /* list_add_tail() insert in front of group_iter */
103 list_add_tail_rcu(&group->inode_group_list,
104 &group_iter->inode_group_list);
105 goto out;
106 }
107 }
108
109 /* apparently we need to be the last entry */
95 list_add_tail_rcu(&group->vfsmount_group_list, &fsnotify_vfsmount_groups); 110 list_add_tail_rcu(&group->vfsmount_group_list, &fsnotify_vfsmount_groups);
111 }
112out:
96 group->on_vfsmount_group_list = 1; 113 group->on_vfsmount_group_list = 1;
97 114
98 mutex_unlock(&fsnotify_grp_mutex); 115 mutex_unlock(&fsnotify_grp_mutex);
@@ -100,10 +117,27 @@ void fsnotify_add_vfsmount_group(struct fsnotify_group *group)
100 117
101void fsnotify_add_inode_group(struct fsnotify_group *group) 118void fsnotify_add_inode_group(struct fsnotify_group *group)
102{ 119{
120 struct fsnotify_group *group_iter;
121 unsigned int priority = group->priority;
122
103 mutex_lock(&fsnotify_grp_mutex); 123 mutex_lock(&fsnotify_grp_mutex);
104 124
105 if (!group->on_inode_group_list) 125 /* add to global group list, priority 0 first, UINT_MAX last */
126 if (!group->on_inode_group_list) {
127 list_for_each_entry(group_iter, &fsnotify_inode_groups,
128 inode_group_list) {
129 if (priority < group_iter->priority) {
130 /* list_add_tail() insert in front of group_iter */
131 list_add_tail_rcu(&group->inode_group_list,
132 &group_iter->inode_group_list);
133 goto out;
134 }
135 }
136
137 /* apparently we need to be the last entry */
106 list_add_tail_rcu(&group->inode_group_list, &fsnotify_inode_groups); 138 list_add_tail_rcu(&group->inode_group_list, &fsnotify_inode_groups);
139 }
140out:
107 group->on_inode_group_list = 1; 141 group->on_inode_group_list = 1;
108 142
109 mutex_unlock(&fsnotify_grp_mutex); 143 mutex_unlock(&fsnotify_grp_mutex);
@@ -226,6 +260,8 @@ struct fsnotify_group *fsnotify_alloc_group(const struct fsnotify_ops *ops)
226 spin_lock_init(&group->mark_lock); 260 spin_lock_init(&group->mark_lock);
227 INIT_LIST_HEAD(&group->marks_list); 261 INIT_LIST_HEAD(&group->marks_list);
228 262
263 group->priority = UINT_MAX;
264
229 group->ops = ops; 265 group->ops = ops;
230 266
231 return group; 267 return group;