Skip to content

Commit e58ac17

Browse files
Christoph HellwigChandan Babu R
authored andcommitted
xfs: refactor dir format helpers
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 <[email protected]> Reviewed-by: "Darrick J. Wong" <[email protected]> Signed-off-by: Chandan Babu R <[email protected]>
1 parent dfe5feb commit e58ac17

File tree

6 files changed

+105
-150
lines changed

6 files changed

+105
-150
lines changed

fs/xfs/libxfs/xfs_dir2.c

Lines changed: 73 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -256,31 +256,60 @@ xfs_dir_init(
256256
return error;
257257
}
258258

259+
enum xfs_dir2_fmt
260+
xfs_dir2_format(
261+
struct xfs_da_args *args,
262+
int *error)
263+
{
264+
struct xfs_inode *dp = args->dp;
265+
struct xfs_mount *mp = dp->i_mount;
266+
struct xfs_da_geometry *geo = mp->m_dir_geo;
267+
xfs_fileoff_t eof;
268+
269+
xfs_assert_ilocked(dp, XFS_ILOCK_SHARED | XFS_ILOCK_EXCL);
270+
271+
*error = 0;
272+
if (dp->i_df.if_format == XFS_DINODE_FMT_LOCAL)
273+
return XFS_DIR2_FMT_SF;
274+
275+
*error = xfs_bmap_last_offset(dp, &eof, XFS_DATA_FORK);
276+
if (*error)
277+
return XFS_DIR2_FMT_ERROR;
278+
279+
if (eof == XFS_B_TO_FSB(mp, geo->blksize)) {
280+
if (XFS_IS_CORRUPT(mp, dp->i_disk_size != geo->blksize)) {
281+
xfs_da_mark_sick(args);
282+
*error = -EFSCORRUPTED;
283+
return XFS_DIR2_FMT_ERROR;
284+
}
285+
return XFS_DIR2_FMT_BLOCK;
286+
}
287+
if (eof == geo->leafblk + geo->fsbcount)
288+
return XFS_DIR2_FMT_LEAF;
289+
return XFS_DIR2_FMT_NODE;
290+
}
291+
259292
int
260293
xfs_dir_createname_args(
261294
struct xfs_da_args *args)
262295
{
263-
bool is_block, is_leaf;
264296
int error;
265297

266298
if (!args->inumber)
267299
args->op_flags |= XFS_DA_OP_JUSTCHECK;
268300

269-
if (args->dp->i_df.if_format == XFS_DINODE_FMT_LOCAL)
301+
switch (xfs_dir2_format(args, &error)) {
302+
case XFS_DIR2_FMT_SF:
270303
return xfs_dir2_sf_addname(args);
271-
272-
error = xfs_dir2_isblock(args, &is_block);
273-
if (error)
274-
return error;
275-
if (is_block)
304+
case XFS_DIR2_FMT_BLOCK:
276305
return xfs_dir2_block_addname(args);
277-
278-
error = xfs_dir2_isleaf(args, &is_leaf);
279-
if (error)
280-
return error;
281-
if (is_leaf)
306+
case XFS_DIR2_FMT_LEAF:
282307
return xfs_dir2_leaf_addname(args);
283-
return xfs_dir2_node_addname(args);
308+
case XFS_DIR2_FMT_NODE:
309+
return xfs_dir2_node_addname(args);
310+
default:
311+
return error;
312+
}
284313
}
285314

286315
/*
@@ -359,36 +388,25 @@ int
359388
xfs_dir_lookup_args(
360389
struct xfs_da_args *args)
361390
{
362-
bool is_block, is_leaf;
363391
int error;
364392

365-
if (args->dp->i_df.if_format == XFS_DINODE_FMT_LOCAL) {
393+
switch (xfs_dir2_format(args, &error)) {
394+
case XFS_DIR2_FMT_SF:
366395
error = xfs_dir2_sf_lookup(args);
367-
goto out;
368-
}
369-
370-
/* dir2 functions require that the data fork is loaded */
371-
error = xfs_iread_extents(args->trans, args->dp, XFS_DATA_FORK);
372-
if (error)
373-
goto out;
374-
375-
error = xfs_dir2_isblock(args, &is_block);
376-
if (error)
377-
goto out;
378-
379-
if (is_block) {
396+
break;
397+
case XFS_DIR2_FMT_BLOCK:
380398
error = xfs_dir2_block_lookup(args);
381-
goto out;
382-
}
383-
384-
error = xfs_dir2_isleaf(args, &is_leaf);
385-
if (error)
386-
goto out;
387-
if (is_leaf)
399+
break;
400+
case XFS_DIR2_FMT_LEAF:
388401
error = xfs_dir2_leaf_lookup(args);
389-
else
402+
break;
403+
case XFS_DIR2_FMT_NODE:
390404
error = xfs_dir2_node_lookup(args);
391-
out:
405+
break;
406+
default:
407+
break;
408+
}
409+
392410
if (error != -EEXIST)
393411
return error;
394412
return 0;
@@ -448,24 +466,20 @@ int
448466
xfs_dir_removename_args(
449467
struct xfs_da_args *args)
450468
{
451-
bool is_block, is_leaf;
452469
int error;
453470

454-
if (args->dp->i_df.if_format == XFS_DINODE_FMT_LOCAL)
471+
switch (xfs_dir2_format(args, &error)) {
472+
case XFS_DIR2_FMT_SF:
455473
return xfs_dir2_sf_removename(args);
456-
457-
error = xfs_dir2_isblock(args, &is_block);
458-
if (error)
459-
return error;
460-
if (is_block)
474+
case XFS_DIR2_FMT_BLOCK:
461475
return xfs_dir2_block_removename(args);
462-
463-
error = xfs_dir2_isleaf(args, &is_leaf);
464-
if (error)
465-
return error;
466-
if (is_leaf)
476+
case XFS_DIR2_FMT_LEAF:
467477
return xfs_dir2_leaf_removename(args);
468-
return xfs_dir2_node_removename(args);
478+
case XFS_DIR2_FMT_NODE:
479+
return xfs_dir2_node_removename(args);
480+
default:
481+
return error;
482+
}
469483
}
470484

