Skip to content

Commit 679b098

Browse files
author
Darrick J. Wong
committed
xfs: refactor directory tree root predicates
Metadata directory trees make reasoning about the parent of a file more difficult. Traditionally, user files are children of sb_rootino, and metadata files are "children" of the superblock. Now, we add a third possibility -- some metadata files can be children of sb_metadirino, but the classic ones (rt free space data and quotas) are left alone. Let's add some helper functions (instead of open-coding the logic everywhere) to make scrub logic easier to understand. Signed-off-by: Darrick J. Wong <[email protected]> Reviewed-by: Christoph Hellwig <[email protected]>
1 parent be42fc1 commit 679b098

File tree

13 files changed

+76
-45
lines changed

13 files changed

+76
-45
lines changed

fs/xfs/scrub/common.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1452,3 +1452,32 @@ xchk_inode_is_allocated(
14521452
rcu_read_unlock();
14531453
return error;
14541454
}
1455+
1456+
/* Is this inode a root directory for either tree? */
1457+
bool
1458+
xchk_inode_is_dirtree_root(const struct xfs_inode *ip)
1459+
{
1460+
struct xfs_mount *mp = ip->i_mount;
1461+
1462+
return ip == mp->m_rootip ||
1463+
(xfs_has_metadir(mp) && ip == mp->m_metadirip);
1464+
}
1465+
1466+
/* Does the superblock point down to this inode? */
1467+
bool
1468+
xchk_inode_is_sb_rooted(const struct xfs_inode *ip)
1469+
{
1470+
return xchk_inode_is_dirtree_root(ip) ||
1471+
xfs_is_sb_inum(ip->i_mount, ip->i_ino);
1472+
}
1473+
1474+
/* What is the root directory inumber for this inode? */
1475+
xfs_ino_t
1476+
xchk_inode_rootdir_inum(const struct xfs_inode *ip)
1477+
{
1478+
struct xfs_mount *mp = ip->i_mount;
1479+
1480+
if (xfs_is_metadir_inode(ip))
1481+
return mp->m_metadirip->i_ino;
1482+
return mp->m_rootip->i_ino;
1483+
}

fs/xfs/scrub/common.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,4 +242,8 @@ void xchk_fsgates_enable(struct xfs_scrub *sc, unsigned int scrub_fshooks);
242242
int xchk_inode_is_allocated(struct xfs_scrub *sc, xfs_agino_t agino,
243243
bool *inuse);
244244

245+
bool xchk_inode_is_dirtree_root(const struct xfs_inode *ip);
246+
bool xchk_inode_is_sb_rooted(const struct xfs_inode *ip);
247+
xfs_ino_t xchk_inode_rootdir_inum(const struct xfs_inode *ip);
248+
245249
#endif /* __XFS_SCRUB_COMMON_H__ */

fs/xfs/scrub/dir.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@ xchk_dir_actor(
253253
* If this is ".." in the root inode, check that the inum
254254
* matches this dir.
255255
*/
256-
if (dp->i_ino == mp->m_sb.sb_rootino && ino != dp->i_ino)
256+
if (xchk_inode_is_dirtree_root(dp) && ino != dp->i_ino)
257257
xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, offset);
258258
}
259259

