@@ -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. */
@@ -122,9 +122,8 @@
#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
@@ -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
@@ -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);
@@ -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;
@@ -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 {