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>
This commit is contained in:
Родитель
4d92604cc9
Коммит
cb2d429faf
|
@ -463,8 +463,6 @@ SYSCALL_DEFINE3(fanotify_init, unsigned int, flags, unsigned int, event_f_flags,
|
||||||
|
|
||||||
if (event_f_flags)
|
if (event_f_flags)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (priority)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
if (!capable(CAP_SYS_ADMIN))
|
if (!capable(CAP_SYS_ADMIN))
|
||||||
return -EACCES;
|
return -EACCES;
|
||||||
|
@ -483,6 +481,8 @@ SYSCALL_DEFINE3(fanotify_init, unsigned int, flags, unsigned int, event_f_flags,
|
||||||
if (IS_ERR(group))
|
if (IS_ERR(group))
|
||||||
return PTR_ERR(group);
|
return PTR_ERR(group);
|
||||||
|
|
||||||
|
group->priority = priority;
|
||||||
|
|
||||||
fd = anon_inode_getfd("[fanotify]", &fanotify_fops, group, f_flags);
|
fd = anon_inode_getfd("[fanotify]", &fanotify_fops, group, f_flags);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
goto out_put_group;
|
goto out_put_group;
|
||||||
|
|
|
@ -89,10 +89,27 @@ void fsnotify_recalc_group_mask(struct fsnotify_group *group)
|
||||||
|
|
||||||
void fsnotify_add_vfsmount_group(struct fsnotify_group *group)
|
void fsnotify_add_vfsmount_group(struct fsnotify_group *group)
|
||||||
{
|
{
|
||||||
|
struct fsnotify_group *group_iter;
|
||||||
|
unsigned int priority = group->priority;
|
||||||
|
|
||||||
mutex_lock(&fsnotify_grp_mutex);
|
mutex_lock(&fsnotify_grp_mutex);
|
||||||
|
|
||||||
if (!group->on_vfsmount_group_list)
|
if (!group->on_vfsmount_group_list) {
|
||||||
|
list_for_each_entry(group_iter, &fsnotify_vfsmount_groups,
|
||||||
|
vfsmount_group_list) {
|
||||||
|
/* insert in front of this one? */
|
||||||
|
if (priority < group_iter->priority) {
|
||||||
|
/* list_add_tail() insert in front of group_iter */
|
||||||
|
list_add_tail_rcu(&group->inode_group_list,
|
||||||
|
&group_iter->inode_group_list);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* apparently we need to be the last entry */
|
||||||
list_add_tail_rcu(&group->vfsmount_group_list, &fsnotify_vfsmount_groups);
|
list_add_tail_rcu(&group->vfsmount_group_list, &fsnotify_vfsmount_groups);
|
||||||
|
}
|
||||||
|
out:
|
||||||
group->on_vfsmount_group_list = 1;
|
group->on_vfsmount_group_list = 1;
|
||||||
|
|
||||||
mutex_unlock(&fsnotify_grp_mutex);
|
mutex_unlock(&fsnotify_grp_mutex);
|
||||||
|
@ -100,10 +117,27 @@ void fsnotify_add_vfsmount_group(struct fsnotify_group *group)
|
||||||
|
|
||||||
void fsnotify_add_inode_group(struct fsnotify_group *group)
|
void fsnotify_add_inode_group(struct fsnotify_group *group)
|
||||||
{
|
{
|
||||||
|
struct fsnotify_group *group_iter;
|
||||||
|
unsigned int priority = group->priority;
|
||||||
|
|
||||||
mutex_lock(&fsnotify_grp_mutex);
|
mutex_lock(&fsnotify_grp_mutex);
|
||||||
|
|
||||||
if (!group->on_inode_group_list)
|
/* add to global group list, priority 0 first, UINT_MAX last */
|
||||||
|
if (!group->on_inode_group_list) {
|
||||||
|
list_for_each_entry(group_iter, &fsnotify_inode_groups,
|
||||||
|
inode_group_list) {
|
||||||
|
if (priority < group_iter->priority) {
|
||||||
|
/* list_add_tail() insert in front of group_iter */
|
||||||
|
list_add_tail_rcu(&group->inode_group_list,
|
||||||
|
&group_iter->inode_group_list);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* apparently we need to be the last entry */
|
||||||
list_add_tail_rcu(&group->inode_group_list, &fsnotify_inode_groups);
|
list_add_tail_rcu(&group->inode_group_list, &fsnotify_inode_groups);
|
||||||
|
}
|
||||||
|
out:
|
||||||
group->on_inode_group_list = 1;
|
group->on_inode_group_list = 1;
|
||||||
|
|
||||||
mutex_unlock(&fsnotify_grp_mutex);
|
mutex_unlock(&fsnotify_grp_mutex);
|
||||||
|
@ -226,6 +260,8 @@ struct fsnotify_group *fsnotify_alloc_group(const struct fsnotify_ops *ops)
|
||||||
spin_lock_init(&group->mark_lock);
|
spin_lock_init(&group->mark_lock);
|
||||||
INIT_LIST_HEAD(&group->marks_list);
|
INIT_LIST_HEAD(&group->marks_list);
|
||||||
|
|
||||||
|
group->priority = UINT_MAX;
|
||||||
|
|
||||||
group->ops = ops;
|
group->ops = ops;
|
||||||
|
|
||||||
return group;
|
return group;
|
||||||
|
|
|
@ -140,6 +140,7 @@ struct fsnotify_group {
|
||||||
* a group */
|
* a group */
|
||||||
struct list_head marks_list; /* all inode marks for this group */
|
struct list_head marks_list; /* all inode marks for this group */
|
||||||
|
|
||||||
|
unsigned int priority; /* order of this group compared to others */
|
||||||
/* prevents double list_del of group_list. protected by global fsnotify_grp_mutex */
|
/* prevents double list_del of group_list. protected by global fsnotify_grp_mutex */
|
||||||
bool on_inode_group_list;
|
bool on_inode_group_list;
|
||||||
bool on_vfsmount_group_list;
|
bool on_vfsmount_group_list;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче