aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/notify/fanotify/fanotify_user.c4
-rw-r--r--fs/notify/group.c40
-rw-r--r--include/linux/fsnotify_backend.h1
3 files changed, 41 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;
diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h
index be4a36ed2008..8b2e095e5907 100644
--- a/include/linux/fsnotify_backend.h
+++ b/include/linux/fsnotify_backend.h
@@ -140,6 +140,7 @@ struct fsnotify_group {
140 * a group */ 140 * a group */
141 struct list_head marks_list; /* all inode marks for this group */ 141 struct list_head marks_list; /* all inode marks for this group */
142 142
143 unsigned int priority; /* order of this group compared to others */
143 /* prevents double list_del of group_list. protected by global fsnotify_grp_mutex */ 144 /* prevents double list_del of group_list. protected by global fsnotify_grp_mutex */
144 bool on_inode_group_list; 145 bool on_inode_group_list;
145 bool on_vfsmount_group_list; 146 bool on_vfsmount_group_list;