fanotify: use both marks when possible
Eric Paris [Wed, 28 Jul 2010 14:18:39 +0000 (10:18 -0400)]
fanotify currently, when given a vfsmount_mark will look up (if it exists)
the corresponding inode mark.  This patch drops that lookup and uses the
mark provided.

Signed-off-by: Eric Paris <eparis@redhat.com>

fs/notify/dnotify/dnotify.c
fs/notify/fanotify/fanotify.c
fs/notify/fsnotify.c
fs/notify/inotify/inotify_fsnotify.c
include/linux/fsnotify_backend.h
kernel/audit_tree.c
kernel/audit_watch.c

index bda588b..3344bdd 100644 (file)
@@ -128,7 +128,7 @@ static int dnotify_handle_event(struct fsnotify_group *group,
  * userspace notification for that pair.
  */
 static bool dnotify_should_send_event(struct fsnotify_group *group,
-                                     struct inode *inode, struct vfsmount *mnt,
+                                     struct inode *inode,
                                      struct fsnotify_mark *inode_mark,
                                      struct fsnotify_mark *vfsmount_mark,
                                      __u32 mask, void *data, int data_type)
index ef4fa4a..eb8f73c 100644 (file)
@@ -153,59 +153,20 @@ static int fanotify_handle_event(struct fsnotify_group *group,
        return ret;
 }
 
-static bool should_send_vfsmount_event(struct fsnotify_group *group,
-                                      struct vfsmount *mnt,
-                                      struct inode *inode,
-                                      struct fsnotify_mark *mnt_mark,
-                                      __u32 mask)
-{
-       struct fsnotify_mark *inode_mark;
-
-       pr_debug("%s: group=%p vfsmount=%p mark=%p mask=%x\n",
-                __func__, group, mnt, mnt_mark, mask);
-
-       mask &= mnt_mark->mask;
-       mask &= ~mnt_mark->ignored_mask;
-
-       if (mask) {
-               inode_mark = fsnotify_find_inode_mark(group, inode);
-               if (inode_mark) {
-                       mask &= ~inode_mark->ignored_mask;
-                       fsnotify_put_mark(inode_mark);
-               }
-       }
-
-       return mask;
-}
-
-static bool should_send_inode_event(struct fsnotify_group *group,
-                                   struct inode *inode,
-                                   struct fsnotify_mark *mark,
-                                   __u32 mask)
-{
-       pr_debug("%s: group=%p inode=%p mark=%p mask=%x\n",
-                __func__, group, inode, mark, mask);
-
-       /*
-        * if the event is for a child and this inode doesn't care about
-        * events on the child, don't send it!
-        */
-       if ((mask & FS_EVENT_ON_CHILD) &&
-           !(mark->mask & FS_EVENT_ON_CHILD))
-               return false;
-       else
-               return true;
-}
-
 static bool fanotify_should_send_event(struct fsnotify_group *group,
                                       struct inode *to_tell,
-                                      struct vfsmount *mnt,
                                       struct fsnotify_mark *inode_mark,
-                                      struct fsnotify_mark *vfsmount_mark,
-                                      __u32 mask, void *data, int data_type)
+                                      struct fsnotify_mark *vfsmnt_mark,
+                                      __u32 event_mask, void *data, int data_type)
 {
-       pr_debug("%s: group=%p to_tell=%p mnt=%p mask=%x data=%p data_type=%d\n",
-                __func__, group, to_tell, mnt, mask, data, data_type);
+       __u32 marks_mask, marks_ignored_mask;
+
+       pr_debug("%s: group=%p to_tell=%p inode_mark=%p vfsmnt_mark=%p "
+                "mask=%x data=%p data_type=%d\n", __func__, group, to_tell,
+                inode_mark, vfsmnt_mark, event_mask, data, data_type);
+
+       pr_debug("%s: group=%p vfsmount_mark=%p inode_mark=%p mask=%x\n",
+                __func__, group, vfsmnt_mark, inode_mark, event_mask);
 
        /* sorry, fanotify only gives a damn about files and dirs */
        if (!S_ISREG(to_tell->i_mode) &&
@@ -216,11 +177,30 @@ static bool fanotify_should_send_event(struct fsnotify_group *group,
        if (data_type != FSNOTIFY_EVENT_FILE)
                return false;
 
-       if (mnt)
-               return should_send_vfsmount_event(group, mnt, to_tell,
-                                                 vfsmount_mark, mask);
-       else
-               return should_send_inode_event(group, to_tell, inode_mark, mask);
+       if (inode_mark && vfsmnt_mark) {
+               marks_mask = (vfsmnt_mark->mask | inode_mark->mask);
+               marks_ignored_mask = (vfsmnt_mark->ignored_mask | inode_mark->ignored_mask);
+       } else if (inode_mark) {
+               /*
+                * if the event is for a child and this inode doesn't care about
+                * events on the child, don't send it!
+                */
+               if ((event_mask & FS_EVENT_ON_CHILD) &&
+                   !(inode_mark->mask & FS_EVENT_ON_CHILD))
+                       return false;
+               marks_mask = inode_mark->mask;
+               marks_ignored_mask = inode_mark->ignored_mask;
+       } else if (vfsmnt_mark) {
+               marks_mask = vfsmnt_mark->mask;
+               marks_ignored_mask = vfsmnt_mark->ignored_mask;
+       } else {
+               BUG();
+       }
+
+       if (event_mask & marks_mask & ~marks_ignored_mask)
+               return true;
+
+       return false;
 }
 
 const struct fsnotify_ops fanotify_fsnotify_ops = {
index 090b64c..4d2a82c 100644 (file)
@@ -183,7 +183,7 @@ static int send_to_group(struct inode *to_tell, struct vfsmount *mnt,
        if (!inode_test_mask && !vfsmount_test_mask)
                return 0;
 
-       if (group->ops->should_send_event(group, to_tell, mnt, inode_mark,
+       if (group->ops->should_send_event(group, to_tell, inode_mark,
                                          vfsmount_mark, mask, data,
                                          data_is) == false)
                return 0;
index e53f497..5e73eeb 100644 (file)
@@ -142,11 +142,11 @@ static void inotify_freeing_mark(struct fsnotify_mark *fsn_mark, struct fsnotify
 }
 
 static bool inotify_should_send_event(struct fsnotify_group *group, struct inode *inode,
-                                     struct vfsmount *mnt, struct fsnotify_mark *mark,
+                                     struct fsnotify_mark *inode_mark,
                                      struct fsnotify_mark *vfsmount_mark,
                                      __u32 mask, void *data, int data_type)
 {
-       if ((mark->mask & FS_EXCL_UNLINK) &&
+       if ((inode_mark->mask & FS_EXCL_UNLINK) &&
            (data_type == FSNOTIFY_EVENT_FILE)) {
                struct file *file  = data;
 
index d38f922..9bbfd72 100644 (file)
@@ -92,7 +92,7 @@ struct fsnotify_event_private_data;
  */
 struct fsnotify_ops {
        bool (*should_send_event)(struct fsnotify_group *group, struct inode *inode,
-                                 struct vfsmount *mnt, struct fsnotify_mark *inode_mark,
+                                 struct fsnotify_mark *inode_mark,
                                  struct fsnotify_mark *vfsmount_mark,
                                  __u32 mask, void *data, int data_type);
        int (*handle_event)(struct fsnotify_group *group,
index 781ab7f..7f18d3a 100644 (file)
@@ -921,7 +921,7 @@ static void audit_tree_freeing_mark(struct fsnotify_mark *entry, struct fsnotify
 }
 
 static bool audit_tree_send_event(struct fsnotify_group *group, struct inode *inode,
-                                 struct vfsmount *mnt, struct fsnotify_mark *inode_mark,
+                                 struct fsnotify_mark *inode_mark,
                                  struct fsnotify_mark *vfsmount_mark,
                                  __u32 mask, void *data, int data_type)
 {
index a273cf3..6bf2306 100644 (file)
@@ -503,7 +503,7 @@ void audit_remove_watch_rule(struct audit_krule *krule)
 }
 
 static bool audit_watch_should_send_event(struct fsnotify_group *group, struct inode *inode,
-                                         struct vfsmount *mnt, struct fsnotify_mark *inode_mark,
+                                         struct fsnotify_mark *inode_mark,
                                          struct fsnotify_mark *vfsmount_mark,
                                          __u32 mask, void *data, int data_type)
 {