xfs: split out handle management helpers a bit
authorDarrick J. Wong <djwong@kernel.org>
Mon, 22 Apr 2024 16:47:55 +0000 (09:47 -0700)
committerDarrick J. Wong <djwong@kernel.org>
Tue, 23 Apr 2024 14:47:00 +0000 (07:47 -0700)
Split out the functions that generate file/fs handles and map them back
into dentries in preparation for the GETPARENTS ioctl next.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
fs/xfs/libxfs/xfs_fs.h
fs/xfs/xfs_handle.c

index 53526fca7386ce0e3ad901d4903f297cf7e5d239..97384ab95de431433c4af3f0c7d91b2300ba2bd9 100644 (file)
@@ -633,7 +633,9 @@ typedef struct xfs_fsop_attrmulti_handlereq {
 /*
  * per machine unique filesystem identifier types.
  */
-typedef struct { __u32 val[2]; } xfs_fsid_t; /* file system id type */
+typedef struct xfs_fsid {
+       __u32   val[2];                 /* file system id type */
+} xfs_fsid_t;
 
 typedef struct xfs_fid {
        __u16   fid_len;                /* length of remainder  */
index 13c2479a3053fa7e401e195fe2434a51b9b881c7..b9f4d9860682aa3e396427b7cd3e323be7f10a51 100644 (file)
 
 #include <linux/namei.h>
 
+static inline size_t
+xfs_filehandle_fid_len(void)
+{
+       struct xfs_handle       *handle = NULL;
+
+       return sizeof(struct xfs_fid) - sizeof(handle->ha_fid.fid_len);
+}
+
+static inline size_t
+xfs_filehandle_init(
+       struct xfs_mount        *mp,
+       xfs_ino_t               ino,
+       uint32_t                gen,
+       struct xfs_handle       *handle)
+{
+       memcpy(&handle->ha_fsid, mp->m_fixedfsid, sizeof(struct xfs_fsid));
+
+       handle->ha_fid.fid_len = xfs_filehandle_fid_len();
+       handle->ha_fid.fid_pad = 0;
+       handle->ha_fid.fid_gen = gen;
+       handle->ha_fid.fid_ino = ino;
+
+       return sizeof(struct xfs_handle);
+}
+
+static inline size_t
+xfs_fshandle_init(
+       struct xfs_mount        *mp,
+       struct xfs_handle       *handle)
+{
+       memcpy(&handle->ha_fsid, mp->m_fixedfsid, sizeof(struct xfs_fsid));
+       memset(&handle->ha_fid, 0, sizeof(handle->ha_fid));
+
+       return sizeof(struct xfs_fsid);
+}
+
 /*
  * xfs_find_handle maps from userspace xfs_fsop_handlereq structure to
  * a file or fs handle.
@@ -84,20 +120,11 @@ xfs_find_handle(
 
        memcpy(&handle.ha_fsid, ip->i_mount->m_fixedfsid, sizeof(xfs_fsid_t));
 
-       if (cmd == XFS_IOC_PATH_TO_FSHANDLE) {
-               /*
-                * This handle only contains an fsid, zero the rest.
-                */
-               memset(&handle.ha_fid, 0, sizeof(handle.ha_fid));
-               hsize = sizeof(xfs_fsid_t);
-       } else {
-               handle.ha_fid.fid_len = sizeof(xfs_fid_t) -
-                                       sizeof(handle.ha_fid.fid_len);
-               handle.ha_fid.fid_pad = 0;
-               handle.ha_fid.fid_gen = inode->i_generation;
-               handle.ha_fid.fid_ino = ip->i_ino;
-               hsize = sizeof(xfs_handle_t);
-       }
+       if (cmd == XFS_IOC_PATH_TO_FSHANDLE)
+               hsize = xfs_fshandle_init(ip->i_mount, &handle);
+       else
+               hsize = xfs_filehandle_init(ip->i_mount, ip->i_ino,
+                               inode->i_generation, &handle);
 
        error = -EFAULT;
        if (copy_to_user(hreq->ohandle, &handle, hsize) ||
@@ -126,6 +153,31 @@ xfs_handle_acceptable(
        return 1;
 }
 
+/* Convert handle already copied to kernel space into a dentry. */
+static struct dentry *
+xfs_khandle_to_dentry(
+       struct file             *file,
+       struct xfs_handle       *handle)
+{
+       struct xfs_fid64        fid = {
+               .ino            = handle->ha_fid.fid_ino,
+               .gen            = handle->ha_fid.fid_gen,
+       };
+
+       /*
+        * Only allow handle opens under a directory.
+        */
+       if (!S_ISDIR(file_inode(file)->i_mode))
+               return ERR_PTR(-ENOTDIR);
+
+       if (handle->ha_fid.fid_len != xfs_filehandle_fid_len())
+               return ERR_PTR(-EINVAL);
+
+       return exportfs_decode_fh(file->f_path.mnt, (struct fid *)&fid, 3,
+                       FILEID_INO32_GEN | XFS_FILEID_TYPE_64FLAG,
+                       xfs_handle_acceptable, NULL);
+}
+
 /*
  * Convert userspace handle data into a dentry.
  */
@@ -136,29 +188,13 @@ xfs_handle_to_dentry(
        u32                     hlen)
 {
        xfs_handle_t            handle;
-       struct xfs_fid64        fid;
-
-       /*
-        * Only allow handle opens under a directory.
-        */
-       if (!S_ISDIR(file_inode(parfilp)->i_mode))
-               return ERR_PTR(-ENOTDIR);
 
        if (hlen != sizeof(xfs_handle_t))
                return ERR_PTR(-EINVAL);
        if (copy_from_user(&handle, uhandle, hlen))
                return ERR_PTR(-EFAULT);
-       if (handle.ha_fid.fid_len !=
-           sizeof(handle.ha_fid) - sizeof(handle.ha_fid.fid_len))
-               return ERR_PTR(-EINVAL);
-
-       memset(&fid, 0, sizeof(struct fid));
-       fid.ino = handle.ha_fid.fid_ino;
-       fid.gen = handle.ha_fid.fid_gen;
 
-       return exportfs_decode_fh(parfilp->f_path.mnt, (struct fid *)&fid, 3,
-                       FILEID_INO32_GEN | XFS_FILEID_TYPE_64FLAG,
-                       xfs_handle_acceptable, NULL);
+       return xfs_khandle_to_dentry(parfilp, &handle);
 }
 
 STATIC struct dentry *