Commit 702c90f4 authored by Darrick J. Wong's avatar Darrick J. Wong
Browse files

xfs: support file data forks containing metadata btrees



Create a new fork format type for metadata btrees.  This fork type
requires that the inode is in the metadata directory tree, and only
applies to the data fork.  The actual type of the metadata btree itself
is determined by the di_metatype field.

Signed-off-by: default avatar"Darrick J. Wong" <djwong@kernel.org>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
parent 219ee99d
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -997,7 +997,8 @@ enum xfs_dinode_fmt {
	XFS_DINODE_FMT_LOCAL,		/* bulk data */
	XFS_DINODE_FMT_EXTENTS,		/* struct xfs_bmbt_rec */
	XFS_DINODE_FMT_BTREE,		/* struct xfs_bmdr_block */
	XFS_DINODE_FMT_UUID		/* added long ago, but never used */
	XFS_DINODE_FMT_UUID,		/* added long ago, but never used */
	XFS_DINODE_FMT_META_BTREE,	/* metadata btree */
};

#define XFS_INODE_FORMAT_STR \
@@ -1005,7 +1006,8 @@ enum xfs_dinode_fmt {
	{ XFS_DINODE_FMT_LOCAL,		"local" }, \
	{ XFS_DINODE_FMT_EXTENTS,	"extent" }, \
	{ XFS_DINODE_FMT_BTREE,		"btree" }, \
	{ XFS_DINODE_FMT_UUID,		"uuid" }
	{ XFS_DINODE_FMT_UUID,		"uuid" }, \
	{ XFS_DINODE_FMT_META_BTREE,	"meta_btree" }

/*
 * Max values for extnum and aextnum.
+20 −3
Original line number Diff line number Diff line
@@ -441,6 +441,16 @@ xfs_dinode_verify_fork(
		if (di_nextents > max_extents)
			return __this_address;
		break;
	case XFS_DINODE_FMT_META_BTREE:
		if (!xfs_has_metadir(mp))
			return __this_address;
		if (!(dip->di_flags2 & cpu_to_be64(XFS_DIFLAG2_METADATA)))
			return __this_address;
		switch (be16_to_cpu(dip->di_metatype)) {
		default:
			return __this_address;
		}
		break;
	default:
		return __this_address;
	}
@@ -460,6 +470,10 @@ xfs_dinode_verify_forkoff(
		if (dip->di_forkoff != (roundup(sizeof(xfs_dev_t), 8) >> 3))
			return __this_address;
		break;
	case XFS_DINODE_FMT_META_BTREE:
		if (!xfs_has_metadir(mp) || !xfs_has_parent(mp))
			return __this_address;
		fallthrough;
	case XFS_DINODE_FMT_LOCAL:	/* fall through ... */
	case XFS_DINODE_FMT_EXTENTS:    /* fall through ... */
	case XFS_DINODE_FMT_BTREE:
@@ -637,9 +651,6 @@ xfs_dinode_verify(
	if (mode && nextents + naextents > nblocks)
		return __this_address;

	if (nextents + naextents == 0 && nblocks != 0)
		return __this_address;

	if (S_ISDIR(mode) && nextents > mp->m_dir_geo->max_extents)
		return __this_address;

@@ -743,6 +754,12 @@ xfs_dinode_verify(
			return fa;
	}

	/* metadata inodes containing btrees always have zero extent count */
	if (XFS_DFORK_FORMAT(dip, XFS_DATA_FORK) != XFS_DINODE_FMT_META_BTREE) {
		if (nextents + naextents == 0 && nblocks != 0)
			return __this_address;
	}

	return NULL;
}

+19 −0
Original line number Diff line number Diff line
@@ -267,6 +267,12 @@ xfs_iformat_data_fork(
			return xfs_iformat_extents(ip, dip, XFS_DATA_FORK);
		case XFS_DINODE_FMT_BTREE:
			return xfs_iformat_btree(ip, dip, XFS_DATA_FORK);
		case XFS_DINODE_FMT_META_BTREE:
			switch (ip->i_metatype) {
			default:
				break;
			}
			fallthrough;
		default:
			xfs_inode_verifier_error(ip, -EFSCORRUPTED, __func__,
					dip, sizeof(*dip), __this_address);
@@ -601,6 +607,19 @@ xfs_iflush_fork(
		}
		break;

	case XFS_DINODE_FMT_META_BTREE:
		ASSERT(whichfork == XFS_DATA_FORK);

		if (!(iip->ili_fields & brootflag[whichfork]))
			break;

		switch (ip->i_metatype) {
		default:
			ASSERT(0);
			break;
		}
		break;

	default:
		ASSERT(0);
		break;
+1 −0
Original line number Diff line number Diff line
@@ -983,6 +983,7 @@ xchk_bmap(
	case XFS_DINODE_FMT_UUID:
	case XFS_DINODE_FMT_DEV:
	case XFS_DINODE_FMT_LOCAL:
	case XFS_DINODE_FMT_META_BTREE:
		/* No mappings to check. */
		if (whichfork == XFS_COW_FORK)
			xchk_fblock_set_corrupt(sc, whichfork, 0);
+1 −0
Original line number Diff line number Diff line
@@ -731,6 +731,7 @@ xrep_bmap_check_inputs(
	case XFS_DINODE_FMT_DEV:
	case XFS_DINODE_FMT_LOCAL:
	case XFS_DINODE_FMT_UUID:
	case XFS_DINODE_FMT_META_BTREE:
		return -ECANCELED;
	case XFS_DINODE_FMT_EXTENTS:
	case XFS_DINODE_FMT_BTREE:
Loading