]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
fsnotify: Pass fsnotify_iter_info into handle_event handler
authorJan Kara <jack@suse.cz>
Thu, 10 Nov 2016 16:51:50 +0000 (17:51 +0100)
committerJan Kara <jack@suse.cz>
Mon, 10 Apr 2017 15:37:36 +0000 (17:37 +0200)
Pass fsnotify_iter_info into ->handle_event() handler so that it can
release and reacquire SRCU lock via fsnotify_prepare_user_wait() and
fsnotify_finish_user_wait() functions.  These functions also make sure
current marks are appropriately pinned so that iteration protected by
srcu in fsnotify() stays safe.

Reviewed-by: Miklos Szeredi <mszeredi@redhat.com>
Reviewed-by: Amir Goldstein <amir73il@gmail.com>
Signed-off-by: Jan Kara <jack@suse.cz>
fs/notify/dnotify/dnotify.c
fs/notify/fanotify/fanotify.c
fs/notify/fsnotify.c
fs/notify/inotify/inotify.h
fs/notify/inotify/inotify_fsnotify.c
fs/notify/inotify/inotify_user.c
include/linux/fsnotify_backend.h
kernel/audit_fsnotify.c
kernel/audit_tree.c
kernel/audit_watch.c

index 41b2a070761c9d60be7a466f30d3342b355160b6..aba165ae33979bc384653629ad33abd71781d939 100644 (file)
@@ -85,7 +85,8 @@ static int dnotify_handle_event(struct fsnotify_group *group,
                                struct fsnotify_mark *inode_mark,
                                struct fsnotify_mark *vfsmount_mark,
                                u32 mask, const void *data, int data_type,
-                               const unsigned char *file_name, u32 cookie)
+                               const unsigned char *file_name, u32 cookie,
+                               struct fsnotify_iter_info *iter_info)
 {
        struct dnotify_mark *dn_mark;
        struct dnotify_struct *dn;
index e5f7e47de68e4bf3cc75dc1cf03e29fed3fda8be..ec80a51cbb3dae03915af1867729a28d3963336f 100644 (file)
@@ -174,7 +174,8 @@ static int fanotify_handle_event(struct fsnotify_group *group,
                                 struct fsnotify_mark *inode_mark,
                                 struct fsnotify_mark *fanotify_mark,
                                 u32 mask, const void *data, int data_type,
-                                const unsigned char *file_name, u32 cookie)
+                                const unsigned char *file_name, u32 cookie,
+                                struct fsnotify_iter_info *iter_info)
 {
        int ret = 0;
        struct fanotify_event_info *event;
index d512ef9f75fc3c3d44a99953f0b87b6547b1175b..c4afb6a8826844362c0fcf3cb58c7f0a40c43b05 100644 (file)
@@ -127,7 +127,8 @@ static int send_to_group(struct inode *to_tell,
                         struct fsnotify_mark *vfsmount_mark,
                         __u32 mask, const void *data,
                         int data_is, u32 cookie,
-                        const unsigned char *file_name)
+                        const unsigned char *file_name,
+                        struct fsnotify_iter_info *iter_info)
 {
        struct fsnotify_group *group = NULL;
        __u32 inode_test_mask = 0;
@@ -178,7 +179,7 @@ static int send_to_group(struct inode *to_tell,
 
        return group->ops->handle_event(group, to_tell, inode_mark,
                                        vfsmount_mark, mask, data, data_is,
-                                       file_name, cookie);
+                                       file_name, cookie, iter_info);
 }
 
 /*
@@ -194,8 +195,9 @@ int fsnotify(struct inode *to_tell, __u32 mask, const void *data, int data_is,
        struct fsnotify_mark *inode_mark = NULL, *vfsmount_mark = NULL;
        struct fsnotify_group *inode_group, *vfsmount_group;
        struct fsnotify_mark_connector *inode_conn, *vfsmount_conn;
+       struct fsnotify_iter_info iter_info;
        struct mount *mnt;
-       int idx, ret = 0;
+       int ret = 0;
        /* global tests shouldn't care about events on child only the specific event */
        __u32 test_mask = (mask & ~FS_EVENT_ON_CHILD);
 
@@ -224,7 +226,7 @@ int fsnotify(struct inode *to_tell, __u32 mask, const void *data, int data_is,
            !(mnt && test_mask & mnt->mnt_fsnotify_mask))
                return 0;
 
-       idx = srcu_read_lock(&fsnotify_mark_srcu);
+       iter_info.srcu_idx = srcu_read_lock(&fsnotify_mark_srcu);
 
        if ((mask & FS_MODIFY) ||
            (test_mask & to_tell->i_fsnotify_mask)) {
@@ -284,8 +286,13 @@ int fsnotify(struct inode *to_tell, __u32 mask, const void *data, int data_is,
                                vfsmount_mark = NULL;
                        }
                }
+
+               iter_info.inode_mark = inode_mark;
+               iter_info.vfsmount_mark = vfsmount_mark;
+
                ret = send_to_group(to_tell, inode_mark, vfsmount_mark, mask,
-                                   data, data_is, cookie, file_name);
+                                   data, data_is, cookie, file_name,
+                                   &iter_info);
 
                if (ret && (mask & ALL_FSNOTIFY_PERM_EVENTS))
                        goto out;
