]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs: refactor dir format helpers
authorChristoph Hellwig <hch@lst.de>
Mon, 29 Jul 2024 23:22:53 +0000 (16:22 -0700)
committerDarrick J. Wong <djwong@kernel.org>
Tue, 30 Jul 2024 00:01:04 +0000 (17:01 -0700)
Source kernel commit: e58ac1770ded2a316447ca7608bb7809af82eca6

Add a new enum and a xfs_dir2_format helper that returns it to allow
the code to switch on the format of a directory in a single operation
and switch all helpers of xfs_dir2_isblock and xfs_dir2_isleaf to it.

This also removes the explicit xfs_iread_extents call in a few of the
call sites given that xfs_bmap_last_offset already takes care of it
underneath.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
Signed-off-by: Chandan Babu R <chandanbabu@kernel.org>
db/namei.c
libxfs/libxfs_api_defs.h
libxfs/xfs_dir2.c
libxfs/xfs_dir2.h
libxfs/xfs_exchmaps.c
repair/phase6.c

index 303ca3448f60f487afbc9dcbcb2925f88f4ca924..6de0621616a606c057ac321dc9e7ff6776878b78 100644 (file)
@@ -449,18 +449,18 @@ listdir(
                .geo            = dp->i_mount->m_dir_geo,
        };
        int                     error;
-       bool                    isblock;
 
-       if (dp->i_df.if_format == XFS_DINODE_FMT_LOCAL)
+       switch (libxfs_dir2_format(&args, &error)) {
+       case XFS_DIR2_FMT_SF:
                return list_sfdir(&args);
-
-       error = -libxfs_dir2_isblock(&args, &isblock);
-       if (error)
-               return error;
-
-       if (isblock)
+       case XFS_DIR2_FMT_BLOCK:
                return list_blockdir(&args);
-       return list_leafdir(&args);
+       case XFS_DIR2_FMT_LEAF:
+       case XFS_DIR2_FMT_NODE:
+               return list_leafdir(&args);
+       default:
+               return error;
+       }
 }
 
 /* List the inode number of the currently selected inode. */
index 896b6c953f4b77fa60f32243805463e4664bb167..cc670d93a9f2a89e0549450e44904eb276d6279c 100644 (file)
 #define xfs_dir2_data_use_free         libxfs_dir2_data_use_free
 #define xfs_dir2_free_hdr_from_disk    libxfs_dir2_free_hdr_from_disk
 #define xfs_dir2_hashname              libxfs_dir2_hashname
-#define xfs_dir2_isblock               libxfs_dir2_isblock
-#define xfs_dir2_isleaf                        libxfs_dir2_isleaf
 #define xfs_dir2_leaf_hdr_from_disk    libxfs_dir2_leaf_hdr_from_disk
+#define xfs_dir2_format                        libxfs_dir2_format
 #define xfs_dir2_namecheck             libxfs_dir2_namecheck
 #define xfs_dir2_sf_entsize            libxfs_dir2_sf_entsize
 #define xfs_dir2_sf_get_ftype          libxfs_dir2_sf_get_ftype
index 55cf39e119ddecb348f312f6a910fdd7faf5f628..9cf05ec51185ee3faf387051e288a635ecbe0558 100644 (file)
@@ -255,31 +255,60 @@ xfs_dir_init(
        return error;
 }
 
