]> bbs.cooldavid.org Git - net-next-2.6.git/commitdiff
fsnotify: add group priorities
authorEric Paris <eparis@redhat.com>
Fri, 18 Dec 2009 02:24:34 +0000 (21:24 -0500)
committerEric Paris <eparis@redhat.com>
Wed, 28 Jul 2010 13:59:01 +0000 (09:59 -0400)
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>
fs/notify/fanotify/fanotify_user.c
fs/notify/group.c
include/linux/fsnotify_backend.h

index 9fe760baf69fcd35c9bd1e2cbc70d5045fad8815..84d3e2047de31792ed49ae8ee3430a44c2211567 100644 (file)
@@ -463,8 +463,6 @@ SYSCALL_DEFINE3(fanotify_init, unsigned int, flags, unsigned int, event_f_flags,
 
        if (event_f_flags)
                return -EINVAL;
-       if (priority)
-               return -EINVAL;
 
        if (!capable(CAP_SYS_ADMIN))
                return -EACCES;
@@ -483,6 +481,8 @@ SYSCALL_DEFINE3(fanotify_init, unsigned int, flags, unsigned int, event_f_flags,
        if (IS_ERR(group))
                return PTR_ERR(group);
 
+       group->priority = priority;
+
        fd = anon_inode_getfd("[fanotify]", &fanotify_fops, group, f_flags);
        if (fd < 0)
                goto out_put_group;
index 9e9eb406afdd40533b8e5073057f17d4a0bf1161..ada913fd4f7fbe9020ef709fab5d21be65385ce9 100644 (file)
@@ -89,10 +89,27 @@ void fsnotify_recalc_group_mask(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);
 
-       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);
+       }
+out:
        group->on_vfsmount_group_list = 1;
 
        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)
 {
+       struct fsnotify_group *group_iter;
+       unsigned int priority = group->priority;
+
        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);
+       }
+out:
        group->on_inode_group_list = 1;
 
        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);
        INIT_LIST_HEAD(&group->marks_list);
 
+       group->priority = UINT_MAX;
+
        group->ops = ops;
 
        return group;
index be4a36ed2008331fc6d4a20b0e55789c7f5c5b5d..8b2e095e5907dfc8f86919667570e936de663258 100644 (file)
@@ -140,6 +140,7 @@ struct fsnotify_group {
                                         * a 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 */
        bool on_inode_group_list;
        bool on_vfsmount_group_list;