fs/xfs/scrub/dir_repair.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1270,7 +1270,7 @@ xrep_dir_scan_dirtree(
12701270
int error;
12711271

12721272
/* Roots of directory trees are their own parents. */
1273-
if (sc->ip == sc->mp->m_rootip)
1273+
if (xchk_inode_is_dirtree_root(sc->ip))
12741274
xrep_findparent_scan_found(&rd->pscan, sc->ip->i_ino);
12751275

12761276
/*

fs/xfs/scrub/dirtree.c

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -917,7 +917,7 @@ xchk_dirtree(
917917
* scan, because the hook doesn't detach until after sc->ip gets
918918
* released during teardown.
919919
*/
920-
dl->root_ino = sc->mp->m_rootip->i_ino;
920+
dl->root_ino = xchk_inode_rootdir_inum(sc->ip);
921921
dl->scan_ino = sc->ip->i_ino;
922922

923923
trace_xchk_dirtree_start(sc->ip, sc->sm, 0);
@@ -983,3 +983,16 @@ xchk_dirtree(
983983
trace_xchk_dirtree_done(sc->ip, sc->sm, error);
984984
return error;
985985
}
986+
987+
/* Does the directory targetted by this scrub have no parents? */
988+
bool
989+
xchk_dirtree_parentless(const struct xchk_dirtree *dl)
990+
{
991+
struct xfs_scrub *sc = dl->sc;
992+
993+
if (xchk_inode_is_dirtree_root(sc->ip))
994+
return true;
995+
if (VFS_I(sc->ip)->i_nlink == 0)
996+
return true;
997+
return false;
998+
}

fs/xfs/scrub/dirtree.h

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -156,17 +156,7 @@ struct xchk_dirtree {
156156
#define xchk_dirtree_for_each_path(dl, path) \
157157
list_for_each_entry((path), &(dl)->path_list, list)
158158

159-
static inline bool
160-
xchk_dirtree_parentless(const struct xchk_dirtree *dl)
161-
{
162-
struct xfs_scrub *sc = dl->sc;
163-
164-
if (sc->ip == sc->mp->m_rootip)
165-
return true;
166-
if (VFS_I(sc->ip)->i_nlink == 0)
167-
return true;
168-
return false;
169-
}
159+
bool xchk_dirtree_parentless(const struct xchk_dirtree *dl);
170160

171161
int xchk_dirtree_find_paths_to_root(struct xchk_dirtree *dl);
172162
int xchk_dirpath_append(struct xchk_dirtree *dl, struct xfs_inode *ip,

fs/xfs/scrub/findparent.c

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -362,15 +362,18 @@ xrep_findparent_confirm(
362362
};
363363
int error;
364364

365-
/*
366-
* The root directory always points to itself. Unlinked dirs can point
367-
* anywhere, so we point them at the root dir too.
368-
*/
369-
if (sc->ip == sc->mp->m_rootip || VFS_I(sc->ip)->i_nlink == 0) {
365+
/* The root directory always points to itself. */
366+
if (sc->ip == sc->mp->m_rootip) {
370367
*parent_ino = sc->mp->m_sb.sb_rootino;
371368
return 0;
372369
}
373370

371+
/* Unlinked dirs can point anywhere; point them up to the root dir. */
372+
if (VFS_I(sc->ip)->i_nlink == 0) {
373+
*parent_ino = xchk_inode_rootdir_inum(sc->ip);
374+
return 0;
375+
}
376+
374377
/* Reject garbage parent inode numbers and self-referential parents. */
375378
if (*parent_ino == NULLFSINO)
376379
return 0;
@@ -413,7 +416,7 @@ xrep_findparent_self_reference(
413416
return sc->mp->m_sb.sb_rootino;
414417

415418
if (VFS_I(sc->ip)->i_nlink == 0)
416-
return sc->mp->m_sb.sb_rootino;
419+
return xchk_inode_rootdir_inum(sc->ip);
417420

418421
return NULLFSINO;
419422
}

fs/xfs/scrub/inode_repair.c

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1767,15 +1767,8 @@ xrep_inode_pptr(
17671767
if (inode->i_nlink == 0 && !(inode->i_state & I_LINKABLE))
17681768
return 0;
17691769

1770-
/* The root directory doesn't have a parent pointer. */
1771-
if (ip == mp->m_rootip)
1772-
return 0;
1773-
1774-
/*
1775-
* Metadata inodes are rooted in the superblock and do not have any
1776-
* parents.
1777-
*/
1778-
if (xfs_is_internal_inode(ip))
1770+
/* Children of the superblock do not have parent pointers. */
1771+
if (xchk_inode_is_sb_rooted(ip))
17791772
return 0;
17801773

17811774
/* Inode already has an attr fork; no further work possible here. */

fs/xfs/scrub/nlinks.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ xchk_nlinks_collect_dirent(
279279
* determine the backref count.
280280
*/
281281
if (dotdot) {
282-
if (dp == sc->mp->m_rootip)
282+
if (xchk_inode_is_dirtree_root(dp))
283283
error = xchk_nlinks_update_incore(xnc, ino, 1, 0, 0);
284284
else if (!xfs_has_parent(sc->mp))
285285
error = xchk_nlinks_update_incore(xnc, ino, 0, 1, 0);
@@ -735,7 +735,7 @@ xchk_nlinks_compare_inode(
735735
}
736736
}
737737

738-
if (ip == sc->mp->m_rootip) {
738+
if (xchk_inode_is_dirtree_root(ip)) {
739739
/*
740740
* For the root of a directory tree, both the '.' and '..'
741741
* entries should point to the root directory. The dotdot

fs/xfs/scrub/nlinks_repair.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,9 @@ xrep_nlinks_is_orphaned(
6060
unsigned int actual_nlink,
6161
const struct xchk_nlink *obs)
6262
{
63-
struct xfs_mount *mp = ip->i_mount;
64-
6563
if (obs->parents != 0)
6664
return false;
67-
if (ip == mp->m_rootip || ip == sc->orphanage)
65+
if (xchk_inode_is_dirtree_root(ip) || ip == sc->orphanage)
6866
return false;
6967
return actual_nlink != 0;
7068
}

0 commit comments

Comments
 (0)