+enum xfs_dir2_fmt
+xfs_dir2_format(
+       struct xfs_da_args      *args,
+       int                     *error)
+{
+       struct xfs_inode        *dp = args->dp;
+       struct xfs_mount        *mp = dp->i_mount;
+       struct xfs_da_geometry  *geo = mp->m_dir_geo;
+       xfs_fileoff_t           eof;
+
+       xfs_assert_ilocked(dp, XFS_ILOCK_SHARED | XFS_ILOCK_EXCL);
+
+       *error = 0;
+       if (dp->i_df.if_format == XFS_DINODE_FMT_LOCAL)
+               return XFS_DIR2_FMT_SF;
+
+       *error = xfs_bmap_last_offset(dp, &eof, XFS_DATA_FORK);
+       if (*error)
+               return XFS_DIR2_FMT_ERROR;
+
+       if (eof == XFS_B_TO_FSB(mp, geo->blksize)) {
+               if (XFS_IS_CORRUPT(mp, dp->i_disk_size != geo->blksize)) {
+                       xfs_da_mark_sick(args);
+                       *error = -EFSCORRUPTED;
+                       return XFS_DIR2_FMT_ERROR;
+               }
+               return XFS_DIR2_FMT_BLOCK;
+       }
+       if (eof == geo->leafblk + geo->fsbcount)
+               return XFS_DIR2_FMT_LEAF;
+       return XFS_DIR2_FMT_NODE;
+}
+
 int
 xfs_dir_createname_args(
        struct xfs_da_args      *args)
 {
-       bool                    is_block, is_leaf;
        int                     error;
 
        if (!args->inumber)
                args->op_flags |= XFS_DA_OP_JUSTCHECK;
 
-       if (args->dp->i_df.if_format == XFS_DINODE_FMT_LOCAL)
+       switch (xfs_dir2_format(args, &error)) {
+       case XFS_DIR2_FMT_SF:
                return xfs_dir2_sf_addname(args);
-
-       error = xfs_dir2_isblock(args, &is_block);
-       if (error)
-               return error;
-       if (is_block)
+       case XFS_DIR2_FMT_BLOCK:
                return xfs_dir2_block_addname(args);
-
-       error = xfs_dir2_isleaf(args, &is_leaf);
-       if (error)
-               return error;
-       if (is_leaf)
+       case XFS_DIR2_FMT_LEAF:
                return xfs_dir2_leaf_addname(args);
-       return xfs_dir2_node_addname(args);
+       case XFS_DIR2_FMT_NODE:
+               return xfs_dir2_node_addname(args);
+       default:
+               return error;
+       }
 }
 
 /*
@@ -358,36 +387,25 @@ int
 xfs_dir_lookup_args(
        struct xfs_da_args      *args)
 {
-       bool                    is_block, is_leaf;
        int                     error;
 
-       if (args->dp->i_df.if_format == XFS_DINODE_FMT_LOCAL) {
+       switch (xfs_dir2_format(args, &error)) {
+       case XFS_DIR2_FMT_SF:
                error = xfs_dir2_sf_lookup(args);
-               goto out;
-       }
-
-       /* dir2 functions require that the data fork is loaded */
-       error = xfs_iread_extents(args->trans, args->dp, XFS_DATA_FORK);
-       if (error)
-               goto out;
-
-       error = xfs_dir2_isblock(args, &is_block);
-       if (error)
-               goto out;
-
-       if (is_block) {
+               break;
+       case XFS_DIR2_FMT_BLOCK:
                error = xfs_dir2_block_lookup(args);
-               goto out;
-       }
-
-       error = xfs_dir2_isleaf(args, &is_leaf);
-       if (error)
-               goto out;
-       if (is_leaf)
+               break;
+       case XFS_DIR2_FMT_LEAF:
                error = xfs_dir2_leaf_lookup(args);
-       else
+               break;
+       case XFS_DIR2_FMT_NODE:
                error = xfs_dir2_node_lookup(args);
-out:
+               break;
+       default:
+               break;
+       }
+
        if (error != -EEXIST)
                return error;
        return 0;
