fsnotify: pass object pointer and type to fsnotify mark helpers
authorAmir Goldstein <amir73il@gmail.com>
Sun, 17 Mar 2024 18:41:49 +0000 (20:41 +0200)
committerJan Kara <jack@suse.cz>
Thu, 4 Apr 2024 14:24:16 +0000 (16:24 +0200)
Instead of passing fsnotify_connp_t, pass the pointer to the marked
object.

Store the object pointer in the connector and move the definition of
fsnotify_connp_t to internal fsnotify subsystem API, so it is no longer
used by fsnotify backends.

Suggested-by: Jan Kara <jack@suse.cz>
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
Signed-off-by: Jan Kara <jack@suse.cz>
Message-Id: <20240317184154.1200192-6-amir73il@gmail.com>

fs/notify/fanotify/fanotify_user.c
fs/notify/fsnotify.h
fs/notify/mark.c
include/linux/fsnotify_backend.h

index 04a0b31f325df9fb7e5957fcc384c6588c8a0ad0..925015ee7fbd1957144de3c908e9164ef07d4c3c 100644 (file)
@@ -1076,7 +1076,7 @@ static __u32 fanotify_mark_remove_from_mask(struct fsnotify_mark *fsn_mark,
 }
 
 static int fanotify_remove_mark(struct fsnotify_group *group,
-                               fsnotify_connp_t *connp, __u32 mask,
+                               void *obj, unsigned int obj_type, __u32 mask,
                                unsigned int flags, __u32 umask)
 {
        struct fsnotify_mark *fsn_mark = NULL;
@@ -1084,7 +1084,7 @@ static int fanotify_remove_mark(struct fsnotify_group *group,
        int destroy_mark;
 
        fsnotify_group_lock(group);
-       fsn_mark = fsnotify_find_mark(connp, group);
+       fsn_mark = fsnotify_find_mark(obj, obj_type, group);
        if (!fsn_mark) {
                fsnotify_group_unlock(group);
                return -ENOENT;
@@ -1105,30 +1105,6 @@ static int fanotify_remove_mark(struct fsnotify_group *group,
        return 0;
 }
 
-static int fanotify_remove_vfsmount_mark(struct fsnotify_group *group,
-                                        struct vfsmount *mnt, __u32 mask,
-                                        unsigned int flags, __u32 umask)
-{
-       return fanotify_remove_mark(group, &real_mount(mnt)->mnt_fsnotify_marks,
-                                   mask, flags, umask);
-}
-
-static int fanotify_remove_sb_mark(struct fsnotify_group *group,
-                                  struct super_block *sb, __u32 mask,
-                                  unsigned int flags, __u32 umask)
-{
-       return fanotify_remove_mark(group, &sb->s_fsnotify_marks, mask,
-                                   flags, umask);
-}
-
-static int fanotify_remove_inode_mark(struct fsnotify_group *group,
-                                     struct inode *inode, __u32 mask,
-                                     unsigned int flags, __u32 umask)
-{
-       return fanotify_remove_mark(group, &inode->i_fsnotify_marks, mask,
-                                   flags, umask);
-}
-
 static bool fanotify_mark_update_flags(struct fsnotify_mark *fsn_mark,
                                       unsigned int fan_flags)
 {
@@ -1249,7 +1225,7 @@ static int fanotify_set_mark_fsid(struct fsnotify_group *group,
 }
 
 static struct fsnotify_mark *fanotify_add_new_mark(struct fsnotify_group *group,
-                                                  fsnotify_connp_t *connp,
+                                                  void *obj,
                                                   unsigned int obj_type,
                                                   unsigned int fan_flags,
                                                   struct fan_fsid *fsid)
@@ -1288,7 +1264,7 @@ static struct fsnotify_mark *fanotify_add_new_mark(struct fsnotify_group *group,
                fan_mark->fsid.val[0] = fan_mark->fsid.val[1] = 0;
        }
 
-       ret = fsnotify_add_mark_locked(mark, connp, obj_type, 0);
+       ret = fsnotify_add_mark_locked(mark, obj, obj_type, 0);
        if (ret)
                goto out_put_mark;
 
@@ -1344,7 +1320,7 @@ static int fanotify_may_update_existing_mark(struct fsnotify_mark *fsn_mark,
 }
 
 static int fanotify_add_mark(struct fsnotify_group *group,
-                            fsnotify_connp_t *connp, unsigned int obj_type,
+                            void *obj, unsigned int obj_type,
                             __u32 mask, unsigned int fan_flags,
                             struct fan_fsid *fsid)
 {
@@ -1353,9 +1329,9 @@ static int fanotify_add_mark(struct fsnotify_group *group,
        int ret = 0;
 
        fsnotify_group_lock(group);
-       fsn_mark = fsnotify_find_mark(connp, group);
+       fsn_mark = fsnotify_find_mark(obj, obj_type, group);
        if (!fsn_mark) {
-               fsn_mark = fanotify_add_new_mark(group, connp, obj_type,
+               fsn_mark = fanotify_add_new_mark(group, obj, obj_type,
                                                 fan_flags, fsid);
                if (IS_ERR(fsn_mark)) {
                        fsnotify_group_unlock(group);
@@ -1392,30 +1368,6 @@ out:
        return ret;
 }
 
-static int fanotify_add_vfsmount_mark(struct fsnotify_group *group,
-                                     struct vfsmount *mnt, __u32 mask,
-                                     unsigned int flags, struct fan_fsid *fsid)
-{
-       return fanotify_add_mark(group, &real_mount(mnt)->mnt_fsnotify_marks,
-                                FSNOTIFY_OBJ_TYPE_VFSMOUNT, mask, flags, fsid);
-}
-
-static int fanotify_add_sb_mark(struct fsnotify_group *group,
-                               struct super_block *sb, __u32 mask,
-                               unsigned int flags, struct fan_fsid *fsid)
-{
-       return fanotify_add_mark(group, &sb->s_fsnotify_marks,
-                                FSNOTIFY_OBJ_TYPE_SB, mask, flags, fsid);
-}
-
-static int fanotify_add_inode_mark(struct fsnotify_group *group,
-                                  struct inode *inode, __u32 mask,
-                                  unsigned int flags, struct fan_fsid *fsid)
-{
-       return fanotify_add_mark(group, &inode->i_fsnotify_marks,
-                                FSNOTIFY_OBJ_TYPE_INODE, mask, flags, fsid);
-}
-
 static struct fsnotify_event *fanotify_alloc_overflow_event(void)
 {
        struct fanotify_event *oevent;
@@ -1738,6 +1690,7 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
        unsigned int mark_cmd = flags & FANOTIFY_MARK_CMD_BITS;
        unsigned int ignore = flags & FANOTIFY_MARK_IGNORE_BITS;
        unsigned int obj_type, fid_mode;
+       void *obj;
        u32 umask = 0;
        int ret;
 
@@ -1896,10 +1849,16 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
        }
 
        /* inode held in place by reference to path; group by fget on fd */
-       if (mark_type == FAN_MARK_INODE)
+       if (mark_type == FAN_MARK_INODE) {
                inode = path.dentry->d_inode;
-       else
+               obj = inode;
+       } else {
                mnt = path.mnt;
+               if (mark_type == FAN_MARK_MOUNT)
+                       obj = mnt;
+               else
+                       obj = mnt->mnt_sb;
+       }
 
        /*
         * If some other task has this inode open for write we should not add
@@ -1935,26 +1894,12 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
        /* create/update an inode mark */
        switch (mark_cmd) {
        case FAN_MARK_ADD:
-               if (mark_type == FAN_MARK_MOUNT)
-                       ret = fanotify_add_vfsmount_mark(group, mnt, mask,
-                                                        flags, fsid);
-               else if (mark_type == FAN_MARK_FILESYSTEM)
-                       ret = fanotify_add_sb_mark(group, mnt->mnt_sb, mask,
-                                                  flags, fsid);
-               else
-                       ret = fanotify_add_inode_mark(group, inode, mask,
-                                                     flags, fsid);
+               ret = fanotify_add_mark(group, obj, obj_type, mask, flags,
+                                       fsid);
                break;
        case FAN_MARK_REMOVE:
-               if (mark_type == FAN_MARK_MOUNT)
-                       ret = fanotify_remove_vfsmount_mark(group, mnt, mask,
-                                                           flags, umask);
-               else if (mark_type == FAN_MARK_FILESYSTEM)
-                       ret = fanotify_remove_sb_mark(group, mnt->mnt_sb, mask,
-                                                     flags, umask);
-               else
-                       ret = fanotify_remove_inode_mark(group, inode, mask,
-                                                        flags, umask);
+               ret = fanotify_remove_mark(group, obj, obj_type, mask, flags,
+                                          umask);
                break;
        default:
                ret = -EINVAL;
index 6d9951aac449cb31ba4eed67cdcb665ba7bb289d..b1fec7cd8ee405b6cd042a5d43200620a6c487ac 100644 (file)
@@ -9,22 +9,28 @@
 
 #include "../mount.h"
 
+/*
+ * fsnotify_connp_t is what we embed in objects which connector can be attached
+ * to.
+ */
+typedef struct fsnotify_mark_connector __rcu *fsnotify_connp_t;
+
 static inline struct inode *fsnotify_conn_inode(
                                struct fsnotify_mark_connector *conn)
 {
-       return container_of(conn->obj, struct inode, i_fsnotify_marks);
+       return conn->obj;
 }
 
 static inline struct mount *fsnotify_conn_mount(
                                struct fsnotify_mark_connector *conn)
 {
-       return container_of(conn->obj, struct mount, mnt_fsnotify_marks);
+       return real_mount(conn->obj);
 }
 
 static inline struct super_block *fsnotify_conn_sb(
                                struct fsnotify_mark_connector *conn)
 {
-       return container_of(conn->obj, struct super_block, s_fsnotify_marks);
+       return conn->obj;
 }
 
 static inline struct super_block *fsnotify_object_sb(void *obj,
@@ -45,16 +51,7 @@ static inline struct super_block *fsnotify_object_sb(void *obj,
 static inline struct super_block *fsnotify_connector_sb(
                                struct fsnotify_mark_connector *conn)
 {
-       switch (conn->type) {
-       case FSNOTIFY_OBJ_TYPE_INODE:
-               return fsnotify_conn_inode(conn)->i_sb;
-       case FSNOTIFY_OBJ_TYPE_VFSMOUNT:
-               return fsnotify_conn_mount(conn)->mnt.mnt_sb;
-       case FSNOTIFY_OBJ_TYPE_SB:
-               return fsnotify_conn_sb(conn);
-       default:
-               return NULL;
-       }
+       return fsnotify_object_sb(conn->obj, conn->type);
 }
 
 /* destroy all events sitting in this groups notification queue */
index d9977af258327437f456d2804acd8199a4898a6e..1f611e4eab53fe06b32a97df28139da6aaf3551a 100644 (file)
@@ -265,6 +265,7 @@ static void *fsnotify_detach_connector_from_object(
                                        struct fsnotify_mark_connector *conn,
                                        unsigned int *type)
 {
+       fsnotify_connp_t *connp = fsnotify_object_connp(conn->obj, conn->type);
        struct inode *inode = NULL;
 
        *type = conn->type;
@@ -285,7 +286,7 @@ static void *fsnotify_detach_connector_from_object(
        }
 
        fsnotify_put_sb_watchers(conn);
-       rcu_assign_pointer(*(conn->obj), NULL);
+       rcu_assign_pointer(*connp, NULL);
        conn->obj = NULL;
        conn->type = FSNOTIFY_OBJ_TYPE_DETACHED;
 
@@ -560,7 +561,7 @@ int fsnotify_compare_groups(struct fsnotify_group *a, struct fsnotify_group *b)
 }
 
 static int fsnotify_attach_connector_to_object(fsnotify_connp_t *connp,
-                                              unsigned int obj_type)
+                                              void *obj, unsigned int obj_type)
 {
        struct fsnotify_mark_connector *conn;
 
@@ -571,7 +572,7 @@ static int fsnotify_attach_connector_to_object(fsnotify_connp_t *connp,
        INIT_HLIST_HEAD(&conn->list);
        conn->flags = 0;
        conn->type = obj_type;
-       conn->obj = connp;
+       conn->obj = obj;
 
        /*
         * cmpxchg() provides the barrier so that readers of *connp can see
@@ -620,24 +621,25 @@ out:
  * to which group and for which inodes. These marks are ordered according to
  * priority, highest number first, and then by the group's location in memory.
  */
-static int fsnotify_add_mark_list(struct fsnotify_mark *mark,
-                                 fsnotify_connp_t *connp,
+static int fsnotify_add_mark_list(struct fsnotify_mark *mark, void *obj,
                                  unsigned int obj_type, int add_flags)
 {
        struct fsnotify_mark *lmark, *last = NULL;
        struct fsnotify_mark_connector *conn;
+       fsnotify_connp_t *connp;
        int cmp;
        int err = 0;
 
        if (WARN_ON(!fsnotify_valid_obj_type(obj_type)))
                return -EINVAL;
 
+       connp = fsnotify_object_connp(obj, obj_type);
 restart:
        spin_lock(&mark->lock);
        conn = fsnotify_grab_connector(connp);
        if (!conn) {
                spin_unlock(&mark->lock);
-               err = fsnotify_attach_connector_to_object(connp, obj_type);
+               err = fsnotify_attach_connector_to_object(connp, obj, obj_type);
                if (err)
                        return err;
                goto restart;
@@ -689,7 +691,7 @@ out_err:
  * event types should be delivered to which group.
  */
 int fsnotify_add_mark_locked(struct fsnotify_mark *mark,
-                            fsnotify_connp_t *connp, unsigned int obj_type,
+                            void *obj, unsigned int obj_type,
                             int add_flags)
 {
        struct fsnotify_group *group = mark->group;
@@ -710,7 +712,7 @@ int fsnotify_add_mark_locked(struct fsnotify_mark *mark,
        fsnotify_get_mark(mark); /* for g_list */
        spin_unlock(&mark->lock);
 
-       ret = fsnotify_add_mark_list(mark, connp, obj_type, add_flags);
+       ret = fsnotify_add_mark_list(mark, obj, obj_type, add_flags);
        if (ret)
                goto err;
 
@@ -728,14 +730,14 @@ err:
        return ret;
 }
 
-int fsnotify_add_mark(struct fsnotify_mark *mark, fsnotify_connp_t *connp,
+int fsnotify_add_mark(struct fsnotify_mark *mark, void *obj,
                      unsigned int obj_type, int add_flags)
 {
        int ret;
        struct fsnotify_group *group = mark->group;
 
        fsnotify_group_lock(group);
-       ret = fsnotify_add_mark_locked(mark, connp, obj_type, add_flags);
+       ret = fsnotify_add_mark_locked(mark, obj, obj_type, add_flags);
        fsnotify_group_unlock(group);
        return ret;
 }
@@ -745,12 +747,16 @@ EXPORT_SYMBOL_GPL(fsnotify_add_mark);
  * Given a list of marks, find the mark associated with given group. If found
  * take a reference to that mark and return it, else return NULL.
  */
-struct fsnotify_mark *fsnotify_find_mark(fsnotify_connp_t *connp,
+struct fsnotify_mark *fsnotify_find_mark(void *obj, unsigned int obj_type,
                                         struct fsnotify_group *group)
 {
+       fsnotify_connp_t *connp = fsnotify_object_connp(obj, obj_type);
        struct fsnotify_mark_connector *conn;
        struct fsnotify_mark *mark;
 
+       if (!connp)
+               return NULL;
+
        conn = fsnotify_grab_connector(connp);
        if (!conn)
                return NULL;
index 992b57a7e95f43fcc5abadf9f9a37259cc132f41..face68fcf850793571eb2034b36fb7b711af2ac8 100644 (file)
@@ -456,13 +456,6 @@ FSNOTIFY_ITER_FUNCS(sb, SB)
             type < FSNOTIFY_ITER_TYPE_COUNT; \
             type++)
 
-/*
- * fsnotify_connp_t is what we embed in objects which connector can be attached
- * to. fsnotify_connp_t * is how we refer from connector back to object.
- */
-struct fsnotify_mark_connector;
-typedef struct fsnotify_mark_connector __rcu *fsnotify_connp_t;
-
 /*
  * Inode/vfsmount/sb point to this structure which tracks all marks attached to
  * the inode/vfsmount/sb. The reference to inode/vfsmount/sb is held by this
@@ -476,7 +469,7 @@ struct fsnotify_mark_connector {
        unsigned short flags;   /* flags [lock] */
        union {
                /* Object pointer [lock] */
-               fsnotify_connp_t *obj;
+               void *obj;
                /* Used listing heads to free after srcu period expires */
                struct fsnotify_mark_connector *destroy_next;
        };
@@ -763,37 +756,35 @@ extern void fsnotify_recalc_mask(struct fsnotify_mark_connector *conn);
 extern void fsnotify_init_mark(struct fsnotify_mark *mark,
                               struct fsnotify_group *group);
 /* Find mark belonging to given group in the list of marks */
-extern struct fsnotify_mark *fsnotify_find_mark(fsnotify_connp_t *connp,
-                                               struct fsnotify_group *group);
+struct fsnotify_mark *fsnotify_find_mark(void *obj, unsigned int obj_type,
+                                        struct fsnotify_group *group);
 /* attach the mark to the object */
-extern int fsnotify_add_mark(struct fsnotify_mark *mark,
-                            fsnotify_connp_t *connp, unsigned int obj_type,
-                            int add_flags);
-extern int fsnotify_add_mark_locked(struct fsnotify_mark *mark,
-                                   fsnotify_connp_t *connp,
-                                   unsigned int obj_type, int add_flags);
+int fsnotify_add_mark(struct fsnotify_mark *mark, void *obj,
+                     unsigned int obj_type, int add_flags);
+int fsnotify_add_mark_locked(struct fsnotify_mark *mark, void *obj,
+                            unsigned int obj_type, int add_flags);
 
 /* attach the mark to the inode */
 static inline int fsnotify_add_inode_mark(struct fsnotify_mark *mark,
                                          struct inode *inode,
                                          int add_flags)
 {
-       return fsnotify_add_mark(mark, &inode->i_fsnotify_marks,
-                                FSNOTIFY_OBJ_TYPE_INODE, add_flags);
+       return fsnotify_add_mark(mark, inode, FSNOTIFY_OBJ_TYPE_INODE,
+                                add_flags);
 }
 static inline int fsnotify_add_inode_mark_locked(struct fsnotify_mark *mark,
                                                 struct inode *inode,
                                                 int add_flags)
 {
-       return fsnotify_add_mark_locked(mark, &inode->i_fsnotify_marks,
-                                       FSNOTIFY_OBJ_TYPE_INODE, add_flags);
+       return fsnotify_add_mark_locked(mark, inode, FSNOTIFY_OBJ_TYPE_INODE,
+                                       add_flags);
 }
 
 static inline struct fsnotify_mark *fsnotify_find_inode_mark(
                                                struct inode *inode,
                                                struct fsnotify_group *group)
 {
-       return fsnotify_find_mark(&inode->i_fsnotify_marks, group);
+       return fsnotify_find_mark(inode, FSNOTIFY_OBJ_TYPE_INODE, group);
 }
 
 /* given a group and a mark, flag mark to be freed when all references are dropped */