diff options
-rw-r--r-- | fs/notify/fanotify/fanotify_user.c | 4 | ||||
-rw-r--r-- | fs/notify/group.c | 40 | ||||
-rw-r--r-- | include/linux/fsnotify_backend.h | 1 |
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 | ||
90 | void fsnotify_add_vfsmount_group(struct fsnotify_group *group) | 90 | void 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 | } | ||
112 | out: | ||
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 | ||
101 | void fsnotify_add_inode_group(struct fsnotify_group *group) | 118 | void 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 | } | ||
140 | out: | ||
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; |