Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 035e00ac authored by Darrick J. Wong's avatar Darrick J. Wong Committed by Dave Chinner
Browse files

xfs: define the on-disk rmap btree format



Originally-From: Dave Chinner <dchinner@redhat.com>

Now we have all the surrounding call infrastructure in place, we can
start filling out the rmap btree implementation. Start with the
on-disk btree format; add everything needed to read, write and
manipulate rmap btree blocks. This prepares the way for adding the
btree operations implementation.

[darrick: record owner and offset info in rmap btree]
[darrick: fork, bmbt and unwritten state in rmap btree]
[darrick: flags are a separate field in xfs_rmap_irec]
[darrick: calculate maxlevels separately]
[darrick: move the 'unwritten' bit into unused parts of rm_offset]

Signed-off-by: default avatarDave Chinner <dchinner@redhat.com>
Signed-off-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: default avatarDave Chinner <dchinner@redhat.com>
Reviewed-by: default avatarBrian Foster <bfoster@redhat.com>
Signed-off-by: default avatarDave Chinner <david@fromorbit.com>
parent 673930c3
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -53,6 +53,7 @@ xfs-y += $(addprefix libxfs/, \
				   xfs_inode_buf.o \
				   xfs_log_rlimit.o \
				   xfs_rmap.o \
				   xfs_rmap_btree.o \
				   xfs_sb.o \
				   xfs_symlink_remote.o \
				   xfs_trans_resv.o \
+3 −0
Original line number Diff line number Diff line
@@ -1213,6 +1213,9 @@ xfs_btree_set_refs(
	case XFS_BTNUM_BMAP:
		xfs_buf_set_ref(bp, XFS_BMAP_BTREE_REF);
		break;
	case XFS_BTNUM_RMAP:
		xfs_buf_set_ref(bp, XFS_RMAP_BTREE_REF);
		break;
	default:
		ASSERT(0);
	}
+14 −8
Original line number Diff line number Diff line
@@ -38,10 +38,11 @@ union xfs_btree_ptr {
};

union xfs_btree_key {
	xfs_bmbt_key_t		bmbt;
	struct xfs_bmbt_key		bmbt;
	xfs_bmdr_key_t			bmbr;	/* bmbt root block */
	xfs_alloc_key_t			alloc;
	xfs_inobt_key_t		inobt;
	struct xfs_inobt_key		inobt;
	struct xfs_rmap_key		rmap;
};

/*
@@ -56,13 +57,18 @@ union xfs_btree_bigkey {
	xfs_bmdr_key_t			bmbr;	/* bmbt root block */
	xfs_alloc_key_t			alloc;
	struct xfs_inobt_key		inobt;
	struct {
		struct xfs_rmap_key	rmap;
		struct xfs_rmap_key	rmap_hi;
	};
};

union xfs_btree_rec {
	xfs_bmbt_rec_t		bmbt;
	struct xfs_bmbt_rec		bmbt;
	xfs_bmdr_rec_t			bmbr;	/* bmbt root block */
	xfs_alloc_rec_t		alloc;
	xfs_inobt_rec_t		inobt;
	struct xfs_alloc_rec		alloc;
	struct xfs_inobt_rec		inobt;
	struct xfs_rmap_rec		rmap;
};

/*
+73 −0
Original line number Diff line number Diff line
@@ -1347,6 +1347,79 @@ struct xfs_owner_info {
#define XFS_RMAP_OWN_INODES	(-7ULL)	/* Inode chunk */
#define XFS_RMAP_OWN_MIN	(-8ULL) /* guard */

#define XFS_RMAP_NON_INODE_OWNER(owner)	(!!((owner) & (1ULL << 63)))

/*
 * Data record structure
 */
struct xfs_rmap_rec {
	__be32		rm_startblock;	/* extent start block */
	__be32		rm_blockcount;	/* extent length */
	__be64		rm_owner;	/* extent owner */
	__be64		rm_offset;	/* offset within the owner */
};

/*
 * rmap btree record
 *  rm_offset:63 is the attribute fork flag
 *  rm_offset:62 is the bmbt block flag
 *  rm_offset:61 is the unwritten extent flag (same as l0:63 in bmbt)
 *  rm_offset:54-60 aren't used and should be zero
 *  rm_offset:0-53 is the block offset within the inode
 */
#define XFS_RMAP_OFF_ATTR_FORK	((__uint64_t)1ULL << 63)
#define XFS_RMAP_OFF_BMBT_BLOCK	((__uint64_t)1ULL << 62)
#define XFS_RMAP_OFF_UNWRITTEN	((__uint64_t)1ULL << 61)

#define XFS_RMAP_LEN_MAX	((__uint32_t)~0U)
#define XFS_RMAP_OFF_FLAGS	(XFS_RMAP_OFF_ATTR_FORK | \
				 XFS_RMAP_OFF_BMBT_BLOCK | \
				 XFS_RMAP_OFF_UNWRITTEN)
#define XFS_RMAP_OFF_MASK	((__uint64_t)0x3FFFFFFFFFFFFFULL)

#define XFS_RMAP_OFF(off)		((off) & XFS_RMAP_OFF_MASK)