@@ -447,24 +465,20 @@ int
 xfs_dir_removename_args(
        struct xfs_da_args      *args)
 {
-       bool                    is_block, is_leaf;
        int                     error;
 
-       if (args->dp->i_df.if_format == XFS_DINODE_FMT_LOCAL)
+       switch (xfs_dir2_format(args, &error)) {
+       case XFS_DIR2_FMT_SF:
                return xfs_dir2_sf_removename(args);
-
-       error = xfs_dir2_isblock(args, &is_block);
-       if (error)
-               return error;
-       if (is_block)
+       case XFS_DIR2_FMT_BLOCK:
                return xfs_dir2_block_removename(args);
-
-       error = xfs_dir2_isleaf(args, &is_leaf);
-       if (error)
-               return error;
-       if (is_leaf)
+       case XFS_DIR2_FMT_LEAF:
                return xfs_dir2_leaf_removename(args);
-       return xfs_dir2_node_removename(args);
+       case XFS_DIR2_FMT_NODE:
+               return xfs_dir2_node_removename(args);
+       default:
+               return error;
+       }
 }
 
 /*
@@ -508,25 +522,20 @@ int
 xfs_dir_replace_args(
        struct xfs_da_args      *args)
 {
-       bool                    is_block, is_leaf;
        int                     error;
 
-       if (args->dp->i_df.if_format == XFS_DINODE_FMT_LOCAL)
+       switch (xfs_dir2_format(args, &error)) {
+       case XFS_DIR2_FMT_SF:
                return xfs_dir2_sf_replace(args);
-
-       error = xfs_dir2_isblock(args, &is_block);
-       if (error)
-               return error;
-       if (is_block)
+       case XFS_DIR2_FMT_BLOCK:
                return xfs_dir2_block_replace(args);
-
-       error = xfs_dir2_isleaf(args, &is_leaf);
-       if (error)
-               return error;
-       if (is_leaf)
+       case XFS_DIR2_FMT_LEAF:
                return xfs_dir2_leaf_replace(args);
-
-       return xfs_dir2_node_replace(args);
+       case XFS_DIR2_FMT_NODE:
+               return xfs_dir2_node_replace(args);
+       default:
+               return error;
+       }
 }
 
 /*
@@ -632,57 +641,6 @@ xfs_dir2_grow_inode(
        return 0;
 }
 
-/*
- * See if the directory is a single-block form directory.
- */
-int
-xfs_dir2_isblock(
-       struct xfs_da_args      *args,
-       bool                    *isblock)
-{
-       struct xfs_mount        *mp = args->dp->i_mount;
-       xfs_fileoff_t           eof;
-       int                     error;
-
-       error = xfs_bmap_last_offset(args->dp, &eof, XFS_DATA_FORK);
-       if (error)
-               return error;
-
-       *isblock = false;
-       if (XFS_FSB_TO_B(mp, eof) != args->geo->blksize)
-               return 0;
-
-       *isblock = true;
-       if (XFS_IS_CORRUPT(mp, args->dp->i_disk_size != args->geo->blksize)) {
-               xfs_da_mark_sick(args);
-               return -EFSCORRUPTED;
-       }
-       return 0;
-}
-
-/*
- * See if the directory is a single-leaf form directory.
- */
-int
-xfs_dir2_isleaf(
-       struct xfs_da_args      *args,
-       bool                    *isleaf)
-{
-       xfs_fileoff_t           eof;
-       int                     error;
-
-       error = xfs_bmap_last_offset(args->dp, &eof, XFS_DATA_FORK);
-       if (error)
-               return error;
-
-       *isleaf = false;
-       if (eof != args->geo->leafblk + args->geo->fsbcount)
-               return 0;
-
-       *isleaf = true;
-       return 0;
-}
-
 /*
  * Remove the given block from the directory.
  * This routine is used for data and free blocks, leaf/node are done
index 6c00fe24a8987ec160e46522ed05c3b50066d159..6dbe6e9ecb491f69e87e2b8ba2dc54a73f59355a 100644 (file)
@@ -36,6 +36,16 @@ xfs_dir2_samename(
        return !memcmp(n1->name, n2->name, n1->len);
 }
 
+enum xfs_dir2_fmt {
+       XFS_DIR2_FMT_SF,
+       XFS_DIR2_FMT_BLOCK,
+       XFS_DIR2_FMT_LEAF,
+       XFS_DIR2_FMT_NODE,
+       XFS_DIR2_FMT_ERROR,
+};
+
+enum xfs_dir2_fmt xfs_dir2_format(struct xfs_da_args *args, int *error);
+
 /*
  * Convert inode mode to directory entry filetype
  */
@@ -79,8 +89,6 @@ extern int xfs_dir2_sf_to_block(struct xfs_da_args *args);
 /*
  * Interface routines used by userspace utilities
  */
-extern int xfs_dir2_isblock(struct xfs_da_args *args, bool *isblock);
-extern int xfs_dir2_isleaf(struct xfs_da_args *args, bool *isleaf);
 extern int xfs_dir2_shrink_inode(struct xfs_da_args *args, xfs_dir2_db_t db,
                                struct xfs_buf *bp);
 
index a8a51ce53881d3e799b70fe8b85ccaa6ffc64a95..08bfe6f1b3422d05537e1206d3e05276ccfc16b9 100644 (file)
@@ -462,17 +462,12 @@ xfs_exchmaps_dir_to_sf(
        };
        struct xfs_dir2_sf_hdr  sfh;
        struct xfs_buf          *bp;