471485
/*
@@ -509,25 +523,20 @@ int
509523
xfs_dir_replace_args(
510524
struct xfs_da_args *args)
511525
{
512-
bool is_block, is_leaf;
513526
int error;
514527

515-
if (args->dp->i_df.if_format == XFS_DINODE_FMT_LOCAL)
528+
switch (xfs_dir2_format(args, &error)) {
529+
case XFS_DIR2_FMT_SF:
516530
return xfs_dir2_sf_replace(args);
517-
518-
error = xfs_dir2_isblock(args, &is_block);
519-
if (error)
520-
return error;
521-
if (is_block)
531+
case XFS_DIR2_FMT_BLOCK:
522532
return xfs_dir2_block_replace(args);
523-
524-
error = xfs_dir2_isleaf(args, &is_leaf);
525-
if (error)
526-
return error;
527-
if (is_leaf)
533+
case XFS_DIR2_FMT_LEAF:
528534
return xfs_dir2_leaf_replace(args);
529-
530-
return xfs_dir2_node_replace(args);
535+
case XFS_DIR2_FMT_NODE:
536+
return xfs_dir2_node_replace(args);
537+
default:
538+
return error;
539+
}
531540
}
532541

533542
/*
@@ -633,57 +642,6 @@ xfs_dir2_grow_inode(
633642
return 0;
634643
}
635644

636-
/*
637-
* See if the directory is a single-block form directory.
638-
*/
639-
int
640-
xfs_dir2_isblock(
641-
struct xfs_da_args *args,
642-
bool *isblock)
643-
{
644-
struct xfs_mount *mp = args->dp->i_mount;
645-
xfs_fileoff_t eof;
646-
int error;
647-
648-
error = xfs_bmap_last_offset(args->dp, &eof, XFS_DATA_FORK);
649-
if (error)
650-
return error;
651-
652-
*isblock = false;
653-
if (XFS_FSB_TO_B(mp, eof) != args->geo->blksize)
654-
return 0;
655-
656-
*isblock = true;
657-
if (XFS_IS_CORRUPT(mp, args->dp->i_disk_size != args->geo->blksize)) {
658-
xfs_da_mark_sick(args);
659-
return -EFSCORRUPTED;
660-
}
661-
return 0;
662-
}
663-
664-
/*
665-
* See if the directory is a single-leaf form directory.
666-
*/
667-
int
668-
xfs_dir2_isleaf(
669-
struct xfs_da_args *args,
670-
bool *isleaf)
671-
{
672-
xfs_fileoff_t eof;
673-
int error;
674-
675-
error = xfs_bmap_last_offset(args->dp, &eof, XFS_DATA_FORK);
676-
if (error)
677-
return error;
678-
679-
*isleaf = false;
680-
if (eof != args->geo->leafblk + args->geo->fsbcount)
681-
return 0;
682-
683-
*isleaf = true;
684-
return 0;
685-
}
686-
687645
/*
688646
* Remove the given block from the directory.
689647
* This routine is used for data and free blocks, leaf/node are done

fs/xfs/libxfs/xfs_dir2.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,16 @@ xfs_dir2_samename(
3636
return !memcmp(n1->name, n2->name, n1->len);
3737
}
3838

39+
enum xfs_dir2_fmt {
40+
XFS_DIR2_FMT_SF,
41+
XFS_DIR2_FMT_BLOCK,
42+
XFS_DIR2_FMT_LEAF,
43+
XFS_DIR2_FMT_NODE,
44+
XFS_DIR2_FMT_ERROR,
45+
};
46+
47+
enum xfs_dir2_fmt xfs_dir2_format(struct xfs_da_args *args, int *error);
48+
3949
/*
4050
* Convert inode mode to directory entry filetype
4151
*/
@@ -79,8 +89,6 @@ extern int xfs_dir2_sf_to_block(struct xfs_da_args *args);
7989
/*
8090
* Interface routines used by userspace utilities
8191
*/
82-
extern int xfs_dir2_isblock(struct xfs_da_args *args, bool *isblock);
83-
extern int xfs_dir2_isleaf(struct xfs_da_args *args, bool *isleaf);
8492
extern int xfs_dir2_shrink_inode(struct xfs_da_args *args, xfs_dir2_db_t db,
8593
struct xfs_buf *bp);
8694

