fsnotify: implement ordering between notifiers
authorEric Paris <eparis@redhat.com>
Thu, 28 Oct 2010 21:21:56 +0000 (17:21 -0400)
committerEric Paris <eparis@redhat.com>
Thu, 28 Oct 2010 21:22:13 +0000 (17:22 -0400)
fanotify needs to be able to specify that some groups get events before
others.  They use this idea to make sure that a hierarchical storage
manager gets access to files before programs which actually use them.  This
is purely infrastructure.  Everything will have a priority of 0, but the
infrastructure will exist for it to be non-zero.

Signed-off-by: Eric Paris <eparis@redhat.com>
fs/notify/inode_mark.c
fs/notify/vfsmount_mark.c
include/linux/fsnotify_backend.h

index 21ed10660b80770c34eb136a311254330568fac2..4c29fcf557d13d21100030c31ab98aa44b555a62 100644 (file)
@@ -177,7 +177,8 @@ void fsnotify_set_inode_mark_mask_locked(struct fsnotify_mark *mark,
  * Attach an initialized mark to a given inode.
  * These marks may be used for the fsnotify backend to determine which
  * event types should be delivered to which group and for which inodes.  These
- * marks are ordered according to the group's location in memory.
+ * marks are ordered according to priority, highest number first, and then by
+ * the group's location in memory.
  */
 int fsnotify_add_inode_mark(struct fsnotify_mark *mark,
                            struct fsnotify_group *group, struct inode *inode,
@@ -211,7 +212,11 @@ int fsnotify_add_inode_mark(struct fsnotify_mark *mark,
                        goto out;
                }
 
-               if (mark->group < lmark->group)
+               if (mark->group->priority < lmark->group->priority)
+                       continue;
+
+               if ((mark->group->priority == lmark->group->priority) &&
+                   (mark->group < lmark->group))
                        continue;
 
                hlist_add_before_rcu(&mark->i.i_list, &lmark->i.i_list);
index 56772b578fbd546d62a199ad25f6b1dec859e660..85eebff6d0d7de00928c5281e7418688c2265907 100644 (file)
@@ -169,7 +169,11 @@ int fsnotify_add_vfsmount_mark(struct fsnotify_mark *mark,
                        goto out;
                }
 
-               if (mark->group < lmark->group)
+               if (mark->group->priority < lmark->group->priority)
+                       continue;
+
+               if ((mark->group->priority == lmark->group->priority) &&
+                   (mark->group < lmark->group))
                        continue;
 
                hlist_add_before_rcu(&mark->m.m_list, &lmark->m.m_list);
index e40190d1687813d5c86e2a1b9e414e48fcf22595..825329534162613362f07830cd60ba95bd0fd2c9 100644 (file)
@@ -129,6 +129,14 @@ struct fsnotify_group {
        wait_queue_head_t notification_waitq;   /* read() on the notification file blocks on this waitq */
        unsigned int q_len;                     /* events on the queue */
        unsigned int max_events;                /* maximum events allowed on the list */
+       /*
+        * Valid fsnotify group priorities.  Events are send in order from highest
+        * priority to lowest priority.  We default to the lowest priority.
+        */
+       #define FS_PRIO_0       0 /* normal notifiers, no permissions */
+       #define FS_PRIO_1       1 /* fanotify content based access control */
+       #define FS_PRIO_2       2 /* fanotify pre-content access */
+       unsigned int priority;
 
        /* stores all fastpath marks assoc with this group so they can be cleaned on unregister */
        spinlock_t mark_lock;           /* protect marks_list */