]> bbs.cooldavid.org Git - net-next-2.6.git/commitdiff
fsnotify: pass both the vfsmount mark and inode mark
authorEric Paris <eparis@redhat.com>
Wed, 28 Jul 2010 14:18:39 +0000 (10:18 -0400)
committerEric Paris <eparis@redhat.com>
Wed, 28 Jul 2010 14:18:54 +0000 (10:18 -0400)
should_send_event() and handle_event() will both need to look up the inode
event if they get a vfsmount event.  Lets just pass both at the same time
since we have them both after walking the lists in lockstep.

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 e92b2c87ae9444cef8a48097ecb35285c8fa9dd4..bda588b831ada8582da6b509c580ac689dabbec0 100644 (file)
@@ -83,7 +83,8 @@ static void dnotify_recalc_inode_mask(struct fsnotify_mark *fsn_mark)
  * events.
  */
 static int dnotify_handle_event(struct fsnotify_group *group,
-                               struct fsnotify_mark *mark,
+                               struct fsnotify_mark *inode_mark,
+                               struct fsnotify_mark *vfsmount_mark,
                                struct fsnotify_event *event)
 {
        struct dnotify_mark *dn_mark;
@@ -93,11 +94,13 @@ static int dnotify_handle_event(struct fsnotify_group *group,
        struct fown_struct *fown;
        __u32 test_mask = event->mask & ~FS_EVENT_ON_CHILD;
 
+       BUG_ON(vfsmount_mark);
+
        to_tell = event->to_tell;
 
-       dn_mark = container_of(mark, struct dnotify_mark, fsn_mark);
+       dn_mark = container_of(inode_mark, struct dnotify_mark, fsn_mark);
 
-       spin_lock(&mark->lock);
+       spin_lock(&inode_mark->lock);
        prev = &dn_mark->dn;
        while ((dn = *prev) != NULL) {
                if ((dn->dn_mask & test_mask) == 0) {
@@ -111,11 +114,11 @@ static int dnotify_handle_event(struct fsnotify_group *group,
                else {
                        *prev = dn->dn_next;
                        kmem_cache_free(dnotify_struct_cache, dn);
-                       dnotify_recalc_inode_mask(mark);
+                       dnotify_recalc_inode_mask(inode_mark);
                }
        }
 
-       spin_unlock(&mark->lock);
+       spin_unlock(&inode_mark->lock);
 
        return 0;
 }
@@ -126,8 +129,9 @@ static int dnotify_handle_event(struct fsnotify_group *group,
  */
 static bool dnotify_should_send_event(struct fsnotify_group *group,
                                      struct inode *inode, struct vfsmount *mnt,
-                                     struct fsnotify_mark *mark, __u32 mask,
-                                     void *data, int data_type)
+                                     struct fsnotify_mark *inode_mark,
+                                     struct fsnotify_mark *vfsmount_mark,
+                                     __u32 mask, void *data, int data_type)
 {
        /* not a dir, dnotify doesn't care */
        if (!S_ISDIR(inode->i_mode))
index fbd7f35c6134b6e69743576a2419900d9b90dadc..ef4fa4a45c94c803a30a0adddab9d742c8ab94f7 100644 (file)
@@ -115,7 +115,8 @@ static int fanotify_get_response_from_access(struct fsnotify_group *group,
 #endif
 
 static int fanotify_handle_event(struct fsnotify_group *group,
-                                struct fsnotify_mark *mark,
+                                struct fsnotify_mark *inode_mark,
+                                struct fsnotify_mark *fanotify_mark,
                                 struct fsnotify_event *event)
 {
        int ret = 0;
@@ -196,8 +197,11 @@ static bool should_send_inode_event(struct fsnotify_group *group,
                return true;
 }
 
-static bool fanotify_should_send_event(struct fsnotify_group *group, struct inode *to_tell,
-                                      struct vfsmount *mnt, struct fsnotify_mark *mark,
+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)
 {
        pr_debug("%s: group=%p to_tell=%p mnt=%p mask=%x data=%p data_type=%d\n",
@@ -213,9 +217,10 @@ static bool fanotify_should_send_event(struct fsnotify_group *group, struct inod
                return false;
 
        if (mnt)
-               return should_send_vfsmount_event(group, mnt, to_tell, mark, mask);
+               return should_send_vfsmount_event(group, mnt, to_tell,
+                                                 vfsmount_mark, mask);
        else
-               return should_send_inode_event(group, to_tell, mark, mask);
+               return should_send_inode_event(group, to_tell, inode_mark, mask);
 }
 
 const struct fsnotify_ops fanotify_fsnotify_ops = {
index cdaa51cb698cf7da4c878633a038cae3d5d7e8c8..090b64c3b4f98b7345a075f8d86eed827edf95d5 100644 (file)
@@ -141,28 +141,51 @@ void __fsnotify_parent(struct file *file, struct dentry *dentry, __u32 mask)
 EXPORT_SYMBOL_GPL(__fsnotify_parent);
 
 static int send_to_group(struct inode *to_tell, struct vfsmount *mnt,
-                        struct fsnotify_mark *mark,
-                       __u32 mask, void *data,
+                        struct fsnotify_mark *inode_mark,
+                        struct fsnotify_mark *vfsmount_mark,
+                        __u32 mask, void *data,
                         int data_is, u32 cookie,
                         const unsigned char *file_name,
                         struct fsnotify_event **event)
 {
-       struct fsnotify_group *group = mark->group;
-       __u32 test_mask = (mask & ~FS_EVENT_ON_CHILD);
+       struct fsnotify_group *group = inode_mark->group;
+       __u32 inode_test_mask = (mask & ~FS_EVENT_ON_CHILD);
+       __u32 vfsmount_test_mask = (mask & ~FS_EVENT_ON_CHILD);
 
        pr_debug("%s: group=%p to_tell=%p mnt=%p mark=%p mask=%x data=%p"
                 " data_is=%d cookie=%d event=%p\n", __func__, group, to_tell,
-                mnt, mark, mask, data, data_is, cookie, *event);
+                mnt, inode_mark, mask, data, data_is, cookie, *event);
+
+       /* clear ignored on inode modification */
+       if (mask & FS_MODIFY) {
+               if (inode_mark &&
+                   !(inode_mark->flags & FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY))
+                       inode_mark->ignored_mask = 0;
+               if (vfsmount_mark &&
+                   !(vfsmount_mark->flags & FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY))
+                       vfsmount_mark->ignored_mask = 0;
+       }
 
-       if ((mask & FS_MODIFY) &&
-           !(mark->flags & FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY))
-               mark->ignored_mask = 0;
+       /* does the inode mark tell us to do something? */
+       if (inode_mark) {
+               inode_test_mask &= inode_mark->mask;
+               inode_test_mask &= ~inode_mark->ignored_mask;
+       }
 
-       if (!(test_mask & mark->mask & ~mark->ignored_mask))
+       /* does the vfsmount_mark tell us to do something? */
+       if (vfsmount_mark) {
+               vfsmount_test_mask &= vfsmount_mark->mask;
+               vfsmount_test_mask &= ~vfsmount_mark->ignored_mask;
+               if (inode_mark)
+                       vfsmount_test_mask &= ~inode_mark->ignored_mask;
+       }
+
+       if (!inode_test_mask && !vfsmount_test_mask)
                return 0;
 
-       if (group->ops->should_send_event(group, to_tell, mnt, mark, mask,
-                                         data, data_is) == false)
+       if (group->ops->should_send_event(group, to_tell, mnt, inode_mark,
+                                         vfsmount_mark, mask, data,
+                                         data_is) == false)
                return 0;
 
        if (!*event) {
@@ -172,7 +195,7 @@ static int send_to_group(struct inode *to_tell, struct vfsmount *mnt,
                if (!*event)
                        return -ENOMEM;
        }
-       return group->ops->handle_event(group, mark, *event);
+       return group->ops->handle_event(group, inode_mark, vfsmount_mark, *event);
 }
 
 /*
@@ -213,14 +236,16 @@ int fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is,
 
        if ((mask & FS_MODIFY) ||
            (test_mask & to_tell->i_fsnotify_mask))
-               inode_node = to_tell->i_fsnotify_marks.first;
+               inode_node = srcu_dereference(to_tell->i_fsnotify_marks.first,
+                                             &fsnotify_mark_srcu);
        else
                inode_node = NULL;
 
        if (mnt) {
                if ((mask & FS_MODIFY) ||
                    (test_mask & mnt->mnt_fsnotify_mask))
-                       vfsmount_node = mnt->mnt_fsnotify_marks.first;
+                       vfsmount_node = srcu_dereference(mnt->mnt_fsnotify_marks.first,
+                                                        &fsnotify_mark_srcu);
                else
                        vfsmount_node = NULL;
        } else {
@@ -245,26 +270,27 @@ int fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is,
 
                if (inode_group < vfsmount_group) {
                        /* handle inode */
-                       send_to_group(to_tell, NULL, inode_mark, mask, data,
+                       send_to_group(to_tell, NULL, inode_mark, NULL, mask, data,
                                      data_is, cookie, file_name, &event);
                        used_inode = true;
                } else if (vfsmount_group < inode_group) {
-                       send_to_group(to_tell, mnt, vfsmount_mark, mask, data,
+                       send_to_group(to_tell, mnt, NULL, vfsmount_mark, mask, data,
                                      data_is, cookie, file_name, &event);
                        used_vfsmount = true;
                } else {
-                       send_to_group(to_tell, mnt, vfsmount_mark, mask, data,
-                                     data_is, cookie, file_name, &event);
+                       send_to_group(to_tell, mnt, inode_mark, vfsmount_mark,
+                                     mask, data, data_is, cookie, file_name,
+                                     &event);
                        used_vfsmount = true;
-                       send_to_group(to_tell, NULL, inode_mark, mask, data,
-                                     data_is, cookie, file_name, &event);
                        used_inode = true;
                }
 
                if (used_inode)
-                       inode_node = inode_node->next;
+                       inode_node = srcu_dereference(inode_node->next,
+                                                     &fsnotify_mark_srcu);
                if (used_vfsmount)
-                       vfsmount_node = vfsmount_node->next;
+                       vfsmount_node = srcu_dereference(vfsmount_node->next,
+                                                        &fsnotify_mark_srcu);
        }
 
        srcu_read_unlock(&fsnotify_mark_srcu, idx);
index 7cf518b25daacf64694977d5b785e4a8149965a8..e53f49731b6e3a5ee56a3de9445f9f95ac99e72d 100644 (file)
@@ -90,7 +90,8 @@ static struct fsnotify_event *inotify_merge(struct list_head *list,
 }
 
 static int inotify_handle_event(struct fsnotify_group *group,
-                               struct fsnotify_mark *mark,
+                               struct fsnotify_mark *inode_mark,
+                               struct fsnotify_mark *vfsmount_mark,
                                struct fsnotify_event *event)
 {
        struct inotify_inode_mark *i_mark;
@@ -100,12 +101,14 @@ static int inotify_handle_event(struct fsnotify_group *group,
        struct fsnotify_event *added_event;
        int wd, ret = 0;
 
+       BUG_ON(vfsmount_mark);
+
        pr_debug("%s: group=%p event=%p to_tell=%p mask=%x\n", __func__, group,
                 event, event->to_tell, event->mask);
 
        to_tell = event->to_tell;
 
-       i_mark = container_of(mark, struct inotify_inode_mark,
+       i_mark = container_of(inode_mark, struct inotify_inode_mark,
                              fsn_mark);
        wd = i_mark->wd;
 
@@ -127,8 +130,8 @@ static int inotify_handle_event(struct fsnotify_group *group,
                        ret = PTR_ERR(added_event);
        }
 
-       if (mark->mask & IN_ONESHOT)
-               fsnotify_destroy_mark(mark);
+       if (inode_mark->mask & IN_ONESHOT)
+               fsnotify_destroy_mark(inode_mark);
 
        return ret;
 }
@@ -140,6 +143,7 @@ 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 *vfsmount_mark,
                                      __u32 mask, void *data, int data_type)
 {
        if ((mark->mask & FS_EXCL_UNLINK) &&
index 2e7cc8c2a1511b46c82b41470e472ca159e1ba86..d38f922977f92fd860996ecb95be3a90624c6580 100644 (file)
@@ -92,9 +92,12 @@ 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 *mark,
+                                 struct vfsmount *mnt, struct fsnotify_mark *inode_mark,
+                                 struct fsnotify_mark *vfsmount_mark,
                                  __u32 mask, void *data, int data_type);
-       int (*handle_event)(struct fsnotify_group *group, struct fsnotify_mark *mark,
+       int (*handle_event)(struct fsnotify_group *group,
+                           struct fsnotify_mark *inode_mark,
+                           struct fsnotify_mark *vfsmount_mark,
                            struct fsnotify_event *event);
        void (*free_group_priv)(struct fsnotify_group *group);
        void (*freeing_mark)(struct fsnotify_mark *mark, struct fsnotify_group *group);
index 2abb99f3459d1750cc61b454105f2517ef1f470c..781ab7f4e35c7197e074a2723ecd4feb0b898deb 100644 (file)
@@ -904,7 +904,8 @@ static void evict_chunk(struct audit_chunk *chunk)
 }
 
 static int audit_tree_handle_event(struct fsnotify_group *group,
-                                  struct fsnotify_mark *mark,
+                                  struct fsnotify_mark *inode_mark,
+                                  struct fsnotify_mark *vfsmonut_mark,
                                   struct fsnotify_event *event)
 {
        BUG();
@@ -920,7 +921,8 @@ 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 *mark,
+                                 struct vfsmount *mnt, struct fsnotify_mark *inode_mark,
+                                 struct fsnotify_mark *vfsmount_mark,
                                  __u32 mask, void *data, int data_type)
 {
        return false;
index 1b87e757845d2220a20a6bf7d488c0f5237427b3..a273cf340527d1b4e54319ddba5bd559443d9fe0 100644 (file)
@@ -503,7 +503,8 @@ 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 *mark,
+                                         struct vfsmount *mnt, struct fsnotify_mark *inode_mark,
+                                         struct fsnotify_mark *vfsmount_mark,
                                          __u32 mask, void *data, int data_type)
 {
        return true;
@@ -511,7 +512,8 @@ static bool audit_watch_should_send_event(struct fsnotify_group *group, struct i
 
 /* Update watch data in audit rules based on fsnotify events. */
 static int audit_watch_handle_event(struct fsnotify_group *group,
-                                   struct fsnotify_mark *mark,
+                                   struct fsnotify_mark *inode_mark,
+                                   struct fsnotify_mark *vfsmount_mark,
                                    struct fsnotify_event *event)
 {
        struct inode *inode;
@@ -519,7 +521,7 @@ static int audit_watch_handle_event(struct fsnotify_group *group,
        const char *dname = event->file_name;
        struct audit_parent *parent;
 
-       parent = container_of(mark, struct audit_parent, mark);
+       parent = container_of(inode_mark, struct audit_parent, mark);
 
        BUG_ON(group != audit_watch_group);