-       bool                    isblock;
        int                     size;
-       int                     error;
+       int                     error = 0;
 
-       error = xfs_dir2_isblock(&args, &isblock);
-       if (error)
+       if (xfs_dir2_format(&args, &error) != XFS_DIR2_FMT_BLOCK)
                return error;
 
-       if (!isblock)
-               return 0;
-
        error = xfs_dir3_block_read(tp, xmi->xmi_ip2, xmi->xmi_ip2->i_ino, &bp);
        if (error)
                return error;
index 2eba9772da6c1308be41ac5fdfe8661a0a7458df..1e985e7db068c8d2fd7f563260b131aeded8a3bb 100644 (file)
@@ -2269,12 +2269,12 @@ longform_dir2_entry_check(
        xfs_dablk_t             da_bno;
        freetab_t               *freetab;
        int                     i;
-       bool                    isblock;
-       bool                    isleaf;
+       enum xfs_dir2_fmt       fmt;
        xfs_fileoff_t           next_da_bno;
        int                     seeval;
        int                     fixit = 0;
        struct xfs_da_args      args;
+       int                     error;
 
        *need_dot = 1;
        freetab = malloc(FREETAB_SIZE(ip->i_disk_size / mp->m_dir_geo->blksize));
@@ -2294,8 +2294,7 @@ longform_dir2_entry_check(
        /* is this a block, leaf, or node directory? */
        args.dp = ip;
        args.geo = mp->m_dir_geo;
-       libxfs_dir2_isblock(&args, &isblock);
-       libxfs_dir2_isleaf(&args, &isleaf);
+       fmt = libxfs_dir2_format(&args, &error);
 
        /* check directory "data" blocks (ie. name/inode pairs) */
        for (da_bno = 0, next_da_bno = 0;
@@ -2318,7 +2317,7 @@ longform_dir2_entry_check(
                        break;
                }
 
-               if (isblock)
+               if (fmt == XFS_DIR2_FMT_BLOCK)
                        ops = &xfs_dir3_block_buf_ops;
                else
                        ops = &xfs_dir3_data_buf_ops;
@@ -2335,7 +2334,7 @@ longform_dir2_entry_check(
                         * block form and we fail, there isn't anything else to
                         * read, and nothing we can do but trash it.
                         */
-                       if (isblock) {
+                       if (fmt == XFS_DIR2_FMT_BLOCK) {
                                fixit++;
                                goto out_fix;
                        }
@@ -2349,7 +2348,7 @@ longform_dir2_entry_check(
                        error = check_dir3_header(mp, bp, ino);
                        if (error) {
                                fixit++;
-                               if (isblock)
+                               if (fmt == XFS_DIR2_FMT_BLOCK)
                                        goto out_fix;
 
                                libxfs_buf_relse(bp);
@@ -2360,8 +2359,8 @@ longform_dir2_entry_check(
 
                longform_dir2_entry_check_data(mp, ip, num_illegal, need_dot,
                                irec, ino_offset, bp, hashtab,
-                               &freetab, da_bno, isblock);
-               if (isblock)
+                               &freetab, da_bno, fmt == XFS_DIR2_FMT_BLOCK);
+               if (fmt == XFS_DIR2_FMT_BLOCK)
                        break;
 
                libxfs_buf_relse(bp);
@@ -2371,7 +2370,7 @@ longform_dir2_entry_check(
 
        if (!dotdot_update) {
                /* check btree and freespace */
-               if (isblock) {
+               if (fmt == XFS_DIR2_FMT_BLOCK) {
                        struct xfs_dir2_data_hdr *block;
                        xfs_dir2_block_tail_t   *btp;
                        xfs_dir2_leaf_entry_t   *blp;
@@ -2384,7 +2383,7 @@ longform_dir2_entry_check(
                                                be32_to_cpu(btp->stale));
                        if (dir_hash_check(hashtab, ip, seeval))
                                fixit |= 1;
-               } else if (isleaf) {
+               } else if (fmt == XFS_DIR2_FMT_LEAF) {
                        fixit |= longform_dir2_check_leaf(mp, ip, hashtab,
                                                                freetab);
                } else {