@@ -299,7 +306,7 @@ int fsnotify(struct inode *to_tell, __u32 mask, const void *data, int data_is,
        }
        ret = 0;
 out:
-       srcu_read_unlock(&fsnotify_mark_srcu, idx);
+       srcu_read_unlock(&fsnotify_mark_srcu, iter_info.srcu_idx);
 
        return ret;
 }
index 7c461fd49c4ccf1f81d87d1eddcacd16c3c3ab86..7a966f456269dd712291cdc3d81084b10be4c575 100644 (file)
@@ -27,7 +27,8 @@ extern int inotify_handle_event(struct fsnotify_group *group,
                                struct fsnotify_mark *inode_mark,
                                struct fsnotify_mark *vfsmount_mark,
                                u32 mask, const void *data, int data_type,
-                               const unsigned char *file_name, u32 cookie);
+                               const unsigned char *file_name, u32 cookie,
+                               struct fsnotify_iter_info *iter_info);
 
 extern const struct fsnotify_ops inotify_fsnotify_ops;
 
index f310d8368a2d8b7143b143426fd3ada6db0b7659..ccd6a4055e0c3dd06cab2733c9c4043af8c588c3 100644 (file)
@@ -68,7 +68,8 @@ int inotify_handle_event(struct fsnotify_group *group,
                         struct fsnotify_mark *inode_mark,
                         struct fsnotify_mark *vfsmount_mark,
                         u32 mask, const void *data, int data_type,
-                        const unsigned char *file_name, u32 cookie)
+                        const unsigned char *file_name, u32 cookie,
+                        struct fsnotify_iter_info *iter_info)
 {
        struct inotify_inode_mark *i_mark;
        struct inotify_event_info *event;
index 43cbd1b178c9f71046d7e3d16c19e651324dbe04..05b268ec0f5f6c929e84d4ddf8cce41154daf116 100644 (file)
@@ -474,7 +474,7 @@ void inotify_ignored_and_remove_idr(struct fsnotify_mark *fsn_mark,
 
        /* Queue ignore event for the watch */
        inotify_handle_event(group, NULL, fsn_mark, NULL, FS_IN_IGNORED,
-                            NULL, FSNOTIFY_EVENT_NONE, NULL, 0);
+                            NULL, FSNOTIFY_EVENT_NONE, NULL, 0, NULL);
 
        i_mark = container_of(fsn_mark, struct inotify_inode_mark, fsn_mark);
        /* remove this mark from the idr */
index 5bb6d988b9f6373afbdd4e0c72ad16d54dec0cf6..744a4b9076f926a9a8719763f9ece10d54962c60 100644 (file)
@@ -99,7 +99,8 @@ struct fsnotify_ops {
                            struct fsnotify_mark *inode_mark,
                            struct fsnotify_mark *vfsmount_mark,
                            u32 mask, const void *data, int data_type,
-                           const unsigned char *file_name, u32 cookie);
+                           const unsigned char *file_name, u32 cookie,
+                           struct fsnotify_iter_info *iter_info);
        void (*free_group_priv)(struct fsnotify_group *group);
        void (*freeing_mark)(struct fsnotify_mark *mark, struct fsnotify_group *group);
        void (*free_event)(struct fsnotify_event *event);
index 7ea57e516029d6b82a9e72adfea70d45f538cb2b..e8b371ff1e91ca6767649bd01d201ff8a628db1f 100644 (file)
@@ -168,7 +168,8 @@ static int audit_mark_handle_event(struct fsnotify_group *group,
                                    struct fsnotify_mark *inode_mark,
                                    struct fsnotify_mark *vfsmount_mark,
                                    u32 mask, const void *data, int data_type,
-                                   const unsigned char *dname, u32 cookie)
+                                   const unsigned char *dname, u32 cookie,
+                                   struct fsnotify_iter_info *iter_info)
 {
        struct audit_fsnotify_mark *audit_mark;
        const struct inode *inode = NULL;
index 2fa8d61b6fd2166e55de50c6ffa50f2868a3d6b9..d59ed4c9037a35dfc020d4ef77ed4b61f905efc6 100644 (file)
@@ -989,7 +989,8 @@ static int audit_tree_handle_event(struct fsnotify_group *group,
                                   struct fsnotify_mark *inode_mark,
                                   struct fsnotify_mark *vfsmount_mark,
                                   u32 mask, const void *data, int data_type,
-                                  const unsigned char *file_name, u32 cookie)
+                                  const unsigned char *file_name, u32 cookie,
+                                  struct fsnotify_iter_info *iter_info)
 {
        return 0;
 }
index f79e4658433d45e9d32a299ebf3f427b508ada2c..6caaf087801f087a69eef71f7fc582b087d60efa 100644 (file)
@@ -472,7 +472,8 @@ static int audit_watch_handle_event(struct fsnotify_group *group,
                                    struct fsnotify_mark *inode_mark,
                                    struct fsnotify_mark *vfsmount_mark,
                                    u32 mask, const void *data, int data_type,
-                                   const unsigned char *dname, u32 cookie)
+                                   const unsigned char *dname, u32 cookie,
+                                   struct fsnotify_iter_info *iter_info)
 {
        const struct inode *inode;
        struct audit_parent *parent;