fs/xfs/libxfs/xfs_exchmaps.c

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -465,17 +465,12 @@ xfs_exchmaps_dir_to_sf(
465465
};
466466
struct xfs_dir2_sf_hdr sfh;
467467
struct xfs_buf *bp;
468-
bool isblock;
469468
int size;
470-
int error;
469+
int error = 0;
471470

472-
error = xfs_dir2_isblock(&args, &isblock);
473-
if (error)
471+
if (xfs_dir2_format(&args, &error) != XFS_DIR2_FMT_BLOCK)
474472
return error;
475473

476-
if (!isblock)
477-
return 0;
478-
479474
error = xfs_dir3_block_read(tp, xmi->xmi_ip2, xmi->xmi_ip2->i_ino, &bp);
480475
if (error)
481476
return error;

fs/xfs/scrub/dir.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -808,7 +808,8 @@ xchk_directory_blocks(
808808
free_lblk = XFS_B_TO_FSB(mp, XFS_DIR2_FREE_OFFSET);
809809

810810
/* Is this a block dir? */
811-
error = xfs_dir2_isblock(&args, &is_block);
811+
if (xfs_dir2_format(&args, &error) == XFS_DIR2_FMT_BLOCK)
812+
is_block = true;
812813
if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, lblk, &error))
813814
goto out;
814815

fs/xfs/scrub/readdir.c

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,6 @@ xchk_dir_walk(
276276
.trans = sc->tp,
277277
.owner = dp->i_ino,
278278
};
279-
bool isblock;
280279
int error;
281280

282281
if (xfs_is_shutdown(dp->i_mount))
@@ -285,22 +284,17 @@ xchk_dir_walk(
285284
ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
286285
xfs_assert_ilocked(dp, XFS_ILOCK_SHARED | XFS_ILOCK_EXCL);
287286

288-
if (dp->i_df.if_format == XFS_DINODE_FMT_LOCAL)
287+
switch (xfs_dir2_format(&args, &error)) {
288+
case XFS_DIR2_FMT_SF:
289289
return xchk_dir_walk_sf(sc, dp, dirent_fn, priv);
290-
291-
/* dir2 functions require that the data fork is loaded */
292-
error = xfs_iread_extents(sc->tp, dp, XFS_DATA_FORK);
293-
if (error)
294-
return error;
295-
296-
error = xfs_dir2_isblock(&args, &isblock);
297-
if (error)
298-
return error;
299-
300-
if (isblock)
290+
case XFS_DIR2_FMT_BLOCK:
301291
return xchk_dir_walk_block(sc, dp, dirent_fn, priv);
302-
303-
return xchk_dir_walk_leaf(sc, dp, dirent_fn, priv);
292+
case XFS_DIR2_FMT_LEAF:
293+
case XFS_DIR2_FMT_NODE:
294+
return xchk_dir_walk_leaf(sc, dp, dirent_fn, priv);
295+
default:
296+
return error;
297+
}
304298
}
305299

306300
/*

fs/xfs/xfs_dir2_readdir.c

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -516,7 +516,6 @@ xfs_readdir(
516516
{
517517
struct xfs_da_args args = { NULL };
518518
unsigned int lock_mode;
519-
bool isblock;
520519
int error;
521520

522521
trace_xfs_readdir(dp);
@@ -539,18 +538,18 @@ xfs_readdir(
539538
return xfs_dir2_sf_getdents(&args, ctx);
540539

541540
lock_mode = xfs_ilock_data_map_shared(dp);
542-
error = xfs_dir2_isblock(&args, &isblock);
543-
if (error)
544-
goto out_unlock;
545-
546-
if (isblock) {
541+
switch (xfs_dir2_format(&args, &error)) {
542+
case XFS_DIR2_FMT_BLOCK:
547543
error = xfs_dir2_block_getdents(&args, ctx, &lock_mode);
548-
goto out_unlock;
544+
break;
545+
case XFS_DIR2_FMT_LEAF:
546+
case XFS_DIR2_FMT_NODE:
547+
error = xfs_dir2_leaf_getdents(&args, ctx, bufsize, &lock_mode);
548+
break;
549+
default:
550+
break;
549551
}
550552

551-
error = xfs_dir2_leaf_getdents(&args, ctx, bufsize, &lock_mode);
552-
553-
out_unlock:
554553
if (lock_mode)
555554
xfs_iunlock(dp, lock_mode);
556555
return error;

0 commit comments

Comments
 (0)