#define XFS_RMAP_IS_BMBT_BLOCK(off)	(!!((off) & XFS_RMAP_OFF_BMBT_BLOCK))
#define XFS_RMAP_IS_ATTR_FORK(off)	(!!((off) & XFS_RMAP_OFF_ATTR_FORK))
#define XFS_RMAP_IS_UNWRITTEN(len)	(!!((off) & XFS_RMAP_OFF_UNWRITTEN))

#define RMAPBT_STARTBLOCK_BITLEN	32
#define RMAPBT_BLOCKCOUNT_BITLEN	32
#define RMAPBT_OWNER_BITLEN		64
#define RMAPBT_ATTRFLAG_BITLEN		1
#define RMAPBT_BMBTFLAG_BITLEN		1
#define RMAPBT_EXNTFLAG_BITLEN		1
#define RMAPBT_UNUSED_OFFSET_BITLEN	7
#define RMAPBT_OFFSET_BITLEN		54

#define XFS_RMAP_ATTR_FORK		(1 << 0)
#define XFS_RMAP_BMBT_BLOCK		(1 << 1)
#define XFS_RMAP_UNWRITTEN		(1 << 2)
#define XFS_RMAP_KEY_FLAGS		(XFS_RMAP_ATTR_FORK | \
					 XFS_RMAP_BMBT_BLOCK)
#define XFS_RMAP_REC_FLAGS		(XFS_RMAP_UNWRITTEN)
struct xfs_rmap_irec {
	xfs_agblock_t	rm_startblock;	/* extent start block */
	xfs_extlen_t	rm_blockcount;	/* extent length */
	__uint64_t	rm_owner;	/* extent owner */
	__uint64_t	rm_offset;	/* offset within the owner */
	unsigned int	rm_flags;	/* state flags */
};

/*
 * Key structure
 *
 * We don't use the length for lookups
 */
struct xfs_rmap_key {
	__be32		rm_startblock;	/* extent start block */
	__be64		rm_owner;	/* extent owner */
	__be64		rm_offset;	/* offset within the owner */
} __attribute__((packed));

/* btree pointer type */
typedef __be32 xfs_rmap_ptr_t;

#define	XFS_RMAP_BLOCK(mp) \
	(xfs_sb_version_hasfinobt(&((mp)->m_sb)) ? \
	 XFS_FIBT_BLOCK(mp) + 1 : \
+67 −0
Original line number Diff line number Diff line
@@ -68,6 +68,73 @@ xfs_rmap_skip_owner_update(

struct xfs_buf;

static inline __u64
xfs_rmap_irec_offset_pack(
	const struct xfs_rmap_irec	*irec)
{
	__u64			x;

	x = XFS_RMAP_OFF(irec->rm_offset);
	if (irec->rm_flags & XFS_RMAP_ATTR_FORK)
		x |= XFS_RMAP_OFF_ATTR_FORK;
	if (irec->rm_flags & XFS_RMAP_BMBT_BLOCK)
		x |= XFS_RMAP_OFF_BMBT_BLOCK;
	if (irec->rm_flags & XFS_RMAP_UNWRITTEN)
		x |= XFS_RMAP_OFF_UNWRITTEN;
	return x;
}

static inline int
xfs_rmap_irec_offset_unpack(
	__u64			offset,
	struct xfs_rmap_irec	*irec)
{
	if (offset & ~(XFS_RMAP_OFF_MASK | XFS_RMAP_OFF_FLAGS))
		return -EFSCORRUPTED;
	irec->rm_offset = XFS_RMAP_OFF(offset);
	if (offset & XFS_RMAP_OFF_ATTR_FORK)
		irec->rm_flags |= XFS_RMAP_ATTR_FORK;
	if (offset & XFS_RMAP_OFF_BMBT_BLOCK)
		irec->rm_flags |= XFS_RMAP_BMBT_BLOCK;
	if (offset & XFS_RMAP_OFF_UNWRITTEN)
		irec->rm_flags |= XFS_RMAP_UNWRITTEN;
	return 0;
}

static inline void
xfs_owner_info_unpack(
	struct xfs_owner_info	*oinfo,
	uint64_t		*owner,
	uint64_t		*offset,
	unsigned int		*flags)
{
	unsigned int		r = 0;

	*owner = oinfo->oi_owner;
	*offset = oinfo->oi_offset;
	if (oinfo->oi_flags & XFS_OWNER_INFO_ATTR_FORK)
		r |= XFS_RMAP_ATTR_FORK;
	if (oinfo->oi_flags & XFS_OWNER_INFO_BMBT_BLOCK)
		r |= XFS_RMAP_BMBT_BLOCK;
	*flags = r;
}

static inline void
xfs_owner_info_pack(
	struct xfs_owner_info	*oinfo,
	uint64_t		owner,
	uint64_t		offset,
	unsigned int		flags)
{
	oinfo->oi_owner = owner;
	oinfo->oi_offset = XFS_RMAP_OFF(offset);
	oinfo->oi_flags = 0;
	if (flags & XFS_RMAP_ATTR_FORK)
		oinfo->oi_flags |= XFS_OWNER_INFO_ATTR_FORK;
	if (flags & XFS_RMAP_BMBT_BLOCK)
		oinfo->oi_flags |= XFS_OWNER_INFO_BMBT_BLOCK;
}

int xfs_rmap_alloc(struct xfs_trans *tp, struct xfs_buf *agbp,
		   xfs_agnumber_t agno, xfs_agblock_t bno, xfs_extlen_t len,
		   struct xfs_owner_info *oinfo);
Loading