All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v8 00/29] xfsprogs: add realtime reverse-mapping support
@ 2016-08-25 23:58 Darrick J. Wong
  2016-08-25 23:58 ` [PATCH 01/29] xfs: refactor long-format btree header verification routines Darrick J. Wong
                   ` (28 more replies)
  0 siblings, 29 replies; 30+ messages in thread
From: Darrick J. Wong @ 2016-08-25 23:58 UTC (permalink / raw)
  To: david, darrick.wong; +Cc: linux-xfs, xfs

Hi all,

This is the eighth revision of a patchset that adds to XFS kernel
support for mapping multiple file logical blocks to the same physical
block (reflink/deduplication), implements the beginnings of online
metadata scrubbing and preening, and implements reverse mapping for
the realtime device.  There shouldn't be any incompatible on-disk
format changes, pending a thorough review of the patches within.

At the beginning of this series are imports of all the kernel patches
against libxfs/ that are needed to provide refcount btrees and reflink
support.  Please note that these patches /do/ have diffs against files
in the libxfs/ directory (mostly for deferred ops) that do not start
with 'xfs_', so the libxfs-apply script cannot be used in isolation.

Following that are fixes against db, io, repair, and mkfs to deal with
the realtime reverse mapping btree.  The repair changes are minimal
here, since we can largely take advantage of the existing code in
repair to track and rebuild reverse mapping btrees.

If you're going to start using this mess, you probably ought to just
pull from my github trees for kernel[1], xfsprogs[2], xfstests[3],
xfs-docs[4], and man-pages[5].  The kernel patches in the git trees
should apply to 4.8-rc3; xfsprogs patches to for-next; and xfstest to
master.

The patches have been xfstested with x64, ppc64, and armhf; all tests
in the clone and rmap groups pass.  AFAICT they don't cause any new
failures for the 'auto' group.

This is an extraordinary way to eat your data.  Enjoy! 
Comments and questions are, as always, welcome.

--D

[1] https://github.com/djwong/linux/tree/djwong-devel
[2] https://github.com/djwong/xfsprogs/tree/djwong-devel
[3] https://github.com/djwong/xfstests/tree/djwong-devel
[4] https://github.com/djwong/xfs-documentation/tree/djwong-devel
[5] https://github.com/djwong/man-pages/tree/djwong-devel

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 01/29] xfs: refactor long-format btree header verification routines
  2016-08-25 23:58 [PATCH v8 00/29] xfsprogs: add realtime reverse-mapping support Darrick J. Wong
@ 2016-08-25 23:58 ` Darrick J. Wong
  2016-08-25 23:58 ` [PATCH 02/29] xfs: make iroot_realloc a btree function Darrick J. Wong
                   ` (27 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: Darrick J. Wong @ 2016-08-25 23:58 UTC (permalink / raw)
  To: david, darrick.wong; +Cc: linux-xfs, xfs

Create two helper functions to verify the headers of a long format
btree block.  We'll use this later for the realtime rmapbt.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 libxfs/xfs_bmap_btree.c |   22 ++--------------------
 libxfs/xfs_btree.c      |   47 +++++++++++++++++++++++++++++++++++++++++++++++
 libxfs/xfs_btree.h      |    3 +++
 3 files changed, 52 insertions(+), 20 deletions(-)


diff --git a/libxfs/xfs_bmap_btree.c b/libxfs/xfs_bmap_btree.c
index 54306b1..72a6390 100644
--- a/libxfs/xfs_bmap_btree.c
+++ b/libxfs/xfs_bmap_btree.c
@@ -674,17 +674,11 @@ xfs_bmbt_verify(
 
 	switch (block->bb_magic) {
 	case cpu_to_be32(XFS_BMAP_CRC_MAGIC):
-		if (!xfs_sb_version_hascrc(&mp->m_sb))
-			return false;
-		if (!uuid_equal(&block->bb_u.l.bb_uuid, &mp->m_sb.sb_meta_uuid))
-			return false;
-		if (be64_to_cpu(block->bb_u.l.bb_blkno) != bp->b_bn)
-			return false;
 		/*
 		 * XXX: need a better way of verifying the owner here. Right now
 		 * just make sure there has been one set.
 		 */
-		if (be64_to_cpu(block->bb_u.l.bb_owner) == 0)
+		if (!xfs_btree_lblock_v5hdr_verify(bp, XFS_RMAP_OWN_UNKNOWN))
 			return false;
 		/* fall through */
 	case cpu_to_be32(XFS_BMAP_MAGIC):
@@ -703,20 +697,8 @@ xfs_bmbt_verify(
 	level = be16_to_cpu(block->bb_level);
 	if (level > max(mp->m_bm_maxlevels[0], mp->m_bm_maxlevels[1]))
 		return false;
-	if (be16_to_cpu(block->bb_numrecs) > mp->m_bmap_dmxr[level != 0])
-		return false;
-
-	/* sibling pointer verification */
-	if (!block->bb_u.l.bb_leftsib ||
-	    (block->bb_u.l.bb_leftsib != cpu_to_be64(NULLFSBLOCK) &&
-	     !XFS_FSB_SANITY_CHECK(mp, be64_to_cpu(block->bb_u.l.bb_leftsib))))
-		return false;
-	if (!block->bb_u.l.bb_rightsib ||
-	    (block->bb_u.l.bb_rightsib != cpu_to_be64(NULLFSBLOCK) &&
-	     !XFS_FSB_SANITY_CHECK(mp, be64_to_cpu(block->bb_u.l.bb_rightsib))))
-		return false;
 
-	return true;
+	return xfs_btree_lblock_verify(bp, mp->m_bmap_dmxr[level != 0]);
 }
 
 static void
diff --git a/libxfs/xfs_btree.c b/libxfs/xfs_btree.c
index ad205c0..df28812 100644
--- a/libxfs/xfs_btree.c
+++ b/libxfs/xfs_btree.c
@@ -4453,6 +4453,53 @@ xfs_btree_change_owner(
 			&bbcoi);
 }
 
+/* Verify the v5 fields of a long-format btree block. */
+bool
+xfs_btree_lblock_v5hdr_verify(
+	struct xfs_buf		*bp,
+	__uint64_t		owner)
+{
+	struct xfs_mount	*mp = bp->b_target->bt_mount;
+	struct xfs_btree_block	*block = XFS_BUF_TO_BLOCK(bp);
+
+	if (!xfs_sb_version_hascrc(&mp->m_sb))
+		return false;
+	if (!uuid_equal(&block->bb_u.l.bb_uuid, &mp->m_sb.sb_meta_uuid))
+		return false;
+	if (block->bb_u.l.bb_blkno != cpu_to_be64(bp->b_bn))
+		return false;
+	if (owner != XFS_RMAP_OWN_UNKNOWN &&
+	    be64_to_cpu(block->bb_u.l.bb_owner) != owner)
+		return false;
+	return true;
+}
+
+/* Verify a long-format btree block. */
+bool
+xfs_btree_lblock_verify(
+	struct xfs_buf		*bp,
+	unsigned int		max_recs)
+{
+	struct xfs_mount	*mp = bp->b_target->bt_mount;
+	struct xfs_btree_block	*block = XFS_BUF_TO_BLOCK(bp);
+
+	/* numrecs verification */
+	if (be16_to_cpu(block->bb_numrecs) > max_recs)
+		return false;
+
+	/* sibling pointer verification */
+	if (!block->bb_u.l.bb_leftsib ||
+	    (block->bb_u.l.bb_leftsib != cpu_to_be64(NULLFSBLOCK) &&
+	     !XFS_FSB_SANITY_CHECK(mp, be64_to_cpu(block->bb_u.l.bb_leftsib))))
+		return false;
+	if (!block->bb_u.l.bb_rightsib ||
+	    (block->bb_u.l.bb_rightsib != cpu_to_be64(NULLFSBLOCK) &&
+	     !XFS_FSB_SANITY_CHECK(mp, be64_to_cpu(block->bb_u.l.bb_rightsib))))
+		return false;
+
+	return true;
+}
+
 /**
  * xfs_btree_sblock_v5hdr_verify() -- verify the v5 fields of a short-format
  *				      btree block
diff --git a/libxfs/xfs_btree.h b/libxfs/xfs_btree.h
index f81b2a8..a7770dd 100644
--- a/libxfs/xfs_btree.h
+++ b/libxfs/xfs_btree.h
@@ -513,6 +513,9 @@ static inline int xfs_btree_get_level(struct xfs_btree_block *block)
 
 bool xfs_btree_sblock_v5hdr_verify(struct xfs_buf *bp);
 bool xfs_btree_sblock_verify(struct xfs_buf *bp, unsigned int max_recs);
+bool xfs_btree_lblock_v5hdr_verify(struct xfs_buf *bp, __uint64_t owner);
+bool xfs_btree_lblock_verify(struct xfs_buf *bp, unsigned int max_recs);
+
 uint xfs_btree_compute_maxlevels(struct xfs_mount *mp, uint *limits,
 				 unsigned long len);
 xfs_extlen_t xfs_btree_calc_size(struct xfs_mount *mp, uint *limits,

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 02/29] xfs: make iroot_realloc a btree function
  2016-08-25 23:58 [PATCH v8 00/29] xfsprogs: add realtime reverse-mapping support Darrick J. Wong
  2016-08-25 23:58 ` [PATCH 01/29] xfs: refactor long-format btree header verification routines Darrick J. Wong
@ 2016-08-25 23:58 ` Darrick J. Wong
  2016-08-25 23:58 ` [PATCH 03/29] xfs: support storing records in the inode core root Darrick J. Wong
                   ` (26 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: Darrick J. Wong @ 2016-08-25 23:58 UTC (permalink / raw)
  To: david, darrick.wong; +Cc: linux-xfs, xfs

For btrees that are rooted in the inode core, we have to have a
function to resize the root.  This is fairly specific to each
btree type, so make xfs_iroot_realloc a per-btree function.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 libxfs/xfs_bmap.c       |    6 +-
 libxfs/xfs_bmap_btree.c |  139 +++++++++++++++++++++++++++++++++++++++++++++++
 libxfs/xfs_bmap_btree.h |    3 +
 libxfs/xfs_btree.c      |   12 +---
 libxfs/xfs_btree.h      |    7 ++
 libxfs/xfs_inode_fork.c |  129 --------------------------------------------
 libxfs/xfs_inode_fork.h |    1 
 7 files changed, 156 insertions(+), 141 deletions(-)


diff --git a/libxfs/xfs_bmap.c b/libxfs/xfs_bmap.c
index 4721cff..f6820c6 100644
--- a/libxfs/xfs_bmap.c
+++ b/libxfs/xfs_bmap.c
@@ -663,7 +663,7 @@ xfs_bmap_btree_to_extents(
 	xfs_trans_binval(tp, cbp);
 	if (cur->bc_bufs[0] == cbp)
 		cur->bc_bufs[0] = NULL;
-	xfs_iroot_realloc(ip, -1, whichfork);
+	xfs_bmbt_iroot_realloc(ip, -1, whichfork);
 	ASSERT(ifp->if_broot == NULL);
 	ASSERT((ifp->if_flags & XFS_IFBROOT) == 0);
 	XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_EXTENTS);
@@ -709,7 +709,7 @@ xfs_bmap_extents_to_btree(
 	/*
 	 * Make space in the inode incore.
 	 */
-	xfs_iroot_realloc(ip, 1, whichfork);
+	xfs_bmbt_iroot_realloc(ip, 1, whichfork);
 	ifp->if_flags |= XFS_IFBROOT;
 
 	/*
@@ -756,7 +756,7 @@ try_another_ag:
 	args.wasdel = wasdel;
 	*logflagsp = 0;
 	if ((error = xfs_alloc_vextent(&args))) {
-		xfs_iroot_realloc(ip, -1, whichfork);
+		xfs_bmbt_iroot_realloc(ip, -1, whichfork);
 		xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
 		return error;
 	}
diff --git a/libxfs/xfs_bmap_btree.c b/libxfs/xfs_bmap_btree.c
index 72a6390..60969f3 100644
--- a/libxfs/xfs_bmap_btree.c
+++ b/libxfs/xfs_bmap_btree.c
@@ -664,6 +664,144 @@ xfs_bmbt_diff_two_keys(
 			  be64_to_cpu(k2->bmbt.br_startoff);
 }
 
+/*
+ * Reallocate the space for if_broot based on the number of records
+ * being added or deleted as indicated in rec_diff.  Move the records
+ * and pointers in if_broot to fit the new size.  When shrinking this
+ * will eliminate holes between the records and pointers created by
+ * the caller.  When growing this will create holes to be filled in
+ * by the caller.
+ *
+ * The caller must not request to add more records than would fit in
+ * the on-disk inode root.  If the if_broot is currently NULL, then
+ * if we are adding records, one will be allocated.  The caller must also
+ * not request that the number of records go below zero, although
+ * it can go to zero.
+ *
+ * ip -- the inode whose if_broot area is changing
+ * ext_diff -- the change in the number of records, positive or negative,
+ *	 requested for the if_broot array.
+ */
+void
+xfs_bmbt_iroot_realloc(
+	struct xfs_inode	*ip,
+	int			rec_diff,
+	int			whichfork)
+{
+	struct xfs_mount	*mp = ip->i_mount;
+	int			cur_max;
+	struct xfs_ifork	*ifp;
+	struct xfs_btree_block	*new_broot;
+	int			new_max;
+	size_t			new_size;
+	char			*np;
+	char			*op;
+
+	/*
+	 * Handle the degenerate case quietly.
+	 */
+	if (rec_diff == 0) {
+		return;
+	}
+
+	ifp = XFS_IFORK_PTR(ip, whichfork);
+	if (rec_diff > 0) {
+		/*
+		 * If there wasn't any memory allocated before, just
+		 * allocate it now and get out.
+		 */
+		if (ifp->if_broot_bytes == 0) {
+			new_size = XFS_BMAP_BROOT_SPACE_CALC(mp, rec_diff);
+			ifp->if_broot = kmem_alloc(new_size, KM_SLEEP | KM_NOFS);
+			ifp->if_broot_bytes = (int)new_size;
+			return;
+		}
+
+		/*
+		 * If there is already an existing if_broot, then we need
+		 * to realloc() it and shift the pointers to their new
+		 * location.  The records don't change location because
+		 * they are kept butted up against the btree block header.
+		 */
+		cur_max = xfs_bmbt_maxrecs(mp, ifp->if_broot_bytes, 0);
+		new_max = cur_max + rec_diff;
+		new_size = XFS_BMAP_BROOT_SPACE_CALC(mp, new_max);
+		ifp->if_broot = kmem_realloc(ifp->if_broot, new_size,
+				KM_SLEEP | KM_NOFS);
+		op = (char *)XFS_BMAP_BROOT_PTR_ADDR(mp, ifp->if_broot, 1,
+						     ifp->if_broot_bytes);
+		np = (char *)XFS_BMAP_BROOT_PTR_ADDR(mp, ifp->if_broot, 1,
+						     (int)new_size);
+		ifp->if_broot_bytes = (int)new_size;
+		ASSERT(XFS_BMAP_BMDR_SPACE(ifp->if_broot) <=
+			XFS_IFORK_SIZE(ip, whichfork));
+		memmove(np, op, cur_max * (uint)sizeof(xfs_fsblock_t));
+		return;
+	}
+
+	/*
+	 * rec_diff is less than 0.  In this case, we are shrinking the
+	 * if_broot buffer.  It must already exist.  If we go to zero
+	 * records, just get rid of the root and clear the status bit.
+	 */
+	ASSERT((ifp->if_broot != NULL) && (ifp->if_broot_bytes > 0));
+	cur_max = xfs_bmbt_maxrecs(mp, ifp->if_broot_bytes, 0);
+	new_max = cur_max + rec_diff;
+	ASSERT(new_max >= 0);
+	if (new_max > 0)
+		new_size = XFS_BMAP_BROOT_SPACE_CALC(mp, new_max);
+	else
+		new_size = 0;
+	if (new_size > 0) {
+		new_broot = kmem_alloc(new_size, KM_SLEEP | KM_NOFS);
+		/*
+		 * First copy over the btree block header.
+		 */
+		memcpy(new_broot, ifp->if_broot,
+			XFS_BMBT_BLOCK_LEN(ip->i_mount));
+	} else {
+		new_broot = NULL;
+		ifp->if_flags &= ~XFS_IFBROOT;
+	}
+
+	/*
+	 * Only copy the records and pointers if there are any.
+	 */
+	if (new_max > 0) {
+		/*
+		 * First copy the records.
+		 */
+		op = (char *)XFS_BMBT_REC_ADDR(mp, ifp->if_broot, 1);
+		np = (char *)XFS_BMBT_REC_ADDR(mp, new_broot, 1);
+		memcpy(np, op, new_max * (uint)sizeof(xfs_bmbt_rec_t));
+
+		/*
+		 * Then copy the pointers.
+		 */
+		op = (char *)XFS_BMAP_BROOT_PTR_ADDR(mp, ifp->if_broot, 1,
+						     ifp->if_broot_bytes);
+		np = (char *)XFS_BMAP_BROOT_PTR_ADDR(mp, new_broot, 1,
+						     (int)new_size);
+		memcpy(np, op, new_max * (uint)sizeof(xfs_fsblock_t));
+	}
+	kmem_free(ifp->if_broot);
+	ifp->if_broot = new_broot;
+	ifp->if_broot_bytes = (int)new_size;
+	if (ifp->if_broot)
+		ASSERT(XFS_BMAP_BMDR_SPACE(ifp->if_broot) <=
+			XFS_IFORK_SIZE(ip, whichfork));
+	return;
+}
+
+STATIC void
+__xfs_bmbt_iroot_realloc(
+	struct xfs_btree_cur	*cur,
+	int			rec_diff)
+{
+	return xfs_bmbt_iroot_realloc(cur->bc_private.b.ip, rec_diff,
+			cur->bc_private.b.whichfork);
+}
+
 static bool
 xfs_bmbt_verify(
 	struct xfs_buf		*bp)
@@ -775,6 +913,7 @@ static const struct xfs_btree_ops xfs_bmbt_ops = {
 	.key_diff		= xfs_bmbt_key_diff,
 	.diff_two_keys		= xfs_bmbt_diff_two_keys,
 	.buf_ops		= &xfs_bmbt_buf_ops,
+	.iroot_realloc		= __xfs_bmbt_iroot_realloc,
 	.keys_inorder		= xfs_bmbt_keys_inorder,
 	.recs_inorder		= xfs_bmbt_recs_inorder,
 };
diff --git a/libxfs/xfs_bmap_btree.h b/libxfs/xfs_bmap_btree.h
index 819a8a4..843e25e 100644
--- a/libxfs/xfs_bmap_btree.h
+++ b/libxfs/xfs_bmap_btree.h
@@ -140,4 +140,7 @@ extern int xfs_bmbt_change_owner(struct xfs_trans *tp, struct xfs_inode *ip,
 extern struct xfs_btree_cur *xfs_bmbt_init_cursor(struct xfs_mount *,
 		struct xfs_trans *, struct xfs_inode *, int);
 
+extern void xfs_bmbt_iroot_realloc(struct xfs_inode *ip, int rec_diff,
+		int whichfork);
+
 #endif	/* __XFS_BMAP_BTREE_H__ */
diff --git a/libxfs/xfs_btree.c b/libxfs/xfs_btree.c
index df28812..0fdbe78 100644
--- a/libxfs/xfs_btree.c
+++ b/libxfs/xfs_btree.c
@@ -2989,9 +2989,7 @@ xfs_btree_new_iroot(
 #endif
 	xfs_btree_copy_ptrs(cur, pp, &nptr, 1);
 
-	xfs_iroot_realloc(cur->bc_private.b.ip,
-			  1 - xfs_btree_get_numrecs(cblock),
-			  cur->bc_private.b.whichfork);
+	cur->bc_ops->iroot_realloc(cur, 1 - xfs_btree_get_numrecs(cblock));
 
 	xfs_btree_setbuf(cur, level, cbp);
 
@@ -3166,7 +3164,7 @@ xfs_btree_make_block_unfull(
 
 		if (numrecs < cur->bc_ops->get_dmaxrecs(cur, level)) {
 			/* A root block that can be made bigger. */
-			xfs_iroot_realloc(ip, 1, cur->bc_private.b.whichfork);
+			cur->bc_ops->iroot_realloc(cur, 1);
 			*stat = 1;
 		} else {
 			/* A root block that needs replacing */
@@ -3585,8 +3583,7 @@ xfs_btree_kill_iroot(
 
 	index = numrecs - cur->bc_ops->get_maxrecs(cur, level);
 	if (index) {
-		xfs_iroot_realloc(cur->bc_private.b.ip, index,
-				  cur->bc_private.b.whichfork);
+		cur->bc_ops->iroot_realloc(cur, index);
 		block = ifp->if_broot;
 	}
 
@@ -3800,8 +3797,7 @@ xfs_btree_delrec(
 	 */
 	if (level == cur->bc_nlevels - 1) {
 		if (cur->bc_flags & XFS_BTREE_ROOT_IN_INODE) {
-			xfs_iroot_realloc(cur->bc_private.b.ip, -1,
-					  cur->bc_private.b.whichfork);
+			cur->bc_ops->iroot_realloc(cur, -1);
 
 			error = xfs_btree_kill_iroot(cur);
 			if (error)
diff --git a/libxfs/xfs_btree.h b/libxfs/xfs_btree.h
index a7770dd..ea15b1e 100644
--- a/libxfs/xfs_btree.h
+++ b/libxfs/xfs_btree.h
@@ -195,6 +195,13 @@ struct xfs_btree_ops {
 				   union xfs_btree_key *key1,
 				   union xfs_btree_key *key2);
 
+	/*
+	 * Reallocate the space for if_broot based on the number of records
+	 * being added or deleted as indicated in rec_diff.
+	 */
+	void (*iroot_realloc)(struct xfs_btree_cur *cur,
+			      int rec_diff);
+
 	const struct xfs_buf_ops	*buf_ops;
 
 	/* check that k1 is lower than k2 */
diff --git a/libxfs/xfs_inode_fork.c b/libxfs/xfs_inode_fork.c
index e65f633..6ed0254 100644
--- a/libxfs/xfs_inode_fork.c
+++ b/libxfs/xfs_inode_fork.c
@@ -504,135 +504,6 @@ xfs_iread_extents(
 	xfs_validate_extents(ifp, nextents, XFS_EXTFMT_INODE(ip));
 	return 0;
 }
-/*
- * Reallocate the space for if_broot based on the number of records
- * being added or deleted as indicated in rec_diff.  Move the records
- * and pointers in if_broot to fit the new size.  When shrinking this
- * will eliminate holes between the records and pointers created by
- * the caller.  When growing this will create holes to be filled in
- * by the caller.
- *
- * The caller must not request to add more records than would fit in
- * the on-disk inode root.  If the if_broot is currently NULL, then
- * if we are adding records, one will be allocated.  The caller must also
- * not request that the number of records go below zero, although
- * it can go to zero.
- *
- * ip -- the inode whose if_broot area is changing
- * ext_diff -- the change in the number of records, positive or negative,
- *	 requested for the if_broot array.
- */
-void
-xfs_iroot_realloc(
-	xfs_inode_t		*ip,
-	int			rec_diff,
-	int			whichfork)
-{
-	struct xfs_mount	*mp = ip->i_mount;
-	int			cur_max;
-	xfs_ifork_t		*ifp;
-	struct xfs_btree_block	*new_broot;
-	int			new_max;
-	size_t			new_size;
-	char			*np;
-	char			*op;
-
-	/*
-	 * Handle the degenerate case quietly.
-	 */
-	if (rec_diff == 0) {
-		return;
-	}
-
-	ifp = XFS_IFORK_PTR(ip, whichfork);
-	if (rec_diff > 0) {
-		/*
-		 * If there wasn't any memory allocated before, just
-		 * allocate it now and get out.
-		 */
-		if (ifp->if_broot_bytes == 0) {
-			new_size = XFS_BMAP_BROOT_SPACE_CALC(mp, rec_diff);
-			ifp->if_broot = kmem_alloc(new_size, KM_SLEEP | KM_NOFS);
-			ifp->if_broot_bytes = (int)new_size;
-			return;
-		}
-
-		/*
-		 * If there is already an existing if_broot, then we need
-		 * to realloc() it and shift the pointers to their new
-		 * location.  The records don't change location because
-		 * they are kept butted up against the btree block header.
-		 */
-		cur_max = xfs_bmbt_maxrecs(mp, ifp->if_broot_bytes, 0);
-		new_max = cur_max + rec_diff;
-		new_size = XFS_BMAP_BROOT_SPACE_CALC(mp, new_max);
-		ifp->if_broot = kmem_realloc(ifp->if_broot, new_size,
-				KM_SLEEP | KM_NOFS);
-		op = (char *)XFS_BMAP_BROOT_PTR_ADDR(mp, ifp->if_broot, 1,
-						     ifp->if_broot_bytes);
-		np = (char *)XFS_BMAP_BROOT_PTR_ADDR(mp, ifp->if_broot, 1,
-						     (int)new_size);
-		ifp->if_broot_bytes = (int)new_size;
-		ASSERT(XFS_BMAP_BMDR_SPACE(ifp->if_broot) <=
-			XFS_IFORK_SIZE(ip, whichfork));
-		memmove(np, op, cur_max * (uint)sizeof(xfs_fsblock_t));
-		return;
-	}
-
-	/*
-	 * rec_diff is less than 0.  In this case, we are shrinking the
-	 * if_broot buffer.  It must already exist.  If we go to zero
-	 * records, just get rid of the root and clear the status bit.
-	 */
-	ASSERT((ifp->if_broot != NULL) && (ifp->if_broot_bytes > 0));
-	cur_max = xfs_bmbt_maxrecs(mp, ifp->if_broot_bytes, 0);
-	new_max = cur_max + rec_diff;
-	ASSERT(new_max >= 0);
-	if (new_max > 0)
-		new_size = XFS_BMAP_BROOT_SPACE_CALC(mp, new_max);
-	else
-		new_size = 0;
-	if (new_size > 0) {
-		new_broot = kmem_alloc(new_size, KM_SLEEP | KM_NOFS);
-		/*
-		 * First copy over the btree block header.
-		 */
-		memcpy(new_broot, ifp->if_broot,
-			XFS_BMBT_BLOCK_LEN(ip->i_mount));
-	} else {
-		new_broot = NULL;
-		ifp->if_flags &= ~XFS_IFBROOT;
-	}
-
-	/*
-	 * Only copy the records and pointers if there are any.
-	 */
-	if (new_max > 0) {
-		/*
-		 * First copy the records.
-		 */
-		op = (char *)XFS_BMBT_REC_ADDR(mp, ifp->if_broot, 1);
-		np = (char *)XFS_BMBT_REC_ADDR(mp, new_broot, 1);
-		memcpy(np, op, new_max * (uint)sizeof(xfs_bmbt_rec_t));
-
-		/*
-		 * Then copy the pointers.
-		 */
-		op = (char *)XFS_BMAP_BROOT_PTR_ADDR(mp, ifp->if_broot, 1,
-						     ifp->if_broot_bytes);
-		np = (char *)XFS_BMAP_BROOT_PTR_ADDR(mp, new_broot, 1,
-						     (int)new_size);
-		memcpy(np, op, new_max * (uint)sizeof(xfs_fsblock_t));
-	}
-	kmem_free(ifp->if_broot);
-	ifp->if_broot = new_broot;
-	ifp->if_broot_bytes = (int)new_size;
-	if (ifp->if_broot)
-		ASSERT(XFS_BMAP_BMDR_SPACE(ifp->if_broot) <=
-			XFS_IFORK_SIZE(ip, whichfork));
-	return;
-}
-
 
 /*
  * This is called when the amount of space needed for if_data
diff --git a/libxfs/xfs_inode_fork.h b/libxfs/xfs_inode_fork.h
index 44d38eb..ecdf665 100644
--- a/libxfs/xfs_inode_fork.h
+++ b/libxfs/xfs_inode_fork.h
@@ -144,7 +144,6 @@ void		xfs_iflush_fork(struct xfs_inode *, struct xfs_dinode *,
 				struct xfs_inode_log_item *, int);
 void		xfs_idestroy_fork(struct xfs_inode *, int);
 void		xfs_idata_realloc(struct xfs_inode *, int, int);
-void		xfs_iroot_realloc(struct xfs_inode *, int, int);
 int		xfs_iread_extents(struct xfs_trans *, struct xfs_inode *, int);
 int		xfs_iextents_copy(struct xfs_inode *, struct xfs_bmbt_rec *,
 				  int);

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 03/29] xfs: support storing records in the inode core root
  2016-08-25 23:58 [PATCH v8 00/29] xfsprogs: add realtime reverse-mapping support Darrick J. Wong
  2016-08-25 23:58 ` [PATCH 01/29] xfs: refactor long-format btree header verification routines Darrick J. Wong
  2016-08-25 23:58 ` [PATCH 02/29] xfs: make iroot_realloc a btree function Darrick J. Wong
@ 2016-08-25 23:58 ` Darrick J. Wong
  2016-08-25 23:59 ` [PATCH 04/29] xfs: widen xfs_refcount_irec fields to handle realtime rmapbt Darrick J. Wong
                   ` (25 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: Darrick J. Wong @ 2016-08-25 23:58 UTC (permalink / raw)
  To: david, darrick.wong; +Cc: linux-xfs, xfs

Make it so that we can actually store btree records in the inode
core (i.e. enable bb_level == 0) so that the rtrmapbt can do this.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 libxfs/xfs_btree.c |  201 +++++++++++++++++++++++++++++++++++++++-------------
 libxfs/xfs_btree.h |    1 
 2 files changed, 150 insertions(+), 52 deletions(-)


diff --git a/libxfs/xfs_btree.c b/libxfs/xfs_btree.c
index 0fdbe78..26b8e62 100644
--- a/libxfs/xfs_btree.c
+++ b/libxfs/xfs_btree.c
@@ -153,6 +153,11 @@ xfs_btree_check_block(
 	int			level,	/* level of the btree block */
 	struct xfs_buf		*bp)	/* buffer containing block, if any */
 {
+	/* Don't check the inode-core root. */
+	if ((cur->bc_flags & XFS_BTREE_ROOT_IN_INODE) &&
+	    level == cur->bc_nlevels - 1)
+		return 0;
+
 	if (cur->bc_flags & XFS_BTREE_LONG_PTRS)
 		return xfs_btree_check_lblock(cur, block, level, bp);
 	else
@@ -1416,10 +1421,15 @@ xfs_btree_log_recs(
 	XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY);
 	XFS_BTREE_TRACE_ARGBII(cur, bp, first, last);
 
-	xfs_trans_buf_set_type(cur->bc_tp, bp, XFS_BLFT_BTREE_BUF);
-	xfs_trans_log_buf(cur->bc_tp, bp,
-			  xfs_btree_rec_offset(cur, first),
-			  xfs_btree_rec_offset(cur, last + 1) - 1);
+	if (bp) {
+		xfs_trans_buf_set_type(cur->bc_tp, bp, XFS_BLFT_BTREE_BUF);
+		xfs_trans_log_buf(cur->bc_tp, bp,
+				  xfs_btree_rec_offset(cur, first),
+				  xfs_btree_rec_offset(cur, last + 1) - 1);
+	} else {
+		xfs_trans_log_inode(cur->bc_tp, cur->bc_private.b.ip,
+				xfs_ilog_fbroot(cur->bc_private.b.whichfork));
+	}
 
 	XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
 }
@@ -2917,8 +2927,11 @@ xfs_btree_new_iroot(
 	struct xfs_btree_block	*cblock;	/* child btree block */
 	union xfs_btree_key	*ckp;		/* child key pointer */
 	union xfs_btree_ptr	*cpp;		/* child ptr pointer */
+	union xfs_btree_rec	*crp;
 	union xfs_btree_key	*kp;		/* pointer to btree key */
 	union xfs_btree_ptr	*pp;		/* pointer to block addr */
+	union xfs_btree_rec	*rp;
+	union xfs_btree_ptr	aptr;
 	union xfs_btree_ptr	nptr;		/* new block addr */
 	int			level;		/* btree level */
 	int			error;		/* error return code */
@@ -2934,10 +2947,15 @@ xfs_btree_new_iroot(
 	level = cur->bc_nlevels - 1;
 
 	block = xfs_btree_get_iroot(cur);
-	pp = xfs_btree_ptr_addr(cur, 1, block);
+	ASSERT(level > 0 || (cur->bc_flags & XFS_BTREE_IROOT_RECORDS));
+	if (level > 0)
+		aptr = *xfs_btree_ptr_addr(cur, 1, block);
+	else
+		aptr.l = cpu_to_be64(XFS_INO_TO_FSB(cur->bc_mp,
+				cur->bc_private.b.ip->i_ino));
 
 	/* Allocate the new block. If we can't do it, we're toast. Give up. */
-	error = cur->bc_ops->alloc_block(cur, pp, &nptr, stat);
+	error = cur->bc_ops->alloc_block(cur, &aptr, &nptr, stat);
 	if (error)
 		goto error0;
 	if (*stat == 0) {
@@ -2963,43 +2981,93 @@ xfs_btree_new_iroot(
 			cblock->bb_u.s.bb_blkno = cpu_to_be64(cbp->b_bn);
 	}
 
-	be16_add_cpu(&block->bb_level, 1);
 	xfs_btree_set_numrecs(block, 1);
 	cur->bc_nlevels++;
 	cur->bc_ptrs[level + 1] = 1;
 
-	kp = xfs_btree_key_addr(cur, 1, block);
-	ckp = xfs_btree_key_addr(cur, 1, cblock);
-	xfs_btree_copy_keys(cur, ckp, kp, xfs_btree_get_numrecs(cblock));
+	if (level > 0) {
+		/*
+		 * We already incremented nlevels, so we have to do the
+		 * same to bb_level or else pp will be calculated with the
+		 * maxrecs for regular blocks and point at the wrong place.
+		 */
+		be16_add_cpu(&block->bb_level, 1);
+
+		kp = xfs_btree_key_addr(cur, 1, block);
+		ckp = xfs_btree_key_addr(cur, 1, cblock);
+		xfs_btree_copy_keys(cur, ckp, kp,
+				xfs_btree_get_numrecs(cblock));
 
-	cpp = xfs_btree_ptr_addr(cur, 1, cblock);
+		pp = xfs_btree_ptr_addr(cur, 1, block);
+		cpp = xfs_btree_ptr_addr(cur, 1, cblock);
 #ifdef DEBUG
-	for (i = 0; i < be16_to_cpu(cblock->bb_numrecs); i++) {
-		error = xfs_btree_check_ptr(cur, pp, i, level);
-		if (error)
-			goto error0;
-	}
+		for (i = 0; i < be16_to_cpu(cblock->bb_numrecs); i++) {
+			error = xfs_btree_check_ptr(cur, pp, i, level);
+			if (error)
+				goto error0;
+		}
 #endif
-	xfs_btree_copy_ptrs(cur, cpp, pp, xfs_btree_get_numrecs(cblock));
+		xfs_btree_copy_ptrs(cur, cpp, pp,
+				xfs_btree_get_numrecs(cblock));
 
 #ifdef DEBUG
-	error = xfs_btree_check_ptr(cur, &nptr, 0, level);
-	if (error)
-		goto error0;
+		error = xfs_btree_check_ptr(cur, &nptr, 0, level);
+		if (error)
+			goto error0;
 #endif
-	xfs_btree_copy_ptrs(cur, pp, &nptr, 1);
+		xfs_btree_copy_ptrs(cur, pp, &nptr, 1);
 
-	cur->bc_ops->iroot_realloc(cur, 1 - xfs_btree_get_numrecs(cblock));
+		cur->bc_ops->iroot_realloc(cur,
+				1 - xfs_btree_get_numrecs(cblock));
+		block = xfs_btree_get_iroot(cur);
 
-	xfs_btree_setbuf(cur, level, cbp);
+		xfs_btree_setbuf(cur, level, cbp);
 
-	/*
-	 * Do all this logging at the end so that
-	 * the root is at the right level.
-	 */
-	xfs_btree_log_block(cur, cbp, XFS_BB_ALL_BITS);
-	xfs_btree_log_keys(cur, cbp, 1, be16_to_cpu(cblock->bb_numrecs));
-	xfs_btree_log_ptrs(cur, cbp, 1, be16_to_cpu(cblock->bb_numrecs));
+		/*
+		 * Do all this logging at the end so that
+		 * the root is at the right level.
+		 */
+		xfs_btree_log_block(cur, cbp, XFS_BB_ALL_BITS);
+		xfs_btree_log_keys(cur, cbp, 1,
+				be16_to_cpu(cblock->bb_numrecs));
+		xfs_btree_log_ptrs(cur, cbp, 1,
+				be16_to_cpu(cblock->bb_numrecs));
+	} else {
+		rp = xfs_btree_rec_addr(cur, 1, block);
+		crp = xfs_btree_rec_addr(cur, 1, cblock);
+		xfs_btree_copy_recs(cur, crp, rp,
+				xfs_btree_get_numrecs(cblock));
+
+		/*
+		 * Trickery here: The number of records we think we have
+		 * changes when we convert a leaf to a node.  Therefore,
+		 * set the length to zero, increment the level, and set
+		 * the length to 1 record.
+		 */
+		cur->bc_ops->iroot_realloc(cur, -xfs_btree_get_numrecs(cblock));
+		block = xfs_btree_get_iroot(cur);
+		be16_add_cpu(&block->bb_level, 1);
+		cur->bc_ops->iroot_realloc(cur, 1);
+		block = xfs_btree_get_iroot(cur);
+
+		/* Copy pointer into the block. */
+		xfs_btree_copy_ptrs(cur, xfs_btree_ptr_addr(cur, 1, block),
+				&nptr, 1);
+
+		xfs_btree_setbuf(cur, level, cbp);
+
+		/*
+		 * Do all this logging at the end so that
+		 * the root is at the right level.
+		 */
+		xfs_btree_log_block(cur, cbp, XFS_BB_ALL_BITS);
+		xfs_btree_log_recs(cur, cbp, 1,
+				be16_to_cpu(cblock->bb_numrecs));
+
+		/* Write the new keys into the root block. */
+	}
+	/* Get the keys for the new block and put them into the root. */
+	xfs_btree_get_keys(cur, cblock, xfs_btree_key_addr(cur, 1, block));
 
 	*logflags |=
 		XFS_ILOG_CORE | xfs_ilog_fbroot(cur->bc_private.b.whichfork);
@@ -3522,15 +3590,15 @@ STATIC int
 xfs_btree_kill_iroot(
 	struct xfs_btree_cur	*cur)
 {
-	int			whichfork = cur->bc_private.b.whichfork;
 	struct xfs_inode	*ip = cur->bc_private.b.ip;
-	struct xfs_ifork	*ifp = XFS_IFORK_PTR(ip, whichfork);
 	struct xfs_btree_block	*block;
 	struct xfs_btree_block	*cblock;
 	union xfs_btree_key	*kp;
 	union xfs_btree_key	*ckp;
 	union xfs_btree_ptr	*pp;
 	union xfs_btree_ptr	*cpp;
+	union xfs_btree_rec	*rp;
+	union xfs_btree_rec	*crp;
 	struct xfs_buf		*cbp;
 	int			level;
 	int			index;
@@ -3544,14 +3612,19 @@ xfs_btree_kill_iroot(
 	XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY);
 
 	ASSERT(cur->bc_flags & XFS_BTREE_ROOT_IN_INODE);
-	ASSERT(cur->bc_nlevels > 1);
+	ASSERT((cur->bc_flags & XFS_BTREE_IROOT_RECORDS) ||
+	       cur->bc_nlevels > 1);
 
 	/*
 	 * Don't deal with the root block needs to be a leaf case.
 	 * We're just going to turn the thing back into extents anyway.
 	 */
 	level = cur->bc_nlevels - 1;
-	if (level == 1)
+	if (level == 1 && !(cur->bc_flags & XFS_BTREE_IROOT_RECORDS))
+		goto out0;
+
+	/* If we're already a leaf, jump out. */
+	if (level == 0)
 		goto out0;
 
 	/*
@@ -3582,30 +3655,55 @@ xfs_btree_kill_iroot(
 #endif
 
 	index = numrecs - cur->bc_ops->get_maxrecs(cur, level);
-	if (index) {
-		cur->bc_ops->iroot_realloc(cur, index);
-		block = ifp->if_broot;
-	}
-
 	be16_add_cpu(&block->bb_numrecs, index);
 	ASSERT(block->bb_numrecs == cblock->bb_numrecs);
 
-	kp = xfs_btree_key_addr(cur, 1, block);
-	ckp = xfs_btree_key_addr(cur, 1, cblock);
-	xfs_btree_copy_keys(cur, kp, ckp, numrecs);
+	if (be16_to_cpu(cblock->bb_level) > 0) {
+		if (index) {
+			cur->bc_ops->iroot_realloc(cur, index);
+			block = xfs_btree_get_iroot(cur);
+		}
+
+		kp = xfs_btree_key_addr(cur, 1, block);
+		ckp = xfs_btree_key_addr(cur, 1, cblock);
+		xfs_btree_copy_keys(cur, kp, ckp, numrecs);
 
-	pp = xfs_btree_ptr_addr(cur, 1, block);
-	cpp = xfs_btree_ptr_addr(cur, 1, cblock);
+		pp = xfs_btree_ptr_addr(cur, 1, block);
+		cpp = xfs_btree_ptr_addr(cur, 1, cblock);
 #ifdef DEBUG
-	for (i = 0; i < numrecs; i++) {
-		error = xfs_btree_check_ptr(cur, cpp, i, level - 1);
-		if (error) {
-			XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR);
-			return error;
+		for (i = 0; i < numrecs; i++) {
+			error = xfs_btree_check_ptr(cur, cpp, i, level - 1);
+			if (error) {
+				XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR);
+				return error;
+			}
 		}
-	}
 #endif
-	xfs_btree_copy_ptrs(cur, pp, cpp, numrecs);
+		xfs_btree_copy_ptrs(cur, pp, cpp, numrecs);
+		/*
+		 * Decrement the (root) block's level after copying the
+		 * pointers or else pp will be calculated using maxrecs
+		 * for a regular block and won't point to the right place.
+		 * Notice how we don't adjust nlevels until later.
+		 */
+		be16_add_cpu(&block->bb_level, -1);
+	} else {
+		/*
+		 * Trickery here: The number of records we think we have
+		 * changes when we convert a leaf to a node.  Therefore,
+		 * set the length to zero, change the level, and set
+		 * the length to however many records we're getting.
+		 */
+		cur->bc_ops->iroot_realloc(cur, -xfs_btree_get_numrecs(block));
+		block = xfs_btree_get_iroot(cur);
+		be16_add_cpu(&block->bb_level, -1);
+		cur->bc_ops->iroot_realloc(cur, numrecs);
+		block = xfs_btree_get_iroot(cur);
+
+		rp = xfs_btree_rec_addr(cur, 1, block);
+		crp = xfs_btree_rec_addr(cur, 1, cblock);
+		xfs_btree_copy_recs(cur, rp, crp, numrecs);
+	}
 
 	error = xfs_btree_free_block(cur, cbp);
 	if (error) {
@@ -3614,7 +3712,6 @@ xfs_btree_kill_iroot(
 	}
 
 	cur->bc_bufs[level - 1] = NULL;
-	be16_add_cpu(&block->bb_level, -1);
 	xfs_trans_log_inode(cur->bc_tp, ip,
 		XFS_ILOG_CORE | xfs_ilog_fbroot(cur->bc_private.b.whichfork));
 	cur->bc_nlevels--;
diff --git a/libxfs/xfs_btree.h b/libxfs/xfs_btree.h
index ea15b1e..8918b81 100644
--- a/libxfs/xfs_btree.h
+++ b/libxfs/xfs_btree.h
@@ -284,6 +284,7 @@ typedef struct xfs_btree_cur
 #define XFS_BTREE_LASTREC_UPDATE	(1<<2)	/* track last rec externally */
 #define XFS_BTREE_CRC_BLOCKS		(1<<3)	/* uses extended btree blocks */
 #define XFS_BTREE_OVERLAPPING		(1<<4)	/* overlapping intervals */
+#define XFS_BTREE_IROOT_RECORDS		(1<<5)	/* iroot can store records */
 
 
 #define	XFS_BTREE_NOERROR	0

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 04/29] xfs: widen xfs_refcount_irec fields to handle realtime rmapbt
  2016-08-25 23:58 [PATCH v8 00/29] xfsprogs: add realtime reverse-mapping support Darrick J. Wong
                   ` (2 preceding siblings ...)
  2016-08-25 23:58 ` [PATCH 03/29] xfs: support storing records in the inode core root Darrick J. Wong
@ 2016-08-25 23:59 ` Darrick J. Wong
  2016-08-25 23:59 ` [PATCH 05/29] xfs: introduce realtime rmap btree definitions Darrick J. Wong
                   ` (24 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: Darrick J. Wong @ 2016-08-25 23:59 UTC (permalink / raw)
  To: david, darrick.wong; +Cc: linux-xfs, xfs

Change the startblock and blockcount fields of xfs_refcount_irec to
be 64 bits wide.  This enables us to use the same high level rmap
code for either tree.  We'll also collect all the resulting breakage
fixes here.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 libxfs/xfs_format.h |    4 ++--
 libxfs/xfs_rmap.c   |   58 ++++++++++++++++++++++++++-------------------------
 libxfs/xfs_rmap.h   |   20 +++++++++---------
 repair/rmap.c       |   26 +++++++++++------------
 4 files changed, 54 insertions(+), 54 deletions(-)


diff --git a/libxfs/xfs_format.h b/libxfs/xfs_format.h
index ed36809..c336f7a 100644
--- a/libxfs/xfs_format.h
+++ b/libxfs/xfs_format.h
@@ -1436,8 +1436,8 @@ struct xfs_rmap_rec {
 					 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 */
+	xfs_fsblock_t	rm_startblock;	/* extent start block */
+	xfs_filblks_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 */
diff --git a/libxfs/xfs_rmap.c b/libxfs/xfs_rmap.c
index 62096cd..5f84f20 100644
--- a/libxfs/xfs_rmap.c
+++ b/libxfs/xfs_rmap.c
@@ -44,8 +44,8 @@
 int
 xfs_rmap_lookup_le(
 	struct xfs_btree_cur	*cur,
-	xfs_agblock_t		bno,
-	xfs_extlen_t		len,
+	xfs_fsblock_t		bno,
+	xfs_filblks_t		len,
 	uint64_t		owner,
 	uint64_t		offset,
 	unsigned int		flags,
@@ -66,8 +66,8 @@ xfs_rmap_lookup_le(
 int
 xfs_rmap_lookup_eq(
 	struct xfs_btree_cur	*cur,
-	xfs_agblock_t		bno,
-	xfs_extlen_t		len,
+	xfs_fsblock_t		bno,
+	xfs_filblks_t		len,
 	uint64_t		owner,
 	uint64_t		offset,
 	unsigned int		flags,
@@ -113,8 +113,8 @@ xfs_rmap_update(
 int
 xfs_rmap_insert(
 	struct xfs_btree_cur	*rcur,
-	xfs_agblock_t		agbno,
-	xfs_extlen_t		len,
+	xfs_fsblock_t		agbno,
+	xfs_filblks_t		len,
 	uint64_t		owner,
 	uint64_t		offset,
 	unsigned int		flags)
@@ -149,8 +149,8 @@ done:
 STATIC int
 xfs_rmap_delete(
 	struct xfs_btree_cur	*rcur,
-	xfs_agblock_t		agbno,
-	xfs_extlen_t		len,
+	xfs_fsblock_t		agbno,
+	xfs_filblks_t		len,
 	uint64_t		owner,
 	uint64_t		offset,
 	unsigned int		flags)
@@ -250,7 +250,7 @@ xfs_rmap_find_left_neighbor_helper(
 int
 xfs_rmap_find_left_neighbor(
 	struct xfs_btree_cur	*cur,
-	xfs_agblock_t		bno,
+	xfs_fsblock_t		bno,
 	uint64_t		owner,
 	uint64_t		offset,
 	unsigned int		flags,
@@ -328,7 +328,7 @@ xfs_rmap_lookup_le_range_helper(
 int
 xfs_rmap_lookup_le_range(
 	struct xfs_btree_cur	*cur,
-	xfs_agblock_t		bno,
+	xfs_fsblock_t		bno,
 	uint64_t		owner,
 	uint64_t		offset,
 	unsigned int		flags,
@@ -385,8 +385,8 @@ xfs_rmap_lookup_le_range(
 STATIC int
 xfs_rmap_unmap(
 	struct xfs_btree_cur	*cur,
-	xfs_agblock_t		bno,
-	xfs_extlen_t		len,
+	xfs_fsblock_t		bno,
+	xfs_filblks_t		len,
 	bool			unwritten,
 	struct xfs_owner_info	*oinfo)
 {
@@ -526,7 +526,7 @@ xfs_rmap_unmap(
 		 * Result:  |rrrrr|         |rrrr|
 		 *               bno       len
 		 */
-		xfs_extlen_t	orig_len = ltrec.rm_blockcount;
+		xfs_filblks_t	orig_len = ltrec.rm_blockcount;
 
 		ltrec.rm_blockcount = bno - ltrec.rm_startblock;
 		error = xfs_rmap_update(cur, &ltrec);
@@ -636,8 +636,8 @@ xfs_rmap_is_mergeable(
 STATIC int
 xfs_rmap_map(
 	struct xfs_btree_cur	*cur,
-	xfs_agblock_t		bno,
-	xfs_extlen_t		len,
+	xfs_fsblock_t		bno,
+	xfs_filblks_t		len,
 	bool			unwritten,
 	struct xfs_owner_info	*oinfo)
 {
@@ -860,8 +860,8 @@ out_error:
 STATIC int
 xfs_rmap_convert(
 	struct xfs_btree_cur	*cur,
-	xfs_agblock_t		bno,
-	xfs_extlen_t		len,
+	xfs_fsblock_t		bno,
+	xfs_filblks_t		len,
 	bool			unwritten,
 	struct xfs_owner_info	*oinfo)
 {
@@ -1285,8 +1285,8 @@ done:
 STATIC int
 xfs_rmap_convert_shared(
 	struct xfs_btree_cur	*cur,
-	xfs_agblock_t		bno,
-	xfs_extlen_t		len,
+	xfs_fsblock_t		bno,
+	xfs_filblks_t		len,
 	bool			unwritten,
 	struct xfs_owner_info	*oinfo)
 {
@@ -1672,8 +1672,8 @@ done:
 STATIC int
 xfs_rmap_unmap_shared(
 	struct xfs_btree_cur	*cur,
-	xfs_agblock_t		bno,
-	xfs_extlen_t		len,
+	xfs_fsblock_t		bno,
+	xfs_filblks_t		len,
 	bool			unwritten,
 	struct xfs_owner_info	*oinfo)
 {
@@ -1790,7 +1790,7 @@ xfs_rmap_unmap_shared(
 		 * Result:  |rrrrr|         |rrrr|
 		 *               bno       len
 		 */
-		xfs_extlen_t	orig_len = ltrec.rm_blockcount;
+		xfs_filblks_t	orig_len = ltrec.rm_blockcount;
 
 		/* Shrink the left side of the rmap */
 		error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
@@ -1834,8 +1834,8 @@ out_error:
 STATIC int
 xfs_rmap_map_shared(
 	struct xfs_btree_cur	*cur,
-	xfs_agblock_t		bno,
-	xfs_extlen_t		len,
+	xfs_fsblock_t		bno,
+	xfs_filblks_t		len,
 	bool			unwritten,
 	struct xfs_owner_info	*oinfo)
 {
@@ -2060,7 +2060,7 @@ xfs_rmap_finish_one(
 	int				error = 0;
 	xfs_agnumber_t			agno;
 	struct xfs_owner_info		oinfo;
-	xfs_agblock_t			bno;
+	xfs_fsblock_t			bno;
 	bool				unwritten;
 
 	agno = XFS_FSB_TO_AGNO(mp, startblock);
@@ -2249,8 +2249,8 @@ xfs_rmap_alloc_extent(
 	struct xfs_mount	*mp,
 	struct xfs_defer_ops	*dfops,
 	xfs_agnumber_t		agno,
-	xfs_agblock_t		bno,
-	xfs_extlen_t		len,
+	xfs_fsblock_t		bno,
+	xfs_filblks_t		len,
 	__uint64_t		owner)
 {
 	struct xfs_bmbt_irec	bmap;
@@ -2273,8 +2273,8 @@ xfs_rmap_free_extent(
 	struct xfs_mount	*mp,
 	struct xfs_defer_ops	*dfops,
 	xfs_agnumber_t		agno,
-	xfs_agblock_t		bno,
-	xfs_extlen_t		len,
+	xfs_fsblock_t		bno,
+	xfs_filblks_t		len,
 	__uint64_t		owner)
 {
 	struct xfs_bmbt_irec	bmap;
diff --git a/libxfs/xfs_rmap.h b/libxfs/xfs_rmap.h
index c5c5817..06f7e73 100644
--- a/libxfs/xfs_rmap.h
+++ b/libxfs/xfs_rmap.h
@@ -142,14 +142,14 @@ int xfs_rmap_free(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);
 
-int xfs_rmap_lookup_le(struct xfs_btree_cur *cur, xfs_agblock_t bno,
-		xfs_extlen_t len, uint64_t owner, uint64_t offset,
+int xfs_rmap_lookup_le(struct xfs_btree_cur *cur, xfs_fsblock_t bno,
+		xfs_filblks_t len, uint64_t owner, uint64_t offset,
 		unsigned int flags, int *stat);
-int xfs_rmap_lookup_eq(struct xfs_btree_cur *cur, xfs_agblock_t bno,
-		xfs_extlen_t len, uint64_t owner, uint64_t offset,
+int xfs_rmap_lookup_eq(struct xfs_btree_cur *cur, xfs_fsblock_t bno,
+		xfs_filblks_t len, uint64_t owner, uint64_t offset,
 		unsigned int flags, int *stat);
-int xfs_rmap_insert(struct xfs_btree_cur *rcur, xfs_agblock_t agbno,
-		xfs_extlen_t len, uint64_t owner, uint64_t offset,
+int xfs_rmap_insert(struct xfs_btree_cur *rcur, xfs_fsblock_t agbno,
+		xfs_filblks_t len, uint64_t owner, uint64_t offset,
 		unsigned int flags);
 int xfs_rmap_get_rec(struct xfs_btree_cur *cur, struct xfs_rmap_irec *irec,
 		int *stat);
@@ -193,10 +193,10 @@ int xfs_rmap_convert_extent(struct xfs_mount *mp, struct xfs_defer_ops *dfops,
 		struct xfs_inode *ip, int whichfork,
 		struct xfs_bmbt_irec *imap);
 int xfs_rmap_alloc_extent(struct xfs_mount *mp, struct xfs_defer_ops *dfops,
-		xfs_agnumber_t agno, xfs_agblock_t bno, xfs_extlen_t len,
+		xfs_agnumber_t agno, xfs_fsblock_t bno, xfs_filblks_t len,
 		__uint64_t owner);
 int xfs_rmap_free_extent(struct xfs_mount *mp, struct xfs_defer_ops *dfops,
-		xfs_agnumber_t agno, xfs_agblock_t bno, xfs_extlen_t len,
+		xfs_agnumber_t agno, xfs_fsblock_t bno, xfs_filblks_t len,
 		__uint64_t owner);
 
 void xfs_rmap_finish_one_cleanup(struct xfs_trans *tp,
@@ -206,10 +206,10 @@ int xfs_rmap_finish_one(struct xfs_trans *tp, enum xfs_rmap_intent_type type,
 		xfs_fsblock_t startblock, xfs_filblks_t blockcount,
 		xfs_exntst_t state, struct xfs_btree_cur **pcur);
 
-int xfs_rmap_find_left_neighbor(struct xfs_btree_cur *cur, xfs_agblock_t bno,
+int xfs_rmap_find_left_neighbor(struct xfs_btree_cur *cur, xfs_fsblock_t bno,
 		uint64_t owner, uint64_t offset, unsigned int flags,
 		struct xfs_rmap_irec *irec, int	*stat);
-int xfs_rmap_lookup_le_range(struct xfs_btree_cur *cur, xfs_agblock_t bno,
+int xfs_rmap_lookup_le_range(struct xfs_btree_cur *cur, xfs_fsblock_t bno,
 		uint64_t owner, uint64_t offset, unsigned int flags,
 		struct xfs_rmap_irec *irec, int	*stat);
 union xfs_btree_rec;
diff --git a/repair/rmap.c b/repair/rmap.c
index 597655b..3b3a195 100644
--- a/repair/rmap.c
+++ b/repair/rmap.c
@@ -1025,12 +1025,12 @@ rmaps_verify_btree(
 		}
 		if (!have) {
 			do_warn(
-_("Missing reverse-mapping record for (%u/%u) %slen %u owner %"PRId64" \
+_("Missing reverse-mapping record for (%u/%llu) %slen %llu owner %"PRId64" \
 %s%soff %"PRIu64"\n"),
-				agno, rm_rec->rm_startblock,
+				agno, (unsigned long long)rm_rec->rm_startblock,
 				(rm_rec->rm_flags & XFS_RMAP_UNWRITTEN) ?
 					_("unwritten ") : "",
-				rm_rec->rm_blockcount,
+				(unsigned long long)rm_rec->rm_blockcount,
 				rm_rec->rm_owner,
 				(rm_rec->rm_flags & XFS_RMAP_ATTR_FORK) ?
 					_("attr ") : "",
@@ -1043,22 +1043,22 @@ _("Missing reverse-mapping record for (%u/%u) %slen %u owner %"PRId64" \
 		/* Compare each refcount observation against the btree's */
 		if (!rmap_is_good(rm_rec, &tmp)) {
 			do_warn(
-_("Incorrect reverse-mapping: saw (%u/%u) %slen %u owner %"PRId64" %s%soff \
-%"PRIu64"; should be (%u/%u) %slen %u owner %"PRId64" %s%soff %"PRIu64"\n"),
-				agno, tmp.rm_startblock,
+_("Incorrect reverse-mapping: saw (%u/%llu) %slen %llu owner %"PRId64" %s%soff \
+%"PRIu64"; should be (%u/%llu) %slen %llu owner %"PRId64" %s%soff %"PRIu64"\n"),
+				agno, (unsigned long long)tmp.rm_startblock,
 				(tmp.rm_flags & XFS_RMAP_UNWRITTEN) ?
 					_("unwritten ") : "",
-				tmp.rm_blockcount,
+				(unsigned long long)tmp.rm_blockcount,
 				tmp.rm_owner,
 				(tmp.rm_flags & XFS_RMAP_ATTR_FORK) ?
 					_("attr ") : "",
 				(tmp.rm_flags & XFS_RMAP_BMBT_BLOCK) ?
 					_("bmbt ") : "",
 				tmp.rm_offset,
-				agno, rm_rec->rm_startblock,
+				agno, (unsigned long long)rm_rec->rm_startblock,
 				(rm_rec->rm_flags & XFS_RMAP_UNWRITTEN) ?
 					_("unwritten ") : "",
-				rm_rec->rm_blockcount,
+				(unsigned long long)rm_rec->rm_blockcount,
 				rm_rec->rm_owner,
 				(rm_rec->rm_flags & XFS_RMAP_ATTR_FORK) ?
 					_("attr ") : "",
@@ -1091,7 +1091,6 @@ rmap_diffkeys(
 {
 	__u64			oa;
 	__u64			ob;
-	__int64_t		d;
 	struct xfs_rmap_irec	tmp;
 
 	tmp = *kp1;
@@ -1101,9 +1100,10 @@ rmap_diffkeys(
 	tmp.rm_flags &= ~XFS_RMAP_REC_FLAGS;
 	ob = libxfs_rmap_irec_offset_pack(&tmp);
 
-	d = (__int64_t)kp1->rm_startblock - kp2->rm_startblock;
-	if (d)
-		return d;
+	if (kp1->rm_startblock > kp2->rm_startblock)
+		return 1;
+	else if (kp2->rm_startblock > kp1->rm_startblock)
+		return -1;
 
 	if (kp1->rm_owner > kp2->rm_owner)
 		return 1;

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 05/29] xfs: introduce realtime rmap btree definitions
  2016-08-25 23:58 [PATCH v8 00/29] xfsprogs: add realtime reverse-mapping support Darrick J. Wong
                   ` (3 preceding siblings ...)
  2016-08-25 23:59 ` [PATCH 04/29] xfs: widen xfs_refcount_irec fields to handle realtime rmapbt Darrick J. Wong
@ 2016-08-25 23:59 ` Darrick J. Wong
  2016-08-25 23:59 ` [PATCH 06/29] xfs: define the on-disk realtime rmap btree format Darrick J. Wong
                   ` (23 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: Darrick J. Wong @ 2016-08-25 23:59 UTC (permalink / raw)
  To: david, darrick.wong; +Cc: linux-xfs, xfs

Add new realtime rmap btree definitions. The realtime rmap btree will
be rooted from a hidden inode, but has its own shape and therefore
needs to have most of its own separate types.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 libxfs/xfs_btree.c  |    4 ++--
 libxfs/xfs_btree.h  |    3 +++
 libxfs/xfs_format.h |    7 +++++++
 libxfs/xfs_types.h  |    3 ++-
 4 files changed, 14 insertions(+), 3 deletions(-)


diff --git a/libxfs/xfs_btree.c b/libxfs/xfs_btree.c
index 26b8e62..53f6192 100644
--- a/libxfs/xfs_btree.c
+++ b/libxfs/xfs_btree.c
@@ -41,10 +41,10 @@ kmem_zone_t	*xfs_btree_cur_zone;
  */
 static const __uint32_t xfs_magics[2][XFS_BTNUM_MAX] = {
 	{ XFS_ABTB_MAGIC, XFS_ABTC_MAGIC, 0, XFS_BMAP_MAGIC, XFS_IBT_MAGIC,
-	  XFS_FIBT_MAGIC, 0 },
+	  XFS_FIBT_MAGIC, 0, 0 },
 	{ XFS_ABTB_CRC_MAGIC, XFS_ABTC_CRC_MAGIC, XFS_RMAP_CRC_MAGIC,
 	  XFS_BMAP_CRC_MAGIC, XFS_IBT_CRC_MAGIC, XFS_FIBT_CRC_MAGIC,
-	  XFS_REFC_CRC_MAGIC }
+	  XFS_REFC_CRC_MAGIC, XFS_RTRMAP_CRC_MAGIC }
 };
 #define xfs_btree_magic(cur) \
 	xfs_magics[!!((cur)->bc_flags & XFS_BTREE_CRC_BLOCKS)][cur->bc_btnum]
diff --git a/libxfs/xfs_btree.h b/libxfs/xfs_btree.h
index 8918b81..8913ffa 100644
--- a/libxfs/xfs_btree.h
+++ b/libxfs/xfs_btree.h
@@ -75,6 +75,7 @@ union xfs_btree_rec {
 #define	XFS_BTNUM_FINO	((xfs_btnum_t)XFS_BTNUM_FINOi)
 #define	XFS_BTNUM_RMAP	((xfs_btnum_t)XFS_BTNUM_RMAPi)
 #define	XFS_BTNUM_REFC	((xfs_btnum_t)XFS_BTNUM_REFCi)
+#define	XFS_BTNUM_RTRMAP	((xfs_btnum_t)XFS_BTNUM_RTRMAPi)
 
 /*
  * For logging record fields.
@@ -107,6 +108,7 @@ do {    \
 	case XFS_BTNUM_BMAP: __XFS_BTREE_STATS_INC(__mp, bmbt, stat); break; \
 	case XFS_BTNUM_INO: __XFS_BTREE_STATS_INC(__mp, ibt, stat); break; \
 	case XFS_BTNUM_FINO: __XFS_BTREE_STATS_INC(__mp, fibt, stat); break; \
+	case XFS_BTNUM_RTRMAP: /* pass-through */ \
 	case XFS_BTNUM_RMAP: __XFS_BTREE_STATS_INC(__mp, rmap, stat); break; \
 	case XFS_BTNUM_REFC: __XFS_BTREE_STATS_INC(__mp, refcbt, stat); break; \
 	case XFS_BTNUM_MAX: ASSERT(0); __mp = __mp /* fucking gcc */ ; break; \
@@ -129,6 +131,7 @@ do {    \
 		__XFS_BTREE_STATS_ADD(__mp, ibt, stat, val); break; \
 	case XFS_BTNUM_FINO:	\
 		__XFS_BTREE_STATS_ADD(__mp, fibt, stat, val); break; \
+	case XFS_BTNUM_RTRMAP: /* pass-through */	\
 	case XFS_BTNUM_RMAP:	\
 		__XFS_BTREE_STATS_ADD(__mp, rmap, stat, val); break; \
 	case XFS_BTNUM_REFC:	\
diff --git a/libxfs/xfs_format.h b/libxfs/xfs_format.h
index c336f7a..ae2d958 100644
--- a/libxfs/xfs_format.h
+++ b/libxfs/xfs_format.h
@@ -1463,6 +1463,13 @@ typedef __be32 xfs_rmap_ptr_t;
 	 XFS_IBT_BLOCK(mp) + 1)
 
 /*
+ * Realtime Reverse mapping btree format definitions
+ *
+ * There is a btree for the reverse map per allocation group
+ */
+#define	XFS_RTRMAP_CRC_MAGIC	0x4d415052	/* 'MAPR' */
+
+/*
  * Reference Count Btree format definitions
  *
  */
diff --git a/libxfs/xfs_types.h b/libxfs/xfs_types.h
index cf044c0..749aa83 100644
--- a/libxfs/xfs_types.h
+++ b/libxfs/xfs_types.h
@@ -113,7 +113,8 @@ typedef enum {
 
 typedef enum {
 	XFS_BTNUM_BNOi, XFS_BTNUM_CNTi, XFS_BTNUM_RMAPi, XFS_BTNUM_BMAPi,
-	XFS_BTNUM_INOi, XFS_BTNUM_FINOi, XFS_BTNUM_REFCi, XFS_BTNUM_MAX
+	XFS_BTNUM_INOi, XFS_BTNUM_FINOi, XFS_BTNUM_REFCi, XFS_BTNUM_RTRMAPi,
+	XFS_BTNUM_MAX
 } xfs_btnum_t;
 
 struct xfs_name {

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 06/29] xfs: define the on-disk realtime rmap btree format
  2016-08-25 23:58 [PATCH v8 00/29] xfsprogs: add realtime reverse-mapping support Darrick J. Wong
                   ` (4 preceding siblings ...)
  2016-08-25 23:59 ` [PATCH 05/29] xfs: introduce realtime rmap btree definitions Darrick J. Wong
@ 2016-08-25 23:59 ` Darrick J. Wong
  2016-08-25 23:59 ` [PATCH 07/29] xfs: realtime rmap btree transaction reservations Darrick J. Wong
                   ` (22 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: Darrick J. Wong @ 2016-08-25 23:59 UTC (permalink / raw)
  To: david, darrick.wong; +Cc: linux-xfs, xfs

Start filling out the rtrmap 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 connecting the
btree operations implementation.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 include/libxfs.h          |    1 
 include/xfs_mount.h       |    3 +
 libxfs/Makefile           |    2 
 libxfs/init.c             |    2 
 libxfs/xfs_btree.c        |    1 
 libxfs/xfs_btree.h        |    3 +
 libxfs/xfs_format.h       |   48 +++++++++++
 libxfs/xfs_rtrmap_btree.c |  195 +++++++++++++++++++++++++++++++++++++++++++++
 libxfs/xfs_rtrmap_btree.h |   62 ++++++++++++++
 libxfs/xfs_sb.c           |    6 +
 libxfs/xfs_shared.h       |    1 
 11 files changed, 324 insertions(+)
 create mode 100644 libxfs/xfs_rtrmap_btree.c
 create mode 100644 libxfs/xfs_rtrmap_btree.h


diff --git a/include/libxfs.h b/include/libxfs.h
index e5e1523..60a90dc 100644
--- a/include/libxfs.h
+++ b/include/libxfs.h
@@ -78,6 +78,7 @@ extern uint32_t crc32c_le(uint32_t crc, unsigned char const *p, size_t len);
 #include "xfs_trace.h"
 #include "xfs_trans.h"
 #include "xfs_rmap_btree.h"
+#include "xfs_rtrmap_btree.h"
 #include "xfs_rmap.h"
 #include "xfs_refcount_btree.h"
 #include "xfs_refcount.h"
diff --git a/include/xfs_mount.h b/include/xfs_mount.h
index 97b4ad7..fcc0d95 100644
--- a/include/xfs_mount.h
+++ b/include/xfs_mount.h
@@ -66,12 +66,15 @@ typedef struct xfs_mount {
 	uint			m_inobt_mnr[2];	/* XFS_INOBT_BLOCK_MINRECS */
 	uint			m_rmap_mxr[2];	/* max rmap btree records */
 	uint			m_rmap_mnr[2];	/* min rmap btree records */
+	uint			m_rtrmap_mxr[2]; /* max rtrmap btree records */
+	uint			m_rtrmap_mnr[2]; /* min rtrmap btree records */
 	uint			m_refc_mxr[2];	/* max refc btree records */
 	uint			m_refc_mnr[2];	/* min refc btree records */
 	uint			m_ag_maxlevels;	/* XFS_AG_MAXLEVELS */
 	uint			m_bm_maxlevels[2]; /* XFS_BM_MAXLEVELS */
 	uint			m_in_maxlevels;	/* XFS_IN_MAXLEVELS */
 	uint			m_rmap_maxlevels; /* max rmap btree levels */
+	uint			m_rtrmap_maxlevels; /* max rtrmap btree level */
 	uint			m_refc_maxlevels; /* max refcount btree level */
 	xfs_extlen_t		m_ag_prealloc_blocks; /* reserved ag blocks */
 	uint			m_alloc_set_aside; /* space we can't use */
diff --git a/libxfs/Makefile b/libxfs/Makefile
index 6499731..5ccf2e4 100644
--- a/libxfs/Makefile
+++ b/libxfs/Makefile
@@ -40,6 +40,7 @@ HFILES = \
 	xfs_refcount_btree.h \
 	xfs_rmap.h \
 	xfs_rmap_btree.h \
+	xfs_rtrmap_btree.h \
 	xfs_sb.h \
 	xfs_shared.h \
 	xfs_trans_resv.h \
@@ -92,6 +93,7 @@ CFILES = cache.c \
 	xfs_refcount_btree.c \
 	xfs_rmap.c \
 	xfs_rmap_btree.c \
+	xfs_rtrmap_btree.c \
 	xfs_rtbitmap.c \
 	xfs_sb.c \
 	xfs_symlink_remote.c \
diff --git a/libxfs/init.c b/libxfs/init.c
index 9134879..e3f8a5d 100644
--- a/libxfs/init.c
+++ b/libxfs/init.c
@@ -33,6 +33,7 @@
 #include "xfs_trans.h"
 #include "xfs_rmap_btree.h"
 #include "xfs_refcount_btree.h"
+#include "xfs_rtrmap_btree.h"
 
 #include "libxfs.h"		/* for now */
 
@@ -690,6 +691,7 @@ libxfs_mount(
 	xfs_bmap_compute_maxlevels(mp, XFS_ATTR_FORK);
 	xfs_ialloc_compute_maxlevels(mp);
 	xfs_rmapbt_compute_maxlevels(mp);
+	xfs_rtrmapbt_compute_maxlevels(mp);
 	xfs_refcountbt_compute_maxlevels(mp);
 
 	if (sbp->sb_imax_pct) {
diff --git a/libxfs/xfs_btree.c b/libxfs/xfs_btree.c
index 53f6192..562e42b 100644
--- a/libxfs/xfs_btree.c
+++ b/libxfs/xfs_btree.c
@@ -1216,6 +1216,7 @@ xfs_btree_set_refs(
 		xfs_buf_set_ref(bp, XFS_BMAP_BTREE_REF);
 		break;
 	case XFS_BTNUM_RMAP:
+	case XFS_BTNUM_RTRMAP:
 		xfs_buf_set_ref(bp, XFS_RMAP_BTREE_REF);
 		break;
 	case XFS_BTNUM_REFC:
diff --git a/libxfs/xfs_btree.h b/libxfs/xfs_btree.h
index 8913ffa..a9936ac 100644
--- a/libxfs/xfs_btree.h
+++ b/libxfs/xfs_btree.h
@@ -50,6 +50,8 @@ union xfs_btree_key {
 	struct xfs_rmap_key		rmap;
 	struct xfs_rmap_key		__rmap_bigkey[2];
 	struct xfs_refcount_key		refc;
+	struct xfs_rtrmap_key		rtrmap;
+	struct xfs_rtrmap_key		__rtrmap_bigkey[2];
 };
 
 union xfs_btree_rec {
@@ -59,6 +61,7 @@ union xfs_btree_rec {
 	struct xfs_inobt_rec		inobt;
 	struct xfs_rmap_rec		rmap;
 	struct xfs_refcount_rec		refc;
+	struct xfs_rtrmap_rec		rtrmap;
 };
 
 /*
diff --git a/libxfs/xfs_format.h b/libxfs/xfs_format.h
index ae2d958..82ff6fc 100644
--- a/libxfs/xfs_format.h
+++ b/libxfs/xfs_format.h
@@ -1470,6 +1470,54 @@ typedef __be32 xfs_rmap_ptr_t;
 #define	XFS_RTRMAP_CRC_MAGIC	0x4d415052	/* 'MAPR' */
 
 /*
+ * Data record structure
+ */
+struct xfs_rtrmap_rec {
+	__be64		rm_startblock;	/* extent start block */
+	__be64		rm_blockcount;	/* extent length */
+	__be64		rm_owner;	/* extent owner */
+	__be64		rm_offset;	/* offset within the owner */
+};
+
+/* rm_offset has the same values as the regular rmapbt. */
+#define XFS_RTRMAP_OFF_ATTR_FORK	XFS_RMAP_OFF_ATTR_FORK
+#define XFS_RTRMAP_OFF_BMBT_BLOCK	XFS_RMAP_OFF_BMBT_BLOCK
+#define XFS_RTRMAP_OFF_UNWRITTEN	XFS_RMAP_OFF_UNWRITTEN
+
+#define XFS_RTRMAP_LEN_MAX		((__uint64_t)~0U)
+#define XFS_RTRMAP_OFF_FLAGS		XFS_RMAP_OFF_FLAGS
+#define XFS_RTRMAP_OFF_MASK		XFS_RMAP_OFF_MASK
+
+#define XFS_RTRMAP_OFF			XFS_RMAP_OFF
+
+#define XFS_RTRMAP_IS_BMBT_BLOCK(off)	XFS_RMAP_IS_BMBT_BLOCK
+#define XFS_RTRMAP_IS_ATTR_FORK(off)	XFS_RMAP_IS_ATTR_FORK
+#define XFS_RTRMAP_IS_UNWRITTEN(len)	XFS_RMAP_IS_UNWRITTEN
+
+#define RTRMAPBT_STARTBLOCK_BITLEN	64
+#define RTRMAPBT_BLOCKCOUNT_BITLEN	64
+#define RTRMAPBT_OWNER_BITLEN		RMAPBT_OWNER_BITLEN
+#define RTRMAPBT_ATTRFLAG_BITLEN	RMAPBT_ATTRFLAG_BITLEN
+#define RTRMAPBT_BMBTFLAG_BITLEN	RMAPBT_BMBTFLAG_BITLEN
+#define RTRMAPBT_EXNTFLAG_BITLEN	RMAPBT_EXNTFLAG_BITLEN
+#define RTRMAPBT_UNUSED_OFFSET_BITLEN	RMAPBT_UNUSED_OFFSET_BITLEN
+#define RTRMAPBT_OFFSET_BITLEN		RMAPBT_OFFSET_BITLEN
+
+/*
+ * Key structure
+ *
+ * We don't use the length for lookups
+ */
+struct xfs_rtrmap_key {
+	__be64		rm_startblock;	/* extent start block */
+	__be64		rm_owner;	/* extent owner */
+	__be64		rm_offset;	/* offset within the owner */
+} __attribute__((packed));
+
+/* btree pointer type */
+typedef __be64 xfs_rtrmap_ptr_t;
+
+/*
  * Reference Count Btree format definitions
  *
  */
diff --git a/libxfs/xfs_rtrmap_btree.c b/libxfs/xfs_rtrmap_btree.c
new file mode 100644
index 0000000..c62e5c8
--- /dev/null
+++ b/libxfs/xfs_rtrmap_btree.c
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2016 Oracle.  All Rights Reserved.
+ *
+ * Author: Darrick J. Wong <darrick.wong@oracle.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it would be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write the Free Software Foundation,
+ * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+#include "libxfs_priv.h"
+#include "xfs_fs.h"
+#include "xfs_shared.h"
+#include "xfs_format.h"
+#include "xfs_log_format.h"
+#include "xfs_trans_resv.h"
+#include "xfs_bit.h"
+#include "xfs_sb.h"
+#include "xfs_mount.h"
+#include "xfs_defer.h"
+#include "xfs_inode.h"
+#include "xfs_trans.h"
+#include "xfs_alloc.h"
+#include "xfs_btree.h"
+#include "xfs_rtrmap_btree.h"
+#include "xfs_trace.h"
+#include "xfs_cksum.h"
+#include "xfs_ag_resv.h"
+
+/*
+ * Realtime Reverse map btree.
+ *
+ * This is a per-ag tree used to track the owner(s) of a given extent
+ * in the realtime device.  See the comments in xfs_rmap_btree.c for
+ * more information.
+ *
+ * This tree is basically the same as the regular rmap btree except that
+ * it doesn't live in free space, and the startblock and blockcount
+ * fields have been widened to 64 bits.
+ */
+
+static struct xfs_btree_cur *
+xfs_rtrmapbt_dup_cursor(
+	struct xfs_btree_cur	*cur)
+{
+	struct xfs_btree_cur	*new;
+
+	new = xfs_rtrmapbt_init_cursor(cur->bc_mp, cur->bc_tp,
+			cur->bc_private.b.ip);
+
+	/*
+	 * Copy the firstblock, dfops, and flags values,
+	 * since init cursor doesn't get them.
+	 */
+	new->bc_private.b.firstblock = cur->bc_private.b.firstblock;
+	new->bc_private.b.dfops = cur->bc_private.b.dfops;
+	new->bc_private.b.flags = cur->bc_private.b.flags;
+
+	return new;
+}
+
+static bool
+xfs_rtrmapbt_verify(
+	struct xfs_buf		*bp)
+{
+	struct xfs_mount	*mp = bp->b_target->bt_mount;
+	struct xfs_btree_block	*block = XFS_BUF_TO_BLOCK(bp);
+	int			level;
+
+	if (block->bb_magic != cpu_to_be32(XFS_RTRMAP_CRC_MAGIC))
+		return false;
+
+	if (!xfs_sb_version_hasrmapbt(&mp->m_sb))
+		return false;
+	if (!xfs_btree_lblock_v5hdr_verify(bp, XFS_RMAP_OWN_UNKNOWN))
+		return false;
+	level = be16_to_cpu(block->bb_level);
+	if (level > mp->m_rtrmap_maxlevels)
+		return false;
+
+	return xfs_btree_lblock_verify(bp, mp->m_rtrmap_mxr[level != 0]);
+}
+
+static void
+xfs_rtrmapbt_read_verify(
+	struct xfs_buf	*bp)
+{
+	if (!xfs_btree_lblock_verify_crc(bp))
+		xfs_buf_ioerror(bp, -EFSBADCRC);
+	else if (!xfs_rtrmapbt_verify(bp))
+		xfs_buf_ioerror(bp, -EFSCORRUPTED);
+
+	if (bp->b_error) {
+		trace_xfs_btree_corrupt(bp, _RET_IP_);
+		xfs_verifier_error(bp);
+	}
+}
+
+static void
+xfs_rtrmapbt_write_verify(
+	struct xfs_buf	*bp)
+{
+	if (!xfs_rtrmapbt_verify(bp)) {
+		trace_xfs_btree_corrupt(bp, _RET_IP_);
+		xfs_buf_ioerror(bp, -EFSCORRUPTED);
+		xfs_verifier_error(bp);
+		return;
+	}
+	xfs_btree_lblock_calc_crc(bp);
+
+}
+
+const struct xfs_buf_ops xfs_rtrmapbt_buf_ops = {
+	.name			= "xfs_rtrmapbt",
+	.verify_read		= xfs_rtrmapbt_read_verify,
+	.verify_write		= xfs_rtrmapbt_write_verify,
+};
+
+static const struct xfs_btree_ops xfs_rtrmapbt_ops = {
+	.rec_len		= sizeof(struct xfs_rtrmap_rec),
+	.key_len		= 2 * sizeof(struct xfs_rtrmap_key),
+
+	.dup_cursor		= xfs_rtrmapbt_dup_cursor,
+	.buf_ops		= &xfs_rtrmapbt_buf_ops,
+};
+
+/*
+ * Allocate a new allocation btree cursor.
+ */
+struct xfs_btree_cur *
+xfs_rtrmapbt_init_cursor(
+	struct xfs_mount	*mp,
+	struct xfs_trans	*tp,
+	struct xfs_inode	*ip)
+{
+	struct xfs_ifork	*ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK);
+	struct xfs_btree_cur	*cur;
+
+	cur = kmem_zone_zalloc(xfs_btree_cur_zone, KM_NOFS);
+	cur->bc_tp = tp;
+	cur->bc_mp = mp;
+	cur->bc_btnum = XFS_BTNUM_RTRMAP;
+	cur->bc_flags = XFS_BTREE_LONG_PTRS | XFS_BTREE_ROOT_IN_INODE |
+			XFS_BTREE_CRC_BLOCKS | XFS_BTREE_IROOT_RECORDS |
+			XFS_BTREE_OVERLAPPING;
+	cur->bc_blocklog = mp->m_sb.sb_blocklog;
+	cur->bc_ops = &xfs_rtrmapbt_ops;
+	cur->bc_nlevels = be16_to_cpu(ifp->if_broot->bb_level) + 1;
+
+	cur->bc_private.b.forksize = XFS_IFORK_SIZE(ip, XFS_DATA_FORK);
+	cur->bc_private.b.ip = ip;
+	cur->bc_private.b.firstblock = NULLFSBLOCK;
+	cur->bc_private.b.dfops = NULL;
+	cur->bc_private.b.allocated = 0;
+	cur->bc_private.b.flags = 0;
+	cur->bc_private.b.whichfork = XFS_DATA_FORK;
+
+	return cur;
+}
+
+/*
+ * Calculate number of records in an rmap btree block.
+ */
+int
+xfs_rtrmapbt_maxrecs(
+	struct xfs_mount	*mp,
+	int			blocklen,
+	bool			leaf)
+{
+	blocklen -= XFS_RTRMAP_BLOCK_LEN;
+
+	if (leaf)
+		return blocklen / sizeof(struct xfs_rtrmap_rec);
+	return blocklen /
+		(2 * sizeof(struct xfs_rtrmap_key) + sizeof(xfs_rtrmap_ptr_t));
+}
+
+/* Compute the maximum height of an rmap btree. */
+void
+xfs_rtrmapbt_compute_maxlevels(
+	struct xfs_mount		*mp)
+{
+	mp->m_rtrmap_maxlevels = xfs_btree_compute_maxlevels(mp,
+			mp->m_rtrmap_mnr, mp->m_sb.sb_rblocks);
+	ASSERT(mp->m_rtrmap_maxlevels <= XFS_BTREE_MAXLEVELS);
+}
diff --git a/libxfs/xfs_rtrmap_btree.h b/libxfs/xfs_rtrmap_btree.h
new file mode 100644
index 0000000..5eb19f4
--- /dev/null
+++ b/libxfs/xfs_rtrmap_btree.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2016 Oracle.  All Rights Reserved.
+ *
+ * Author: Darrick J. Wong <darrick.wong@oracle.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it would be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write the Free Software Foundation,
+ * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+#ifndef __XFS_RTRMAP_BTREE_H__
+#define	__XFS_RTRMAP_BTREE_H__
+
+struct xfs_buf;
+struct xfs_btree_cur;
+struct xfs_mount;
+
+/* rmaps only exist on crc enabled filesystems */
+#define XFS_RTRMAP_BLOCK_LEN	XFS_BTREE_LBLOCK_CRC_LEN
+
+/*
+ * Record, key, and pointer address macros for btree blocks.
+ *
+ * (note that some of these may appear unused, but they are used in userspace)
+ */
+#define XFS_RTRMAP_REC_ADDR(block, index) \
+	((struct xfs_rtrmap_rec *) \
+		((char *)(block) + XFS_RTRMAP_BLOCK_LEN + \
+		 (((index) - 1) * sizeof(struct xfs_rtrmap_rec))))
+
+#define XFS_RTRMAP_KEY_ADDR(block, index) \
+	((struct xfs_rtrmap_key *) \
+		((char *)(block) + XFS_RTRMAP_BLOCK_LEN + \
+		 ((index) - 1) * 2 * sizeof(struct xfs_rtrmap_key)))
+
+#define XFS_RTRMAP_HIGH_KEY_ADDR(block, index) \
+	((struct xfs_rtrmap_key *) \
+		((char *)(block) + XFS_RTRMAP_BLOCK_LEN + \
+		 sizeof(struct xfs_rtrmap_key) + \
+		 ((index) - 1) * 2 * sizeof(struct xfs_rtrmap_key)))
+
+#define XFS_RTRMAP_PTR_ADDR(block, index, maxrecs) \
+	((xfs_rtrmap_ptr_t *) \
+		((char *)(block) + XFS_RTRMAP_BLOCK_LEN + \
+		 (maxrecs) * 2 * sizeof(struct xfs_rtrmap_key) + \
+		 ((index) - 1) * sizeof(xfs_rtrmap_ptr_t)))
+
+struct xfs_btree_cur *xfs_rtrmapbt_init_cursor(struct xfs_mount *mp,
+				struct xfs_trans *tp, struct xfs_inode *ip);
+int xfs_rtrmapbt_maxrecs(struct xfs_mount *mp, int blocklen, bool leaf);
+extern void xfs_rtrmapbt_compute_maxlevels(struct xfs_mount *mp);
+
+#endif	/* __XFS_RTRMAP_BTREE_H__ */
diff --git a/libxfs/xfs_sb.c b/libxfs/xfs_sb.c
index de25489..2e6afe9 100644
--- a/libxfs/xfs_sb.c
+++ b/libxfs/xfs_sb.c
@@ -37,6 +37,7 @@
 #include "xfs_rmap_btree.h"
 #include "xfs_bmap.h"
 #include "xfs_refcount_btree.h"
+#include "xfs_rtrmap_btree.h"
 
 /*
  * Physical superblock buffer manipulations. Shared with libxfs in userspace.
@@ -742,6 +743,11 @@ xfs_sb_mount_common(
 	mp->m_rmap_mnr[0] = mp->m_rmap_mxr[0] / 2;
 	mp->m_rmap_mnr[1] = mp->m_rmap_mxr[1] / 2;
 
+	mp->m_rtrmap_mxr[0] = xfs_rtrmapbt_maxrecs(mp, sbp->sb_blocksize, 1);
+	mp->m_rtrmap_mxr[1] = xfs_rtrmapbt_maxrecs(mp, sbp->sb_blocksize, 0);
+	mp->m_rtrmap_mnr[0] = mp->m_rtrmap_mxr[0] / 2;
+	mp->m_rtrmap_mnr[1] = mp->m_rtrmap_mxr[1] / 2;
+
 	mp->m_refc_mxr[0] = xfs_refcountbt_maxrecs(mp, sbp->sb_blocksize,
 			true);
 	mp->m_refc_mxr[1] = xfs_refcountbt_maxrecs(mp, sbp->sb_blocksize,
diff --git a/libxfs/xfs_shared.h b/libxfs/xfs_shared.h
index c6f4eb4..0032a8c 100644
--- a/libxfs/xfs_shared.h
+++ b/libxfs/xfs_shared.h
@@ -39,6 +39,7 @@ extern const struct xfs_buf_ops xfs_agf_buf_ops;
 extern const struct xfs_buf_ops xfs_agfl_buf_ops;
 extern const struct xfs_buf_ops xfs_allocbt_buf_ops;
 extern const struct xfs_buf_ops xfs_rmapbt_buf_ops;
+extern const struct xfs_buf_ops xfs_rtrmapbt_buf_ops;
 extern const struct xfs_buf_ops xfs_refcountbt_buf_ops;
 extern const struct xfs_buf_ops xfs_attr3_leaf_buf_ops;
 extern const struct xfs_buf_ops xfs_attr3_rmt_buf_ops;

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 07/29] xfs: realtime rmap btree transaction reservations
  2016-08-25 23:58 [PATCH v8 00/29] xfsprogs: add realtime reverse-mapping support Darrick J. Wong
                   ` (5 preceding siblings ...)
  2016-08-25 23:59 ` [PATCH 06/29] xfs: define the on-disk realtime rmap btree format Darrick J. Wong
@ 2016-08-25 23:59 ` Darrick J. Wong
  2016-08-25 23:59 ` [PATCH 08/29] xfs: add realtime rmap btree operations Darrick J. Wong
                   ` (21 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: Darrick J. Wong @ 2016-08-25 23:59 UTC (permalink / raw)
  To: david, darrick.wong; +Cc: linux-xfs, xfs

Make sure that there's enough log reservation to handle mapping
and unmapping realtime extents.  We have to reserve enough space
to handle a split in the rtrmapbt to add the record and a second
split in the regular rmapbt to record the rtrmapbt split.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 libxfs/xfs_trans_resv.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)


diff --git a/libxfs/xfs_trans_resv.c b/libxfs/xfs_trans_resv.c
index 5152a5b..7947d8e 100644
--- a/libxfs/xfs_trans_resv.c
+++ b/libxfs/xfs_trans_resv.c
@@ -82,7 +82,8 @@ xfs_allocfree_log_count(
 
 	blocks = num_ops * 2 * (2 * mp->m_ag_maxlevels - 1);
 	if (xfs_sb_version_hasrmapbt(&mp->m_sb))
-		blocks += num_ops * (2 * mp->m_rmap_maxlevels - 1);
+		blocks += max(num_ops * (2 * mp->m_rmap_maxlevels - 1),
+			      num_ops * (2 * mp->m_rtrmap_maxlevels - 1));
 	if (xfs_sb_version_hasreflink(&mp->m_sb))
 		blocks += num_ops * (2 * mp->m_refc_maxlevels - 1);
 

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 08/29] xfs: add realtime rmap btree operations
  2016-08-25 23:58 [PATCH v8 00/29] xfsprogs: add realtime reverse-mapping support Darrick J. Wong
                   ` (6 preceding siblings ...)
  2016-08-25 23:59 ` [PATCH 07/29] xfs: realtime rmap btree transaction reservations Darrick J. Wong
@ 2016-08-25 23:59 ` Darrick J. Wong
  2016-08-25 23:59 ` [PATCH 09/29] xfs: prepare rmap functions to deal with rtrmapbt Darrick J. Wong
                   ` (20 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: Darrick J. Wong @ 2016-08-25 23:59 UTC (permalink / raw)
  To: david, darrick.wong; +Cc: linux-xfs, xfs

Implement the generic btree operations needed to manipulate rtrmap
btree blocks. This is different from the regular rmapbt in that we
allocate space from the filesystem at large, and are neither
constrained to the free space nor any particular AG.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 libxfs/xfs_rtrmap_btree.c |  319 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 319 insertions(+)


diff --git a/libxfs/xfs_rtrmap_btree.c b/libxfs/xfs_rtrmap_btree.c
index c62e5c8..66c9190 100644
--- a/libxfs/xfs_rtrmap_btree.c
+++ b/libxfs/xfs_rtrmap_btree.c
@@ -31,10 +31,12 @@
 #include "xfs_trans.h"
 #include "xfs_alloc.h"
 #include "xfs_btree.h"
+#include "xfs_rmap.h"
 #include "xfs_rtrmap_btree.h"
 #include "xfs_trace.h"
 #include "xfs_cksum.h"
 #include "xfs_ag_resv.h"
+#include "xfs_bmap.h"
 
 /*
  * Realtime Reverse map btree.
@@ -68,6 +70,275 @@ xfs_rtrmapbt_dup_cursor(
 	return new;
 }
 
+STATIC int
+xfs_rtrmapbt_alloc_block(
+	struct xfs_btree_cur	*cur,
+	union xfs_btree_ptr	*start,
+	union xfs_btree_ptr	*new,
+	int			*stat)
+{
+	struct xfs_alloc_arg	args;
+	int			error;
+
+	memset(&args, 0, sizeof(args));
+	args.tp = cur->bc_tp;
+	args.mp = cur->bc_mp;
+	args.fsbno = cur->bc_private.b.firstblock;
+	args.firstblock = args.fsbno;
+	xfs_rmap_ino_bmbt_owner(&args.oinfo, cur->bc_private.b.ip->i_ino,
+			cur->bc_private.b.whichfork);
+
+	if (args.fsbno == NULLFSBLOCK) {
+		args.fsbno = be64_to_cpu(start->l);
+		args.type = XFS_ALLOCTYPE_START_BNO;
+		/*
+		 * Make sure there is sufficient room left in the AG to
+		 * complete a full tree split for an extent insert.  If
+		 * we are converting the middle part of an extent then
+		 * we may need space for two tree splits.
+		 *
+		 * We are relying on the caller to make the correct block
+		 * reservation for this operation to succeed.  If the
+		 * reservation amount is insufficient then we may fail a
+		 * block allocation here and corrupt the filesystem.
+		 */
+		args.minleft = args.tp->t_blk_res;
+	} else if (cur->bc_private.b.dfops->dop_low) {
+		args.type = XFS_ALLOCTYPE_START_BNO;
+	} else {
+		args.type = XFS_ALLOCTYPE_NEAR_BNO;
+	}
+
+	args.minlen = args.maxlen = args.prod = 1;
+	args.wasdel = 0;
+	error = xfs_alloc_vextent(&args);
+	if (error)
+		goto error0;
+
+	if (args.fsbno == NULLFSBLOCK && args.minleft) {
+		/*
+		 * Could not find an AG with enough free space to satisfy
+		 * a full btree split.  Try again without minleft and if
+		 * successful activate the lowspace algorithm.
+		 */
+		args.fsbno = 0;
+		args.type = XFS_ALLOCTYPE_FIRST_AG;
+		args.minleft = 0;
+		error = xfs_alloc_vextent(&args);
+		if (error)
+			goto error0;
+		cur->bc_private.b.dfops->dop_low = true;
+	}
+	if (args.fsbno == NULLFSBLOCK) {
+		XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
+		*stat = 0;
+		return 0;
+	}
+	ASSERT(args.len == 1);
+	cur->bc_private.b.firstblock = args.fsbno;
+	cur->bc_private.b.allocated++;
+	cur->bc_private.b.ip->i_d.di_nblocks++;
+	xfs_trans_log_inode(args.tp, cur->bc_private.b.ip, XFS_ILOG_CORE);
+
+	new->l = cpu_to_be64(args.fsbno);
+
+	XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
+	*stat = 1;
+	return 0;
+
+ error0:
+	XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR);
+	return error;
+}
+
+STATIC int
+xfs_rtrmapbt_free_block(
+	struct xfs_btree_cur	*cur,
+	struct xfs_buf		*bp)
+{
+	struct xfs_mount	*mp = cur->bc_mp;
+	struct xfs_inode	*ip = cur->bc_private.b.ip;
+	struct xfs_trans	*tp = cur->bc_tp;
+	xfs_fsblock_t		fsbno = XFS_DADDR_TO_FSB(mp, XFS_BUF_ADDR(bp));
+	struct xfs_owner_info	oinfo;
+
+	xfs_rmap_ino_bmbt_owner(&oinfo, ip->i_ino, cur->bc_private.b.whichfork);
+	xfs_bmap_add_free(mp, cur->bc_private.b.dfops, fsbno, 1, &oinfo);
+	ip->i_d.di_nblocks--;
+
+	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
+	return 0;
+}
+
+/*
+ * Calculate number of records in the in-core realtime rmap btree inode root.
+ */
+STATIC int
+xfs_rtrmapbt_broot_maxrecs(
+	int			blocklen,
+	bool			leaf)
+{
+	blocklen -= XFS_RTRMAP_BLOCK_LEN;
+
+	if (leaf)
+		return blocklen / sizeof(struct xfs_rtrmap_rec);
+	return blocklen / (2 * sizeof(struct xfs_rtrmap_key) +
+			sizeof(xfs_rtrmap_ptr_t));
+}
+
+STATIC int
+xfs_rtrmapbt_get_minrecs(
+	struct xfs_btree_cur	*cur,
+	int			level)
+{
+	struct xfs_ifork	*ifp;
+
+	if (level == cur->bc_nlevels - 1) {
+		ifp = XFS_IFORK_PTR(cur->bc_private.b.ip,
+				    cur->bc_private.b.whichfork);
+
+		return xfs_rtrmapbt_broot_maxrecs(ifp->if_broot_bytes,
+				level == 0) / 2;
+	}
+
+	return cur->bc_mp->m_rtrmap_mnr[level != 0];
+}
+
+STATIC int
+xfs_rtrmapbt_get_maxrecs(
+	struct xfs_btree_cur	*cur,
+	int			level)
+{
+	struct xfs_ifork	*ifp;
+
+	if (level == cur->bc_nlevels - 1) {
+		ifp = XFS_IFORK_PTR(cur->bc_private.b.ip,
+				    cur->bc_private.b.whichfork);
+
+		return xfs_rtrmapbt_broot_maxrecs(ifp->if_broot_bytes,
+				level == 0);
+	}
+
+	return cur->bc_mp->m_rtrmap_mxr[level != 0];
+}
+
+STATIC void
+xfs_rtrmapbt_init_key_from_rec(
+	union xfs_btree_key	*key,
+	union xfs_btree_rec	*rec)
+{
+	key->rtrmap.rm_startblock = rec->rtrmap.rm_startblock;
+	key->rtrmap.rm_owner = rec->rtrmap.rm_owner;
+	key->rtrmap.rm_offset = rec->rtrmap.rm_offset;
+}
+
+STATIC void
+xfs_rtrmapbt_init_high_key_from_rec(
+	union xfs_btree_key	*key,
+	union xfs_btree_rec	*rec)
+{
+	__uint64_t		off;
+	int			adj;
+
+	adj = be64_to_cpu(rec->rtrmap.rm_blockcount) - 1;
+
+	key->rtrmap.rm_startblock = rec->rtrmap.rm_startblock;
+	be64_add_cpu(&key->rtrmap.rm_startblock, adj);
+	key->rtrmap.rm_owner = rec->rtrmap.rm_owner;
+	key->rtrmap.rm_offset = rec->rtrmap.rm_offset;
+	if (XFS_RMAP_NON_INODE_OWNER(be64_to_cpu(rec->rtrmap.rm_owner)) ||
+	    XFS_RMAP_IS_BMBT_BLOCK(be64_to_cpu(rec->rtrmap.rm_offset)))
+		return;
+	off = be64_to_cpu(key->rtrmap.rm_offset);
+	off = (XFS_RMAP_OFF(off) + adj) | (off & ~XFS_RMAP_OFF_MASK);
+	key->rtrmap.rm_offset = cpu_to_be64(off);
+}
+
+STATIC void
+xfs_rtrmapbt_init_rec_from_cur(
+	struct xfs_btree_cur	*cur,
+	union xfs_btree_rec	*rec)
+{
+	rec->rtrmap.rm_startblock = cpu_to_be64(cur->bc_rec.r.rm_startblock);
+	rec->rtrmap.rm_blockcount = cpu_to_be64(cur->bc_rec.r.rm_blockcount);
+	rec->rtrmap.rm_owner = cpu_to_be64(cur->bc_rec.r.rm_owner);
+	rec->rtrmap.rm_offset = cpu_to_be64(
+			xfs_rmap_irec_offset_pack(&cur->bc_rec.r));
+}
+
+STATIC void
+xfs_rtrmapbt_init_ptr_from_cur(
+	struct xfs_btree_cur	*cur,
+	union xfs_btree_ptr	*ptr)
+{
+	ptr->l = 0;
+}
+
+STATIC __int64_t
+xfs_rtrmapbt_key_diff(
+	struct xfs_btree_cur	*cur,
+	union xfs_btree_key	*key)
+{
+	struct xfs_rmap_irec	*rec = &cur->bc_rec.r;
+	struct xfs_rtrmap_key	*kp = &key->rtrmap;
+	__u64			x, y;
+
+	x = be64_to_cpu(kp->rm_startblock);
+	y = rec->rm_startblock;
+	if (x > y)
+		return 1;
+	else if (y > x)
+		return -1;
+
+	x = be64_to_cpu(kp->rm_owner);
+	y = rec->rm_owner;
+	if (x > y)
+		return 1;
+	else if (y > x)
+		return -1;
+
+	x = XFS_RMAP_OFF(be64_to_cpu(kp->rm_offset));
+	y = rec->rm_offset;
+	if (x > y)
+		return 1;
+	else if (y > x)
+		return -1;
+	return 0;
+}
+
+STATIC __int64_t
+xfs_rtrmapbt_diff_two_keys(
+	struct xfs_btree_cur	*cur,
+	union xfs_btree_key	*k1,
+	union xfs_btree_key	*k2)
+{
+	struct xfs_rtrmap_key	*kp1 = &k1->rtrmap;
+	struct xfs_rtrmap_key	*kp2 = &k2->rtrmap;
+	__u64			x, y;
+
+	x = be64_to_cpu(kp1->rm_startblock);
+	y = be64_to_cpu(kp2->rm_startblock);
+	if (x > y)
+		return 1;
+	else if (y > x)
+		return -1;
+
+	x = be64_to_cpu(kp1->rm_owner);
+	y = be64_to_cpu(kp2->rm_owner);
+	if (x > y)
+		return 1;
+	else if (y > x)
+		return -1;
+
+	x = XFS_RMAP_OFF(be64_to_cpu(kp1->rm_offset));
+	y = XFS_RMAP_OFF(be64_to_cpu(kp2->rm_offset));
+	if (x > y)
+		return 1;
+	else if (y > x)
+		return -1;
+	return 0;
+}
+
 static bool
 xfs_rtrmapbt_verify(
 	struct xfs_buf		*bp)
@@ -125,12 +396,60 @@ const struct xfs_buf_ops xfs_rtrmapbt_buf_ops = {
 	.verify_write		= xfs_rtrmapbt_write_verify,
 };
 
+STATIC int
+xfs_rtrmapbt_keys_inorder(
+	struct xfs_btree_cur	*cur,
+	union xfs_btree_key	*k1,
+	union xfs_btree_key	*k2)
+{
+	if (be64_to_cpu(k1->rtrmap.rm_startblock) <
+	    be64_to_cpu(k2->rtrmap.rm_startblock))
+		return 1;
+	if (be64_to_cpu(k1->rtrmap.rm_owner) <
+	    be64_to_cpu(k2->rtrmap.rm_owner))
+		return 1;
+	if (XFS_RMAP_OFF(be64_to_cpu(k1->rtrmap.rm_offset)) <=
+	    XFS_RMAP_OFF(be64_to_cpu(k2->rtrmap.rm_offset)))
+		return 1;
+	return 0;
+}
+
+STATIC int
+xfs_rtrmapbt_recs_inorder(
+	struct xfs_btree_cur	*cur,
+	union xfs_btree_rec	*r1,
+	union xfs_btree_rec	*r2)
+{
+	if (be64_to_cpu(r1->rtrmap.rm_startblock) <
+	    be64_to_cpu(r2->rtrmap.rm_startblock))
+		return 1;
+	if (XFS_RMAP_OFF(be64_to_cpu(r1->rtrmap.rm_offset)) <
+	    XFS_RMAP_OFF(be64_to_cpu(r2->rtrmap.rm_offset)))
+		return 1;
+	if (be64_to_cpu(r1->rtrmap.rm_owner) <=
+	    be64_to_cpu(r2->rtrmap.rm_owner))
+		return 1;
+	return 0;
+}
+
 static const struct xfs_btree_ops xfs_rtrmapbt_ops = {
 	.rec_len		= sizeof(struct xfs_rtrmap_rec),
 	.key_len		= 2 * sizeof(struct xfs_rtrmap_key),
 
 	.dup_cursor		= xfs_rtrmapbt_dup_cursor,
+	.alloc_block		= xfs_rtrmapbt_alloc_block,
+	.free_block		= xfs_rtrmapbt_free_block,
+	.get_minrecs		= xfs_rtrmapbt_get_minrecs,
+	.get_maxrecs		= xfs_rtrmapbt_get_maxrecs,
+	.init_key_from_rec	= xfs_rtrmapbt_init_key_from_rec,
+	.init_high_key_from_rec	= xfs_rtrmapbt_init_high_key_from_rec,
+	.init_rec_from_cur	= xfs_rtrmapbt_init_rec_from_cur,
+	.init_ptr_from_cur	= xfs_rtrmapbt_init_ptr_from_cur,
+	.key_diff		= xfs_rtrmapbt_key_diff,
 	.buf_ops		= &xfs_rtrmapbt_buf_ops,
+	.diff_two_keys		= xfs_rtrmapbt_diff_two_keys,
+	.keys_inorder		= xfs_rtrmapbt_keys_inorder,
+	.recs_inorder		= xfs_rtrmapbt_recs_inorder,
 };
 
 /*

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 09/29] xfs: prepare rmap functions to deal with rtrmapbt
  2016-08-25 23:58 [PATCH v8 00/29] xfsprogs: add realtime reverse-mapping support Darrick J. Wong
                   ` (7 preceding siblings ...)
  2016-08-25 23:59 ` [PATCH 08/29] xfs: add realtime rmap btree operations Darrick J. Wong
@ 2016-08-25 23:59 ` Darrick J. Wong
  2016-08-25 23:59 ` [PATCH 10/29] xfs: add a realtime flag to the rmap update log redo items Darrick J. Wong
                   ` (19 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: Darrick J. Wong @ 2016-08-25 23:59 UTC (permalink / raw)
  To: david, darrick.wong; +Cc: linux-xfs, xfs

Prepare the high-level rmap functions to deal with the new realtime
rmapbt and its slightly different conventions.  Provide the ability
to talk to either rmapbt or rtrmapbt formats from the same high
level code.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 libxfs/xfs_rmap.c |  178 ++++++++++++++++++++++++++++++++---------------------
 libxfs/xfs_rmap.h |    2 -
 2 files changed, 107 insertions(+), 73 deletions(-)


diff --git a/libxfs/xfs_rmap.c b/libxfs/xfs_rmap.c
index 5f84f20..d5057b3 100644
--- a/libxfs/xfs_rmap.c
+++ b/libxfs/xfs_rmap.c
@@ -37,6 +37,24 @@
 #include "xfs_bmap.h"
 #include "xfs_inode.h"
 
+/* By convention, the rtrmapbt's "AG" number is NULLAGNUMBER. */
+static xfs_agnumber_t
+xfs_rmap_cur_agno(
+	struct xfs_btree_cur	*cur)
+{
+	return (cur->bc_flags & XFS_BTREE_LONG_PTRS) ?
+			NULLAGNUMBER : cur->bc_private.a.agno;
+}
+
+/* Return the maximum length of an rmap record. */
+static xfs_filblks_t
+xfs_rmap_len_max(
+	struct xfs_btree_cur	*cur)
+{
+	return (cur->bc_flags & XFS_BTREE_LONG_PTRS) ?
+			XFS_RTRMAP_LEN_MAX : XFS_RMAP_LEN_MAX;
+}
+
 /*
  * Lookup the first record less than or equal to [bno, len, owner, offset]
  * in the btree given by cur.
@@ -94,19 +112,27 @@ xfs_rmap_update(
 	union xfs_btree_rec	rec;
 	int			error;
 
-	trace_xfs_rmap_update(cur->bc_mp, cur->bc_private.a.agno,
+	trace_xfs_rmap_update(cur->bc_mp, xfs_rmap_cur_agno(cur),
 			irec->rm_startblock, irec->rm_blockcount,
 			irec->rm_owner, irec->rm_offset, irec->rm_flags);
 
-	rec.rmap.rm_startblock = cpu_to_be32(irec->rm_startblock);
-	rec.rmap.rm_blockcount = cpu_to_be32(irec->rm_blockcount);
-	rec.rmap.rm_owner = cpu_to_be64(irec->rm_owner);
-	rec.rmap.rm_offset = cpu_to_be64(
-			xfs_rmap_irec_offset_pack(irec));
+	if (cur->bc_flags & XFS_BTREE_LONG_PTRS) {
+		rec.rtrmap.rm_startblock = cpu_to_be64(irec->rm_startblock);
+		rec.rtrmap.rm_blockcount = cpu_to_be64(irec->rm_blockcount);
+		rec.rtrmap.rm_owner = cpu_to_be64(irec->rm_owner);
+		rec.rtrmap.rm_offset = cpu_to_be64(
+				xfs_rmap_irec_offset_pack(irec));
+	} else {
+		rec.rmap.rm_startblock = cpu_to_be32(irec->rm_startblock);
+		rec.rmap.rm_blockcount = cpu_to_be32(irec->rm_blockcount);
+		rec.rmap.rm_owner = cpu_to_be64(irec->rm_owner);
+		rec.rmap.rm_offset = cpu_to_be64(
+				xfs_rmap_irec_offset_pack(irec));
+	}
 	error = xfs_btree_update(cur, &rec);
 	if (error)
 		trace_xfs_rmap_update_error(cur->bc_mp,
-				cur->bc_private.a.agno, error, _RET_IP_);
+				xfs_rmap_cur_agno(cur), error, _RET_IP_);
 	return error;
 }
 
@@ -122,7 +148,7 @@ xfs_rmap_insert(
 	int			i;
 	int			error;
 
-	trace_xfs_rmap_insert(rcur->bc_mp, rcur->bc_private.a.agno, agbno,
+	trace_xfs_rmap_insert(rcur->bc_mp, xfs_rmap_cur_agno(rcur), agbno,
 			len, owner, offset, flags);
 
 	error = xfs_rmap_lookup_eq(rcur, agbno, len, owner, offset, flags, &i);
@@ -142,7 +168,7 @@ xfs_rmap_insert(
 done:
 	if (error)
 		trace_xfs_rmap_insert_error(rcur->bc_mp,
-				rcur->bc_private.a.agno, error, _RET_IP_);
+				xfs_rmap_cur_agno(rcur), error, _RET_IP_);
 	return error;
 }
 
@@ -158,7 +184,7 @@ xfs_rmap_delete(
 	int			i;
 	int			error;
 
-	trace_xfs_rmap_delete(rcur->bc_mp, rcur->bc_private.a.agno, agbno,
+	trace_xfs_rmap_delete(rcur->bc_mp, xfs_rmap_cur_agno(rcur), agbno,
 			len, owner, offset, flags);
 
 	error = xfs_rmap_lookup_eq(rcur, agbno, len, owner, offset, flags, &i);
@@ -173,22 +199,31 @@ xfs_rmap_delete(
 done:
 	if (error)
 		trace_xfs_rmap_delete_error(rcur->bc_mp,
-				rcur->bc_private.a.agno, error, _RET_IP_);
+				xfs_rmap_cur_agno(rcur), error, _RET_IP_);
 	return error;
 }
 
 /* Convert an internal btree record to an rmap record. */
 int
 xfs_rmap_btrec_to_irec(
+	struct xfs_btree_cur	*cur,
 	union xfs_btree_rec	*rec,
 	struct xfs_rmap_irec	*irec)
 {
 	irec->rm_flags = 0;
-	irec->rm_startblock = be32_to_cpu(rec->rmap.rm_startblock);
-	irec->rm_blockcount = be32_to_cpu(rec->rmap.rm_blockcount);
-	irec->rm_owner = be64_to_cpu(rec->rmap.rm_owner);
-	return xfs_rmap_irec_offset_unpack(be64_to_cpu(rec->rmap.rm_offset),
-			irec);
+	if (cur->bc_flags & XFS_BTREE_LONG_PTRS) {
+		irec->rm_startblock = be64_to_cpu(rec->rtrmap.rm_startblock);
+		irec->rm_blockcount = be64_to_cpu(rec->rtrmap.rm_blockcount);
+		irec->rm_owner = be64_to_cpu(rec->rtrmap.rm_owner);
+		return xfs_rmap_irec_offset_unpack(
+				be64_to_cpu(rec->rtrmap.rm_offset), irec);
+	} else {
+		irec->rm_startblock = be32_to_cpu(rec->rmap.rm_startblock);
+		irec->rm_blockcount = be32_to_cpu(rec->rmap.rm_blockcount);
+		irec->rm_owner = be64_to_cpu(rec->rmap.rm_owner);
+		return xfs_rmap_irec_offset_unpack(
+				be64_to_cpu(rec->rmap.rm_offset), irec);
+	}
 }
 
 /*
@@ -207,7 +242,7 @@ xfs_rmap_get_rec(
 	if (error || !*stat)
 		return error;
 
-	return xfs_rmap_btrec_to_irec(rec, irec);
+	return xfs_rmap_btrec_to_irec(cur, rec, irec);
 }
 
 struct xfs_find_left_neighbor_info {
@@ -226,7 +261,7 @@ xfs_rmap_find_left_neighbor_helper(
 	struct xfs_find_left_neighbor_info	*info = priv;
 
 	trace_xfs_rmap_find_left_neighbor_candidate(cur->bc_mp,
-			cur->bc_private.a.agno, rec->rm_startblock,
+			xfs_rmap_cur_agno(cur), rec->rm_startblock,
 			rec->rm_blockcount, rec->rm_owner, rec->rm_offset,
 			rec->rm_flags);
 
@@ -278,7 +313,7 @@ xfs_rmap_find_left_neighbor(
 	info.stat = stat;
 
 	trace_xfs_rmap_find_left_neighbor_query(cur->bc_mp,
-			cur->bc_private.a.agno, bno, 0, owner, offset, flags);
+			xfs_rmap_cur_agno(cur), bno, 0, owner, offset, flags);
 
 	error = xfs_rmap_query_range(cur, &info.high, &info.high,
 			xfs_rmap_find_left_neighbor_helper, &info);
@@ -286,7 +321,7 @@ xfs_rmap_find_left_neighbor(
 		error = 0;
 	if (*stat)
 		trace_xfs_rmap_find_left_neighbor_result(cur->bc_mp,
-				cur->bc_private.a.agno, irec->rm_startblock,
+				xfs_rmap_cur_agno(cur), irec->rm_startblock,
 				irec->rm_blockcount, irec->rm_owner,
 				irec->rm_offset, irec->rm_flags);
 	return error;
@@ -302,7 +337,7 @@ xfs_rmap_lookup_le_range_helper(
 	struct xfs_find_left_neighbor_info	*info = priv;
 
 	trace_xfs_rmap_lookup_le_range_candidate(cur->bc_mp,
-			cur->bc_private.a.agno, rec->rm_startblock,
+			xfs_rmap_cur_agno(cur), rec->rm_startblock,
 			rec->rm_blockcount, rec->rm_owner, rec->rm_offset,
 			rec->rm_flags);
 
@@ -351,14 +386,14 @@ xfs_rmap_lookup_le_range(
 	info.stat = stat;
 
 	trace_xfs_rmap_lookup_le_range(cur->bc_mp,
-			cur->bc_private.a.agno, bno, 0, owner, offset, flags);
+			xfs_rmap_cur_agno(cur), bno, 0, owner, offset, flags);
 	error = xfs_rmap_query_range(cur, &info.high, &info.high,
 			xfs_rmap_lookup_le_range_helper, &info);
 	if (error == XFS_BTREE_QUERY_RANGE_ABORT)
 		error = 0;
 	if (*stat)
 		trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
-				cur->bc_private.a.agno, irec->rm_startblock,
+				xfs_rmap_cur_agno(cur), irec->rm_startblock,
 				irec->rm_blockcount, irec->rm_owner,
 				irec->rm_offset, irec->rm_flags);
 	return error;
@@ -405,7 +440,7 @@ xfs_rmap_unmap(
 			(flags & XFS_RMAP_BMBT_BLOCK);
 	if (unwritten)
 		flags |= XFS_RMAP_UNWRITTEN;
-	trace_xfs_rmap_unmap(mp, cur->bc_private.a.agno, bno, len,
+	trace_xfs_rmap_unmap(mp, xfs_rmap_cur_agno(cur), bno, len,
 			unwritten, oinfo);
 
 	/*
@@ -423,7 +458,7 @@ xfs_rmap_unmap(
 		goto out_error;
 	XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
 	trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
-			cur->bc_private.a.agno, ltrec.rm_startblock,
+			xfs_rmap_cur_agno(cur), ltrec.rm_startblock,
 			ltrec.rm_blockcount, ltrec.rm_owner,
 			ltrec.rm_offset, ltrec.rm_flags);
 	ltoff = ltrec.rm_offset;
@@ -471,7 +506,7 @@ xfs_rmap_unmap(
 
 	if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) {
 		/* exact match, simply remove the record from rmap tree */
-		trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
+		trace_xfs_rmap_delete(mp, xfs_rmap_cur_agno(cur),
 				ltrec.rm_startblock, ltrec.rm_blockcount,
 				ltrec.rm_owner, ltrec.rm_offset,
 				ltrec.rm_flags);
@@ -546,7 +581,7 @@ xfs_rmap_unmap(
 		else
 			cur->bc_rec.r.rm_offset = offset + len;
 		cur->bc_rec.r.rm_flags = flags;
-		trace_xfs_rmap_insert(mp, cur->bc_private.a.agno,
+		trace_xfs_rmap_insert(mp, xfs_rmap_cur_agno(cur),
 				cur->bc_rec.r.rm_startblock,
 				cur->bc_rec.r.rm_blockcount,
 				cur->bc_rec.r.rm_owner,
@@ -558,11 +593,11 @@ xfs_rmap_unmap(
 	}
 
 out_done:
-	trace_xfs_rmap_unmap_done(mp, cur->bc_private.a.agno, bno, len,
+	trace_xfs_rmap_unmap_done(mp, xfs_rmap_cur_agno(cur), bno, len,
 			unwritten, oinfo);
 out_error:
 	if (error)
-		trace_xfs_rmap_unmap_error(mp, cur->bc_private.a.agno,
+		trace_xfs_rmap_unmap_error(mp, xfs_rmap_cur_agno(cur),
 				error, _RET_IP_);
 	return error;
 }
@@ -659,7 +694,7 @@ xfs_rmap_map(
 			(flags & XFS_RMAP_BMBT_BLOCK);
 	if (unwritten)
 		flags |= XFS_RMAP_UNWRITTEN;
-	trace_xfs_rmap_map(mp, cur->bc_private.a.agno, bno, len,
+	trace_xfs_rmap_map(mp, xfs_rmap_cur_agno(cur), bno, len,
 			unwritten, oinfo);
 
 	/*
@@ -678,7 +713,7 @@ xfs_rmap_map(
 		goto out_error;
 	XFS_WANT_CORRUPTED_GOTO(mp, have_lt == 1, out_error);
 	trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
-			cur->bc_private.a.agno, ltrec.rm_startblock,
+			xfs_rmap_cur_agno(cur), ltrec.rm_startblock,
 			ltrec.rm_blockcount, ltrec.rm_owner,
 			ltrec.rm_offset, ltrec.rm_flags);
 
@@ -705,7 +740,7 @@ xfs_rmap_map(
 		XFS_WANT_CORRUPTED_GOTO(mp, bno + len <= gtrec.rm_startblock,
 					out_error);
 		trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
-			cur->bc_private.a.agno, gtrec.rm_startblock,
+			xfs_rmap_cur_agno(cur), gtrec.rm_startblock,
 			gtrec.rm_blockcount, gtrec.rm_owner,
 			gtrec.rm_offset, gtrec.rm_flags);
 		if (!xfs_rmap_is_mergeable(&gtrec, owner, flags))
@@ -732,8 +767,8 @@ xfs_rmap_map(
 		if (have_gt &&
 		    bno + len == gtrec.rm_startblock &&
 		    (ignore_off || offset + len == gtrec.rm_offset) &&
-		    (unsigned long)ltrec.rm_blockcount + len +
-				gtrec.rm_blockcount <= XFS_RMAP_LEN_MAX) {
+		    ltrec.rm_blockcount + len + gtrec.rm_blockcount <=
+		    xfs_rmap_len_max(cur)) {
 			/*
 			 * right edge also contiguous, delete right record
 			 * and merge into left record.
@@ -744,7 +779,7 @@ xfs_rmap_map(
 			 * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
 			 */
 			ltrec.rm_blockcount += gtrec.rm_blockcount;
-			trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
+			trace_xfs_rmap_delete(mp, xfs_rmap_cur_agno(cur),
 					gtrec.rm_startblock,
 					gtrec.rm_blockcount,
 					gtrec.rm_owner,
@@ -792,7 +827,7 @@ xfs_rmap_map(
 		cur->bc_rec.r.rm_owner = owner;
 		cur->bc_rec.r.rm_offset = offset;
 		cur->bc_rec.r.rm_flags = flags;
-		trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno, len,
+		trace_xfs_rmap_insert(mp, xfs_rmap_cur_agno(cur), bno, len,
 			owner, offset, flags);
 		error = xfs_btree_insert(cur, &i);
 		if (error)
@@ -800,11 +835,11 @@ xfs_rmap_map(
 		XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
 	}
 
-	trace_xfs_rmap_map_done(mp, cur->bc_private.a.agno, bno, len,
+	trace_xfs_rmap_map_done(mp, xfs_rmap_cur_agno(cur), bno, len,
 			unwritten, oinfo);
 out_error:
 	if (error)
-		trace_xfs_rmap_map_error(mp, cur->bc_private.a.agno,
+		trace_xfs_rmap_map_error(mp, xfs_rmap_cur_agno(cur),
 				error, _RET_IP_);
 	return error;
 }
@@ -884,7 +919,7 @@ xfs_rmap_convert(
 			(flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK))));
 	oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0;
 	new_endoff = offset + len;
-	trace_xfs_rmap_convert(mp, cur->bc_private.a.agno, bno, len,
+	trace_xfs_rmap_convert(mp, xfs_rmap_cur_agno(cur), bno, len,
 			unwritten, oinfo);
 
 	/*
@@ -902,7 +937,7 @@ xfs_rmap_convert(
 		goto done;
 	XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
 	trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
-			cur->bc_private.a.agno, PREV.rm_startblock,
+			xfs_rmap_cur_agno(cur), PREV.rm_startblock,
 			PREV.rm_blockcount, PREV.rm_owner,
 			PREV.rm_offset, PREV.rm_flags);
 
@@ -938,7 +973,7 @@ xfs_rmap_convert(
 				LEFT.rm_startblock + LEFT.rm_blockcount <= bno,
 				done);
 		trace_xfs_rmap_find_left_neighbor_result(cur->bc_mp,
-				cur->bc_private.a.agno, LEFT.rm_startblock,
+				xfs_rmap_cur_agno(cur), LEFT.rm_startblock,
 				LEFT.rm_blockcount, LEFT.rm_owner,
 				LEFT.rm_offset, LEFT.rm_flags);
 		if (LEFT.rm_startblock + LEFT.rm_blockcount == bno &&
@@ -968,7 +1003,7 @@ xfs_rmap_convert(
 		XFS_WANT_CORRUPTED_GOTO(mp, bno + len <= RIGHT.rm_startblock,
 					done);
 		trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
-				cur->bc_private.a.agno, RIGHT.rm_startblock,
+				xfs_rmap_cur_agno(cur), RIGHT.rm_startblock,
 				RIGHT.rm_blockcount, RIGHT.rm_owner,
 				RIGHT.rm_offset, RIGHT.rm_flags);
 		if (bno + len == RIGHT.rm_startblock &&
@@ -982,11 +1017,11 @@ xfs_rmap_convert(
 			 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) ==
 	    (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
 	     RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) &&
-	    (unsigned long)LEFT.rm_blockcount + len +
-	     RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX)
+	    LEFT.rm_blockcount + len + RIGHT.rm_blockcount >
+	    xfs_rmap_len_max(cur))
 		state &= ~RMAP_RIGHT_CONTIG;
 
-	trace_xfs_rmap_convert_state(mp, cur->bc_private.a.agno, state,
+	trace_xfs_rmap_convert_state(mp, xfs_rmap_cur_agno(cur), state,
 			_RET_IP_);
 
 	/* reset the cursor back to PREV */
@@ -1010,7 +1045,7 @@ xfs_rmap_convert(
 		if (error)
 			goto done;
 		XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
-		trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
+		trace_xfs_rmap_delete(mp, xfs_rmap_cur_agno(cur),
 				RIGHT.rm_startblock, RIGHT.rm_blockcount,
 				RIGHT.rm_owner, RIGHT.rm_offset,
 				RIGHT.rm_flags);
@@ -1022,7 +1057,7 @@ xfs_rmap_convert(
 		if (error)
 			goto done;
 		XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
-		trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
+		trace_xfs_rmap_delete(mp, xfs_rmap_cur_agno(cur),
 				PREV.rm_startblock, PREV.rm_blockcount,
 				PREV.rm_owner, PREV.rm_offset,
 				PREV.rm_flags);
@@ -1046,7 +1081,7 @@ xfs_rmap_convert(
 		 * Setting all of a previous oldext extent to newext.
 		 * The left neighbor is contiguous, the right is not.
 		 */
-		trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
+		trace_xfs_rmap_delete(mp, xfs_rmap_cur_agno(cur),
 				PREV.rm_startblock, PREV.rm_blockcount,
 				PREV.rm_owner, PREV.rm_offset,
 				PREV.rm_flags);
@@ -1074,7 +1109,7 @@ xfs_rmap_convert(
 		if (error)
 			goto done;
 		XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
-		trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
+		trace_xfs_rmap_delete(mp, xfs_rmap_cur_agno(cur),
 				RIGHT.rm_startblock, RIGHT.rm_blockcount,
 				RIGHT.rm_owner, RIGHT.rm_offset,
 				RIGHT.rm_flags);
@@ -1147,7 +1182,7 @@ xfs_rmap_convert(
 		NEW.rm_blockcount = len;
 		NEW.rm_flags = newext;
 		cur->bc_rec.r = NEW;
-		trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno,
+		trace_xfs_rmap_insert(mp, xfs_rmap_cur_agno(cur), bno,
 				len, owner, offset, newext);
 		error = xfs_btree_insert(cur, &i);
 		if (error)
@@ -1198,7 +1233,7 @@ xfs_rmap_convert(
 		NEW.rm_blockcount = len;
 		NEW.rm_flags = newext;
 		cur->bc_rec.r = NEW;
-		trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno,
+		trace_xfs_rmap_insert(mp, xfs_rmap_cur_agno(cur), bno,
 				len, owner, offset, newext);
 		error = xfs_btree_insert(cur, &i);
 		if (error)
@@ -1226,7 +1261,7 @@ xfs_rmap_convert(
 		NEW = PREV;
 		NEW.rm_blockcount = offset - PREV.rm_offset;
 		cur->bc_rec.r = NEW;
-		trace_xfs_rmap_insert(mp, cur->bc_private.a.agno,
+		trace_xfs_rmap_insert(mp, xfs_rmap_cur_agno(cur),
 				NEW.rm_startblock, NEW.rm_blockcount,
 				NEW.rm_owner, NEW.rm_offset,
 				NEW.rm_flags);
@@ -1247,7 +1282,7 @@ xfs_rmap_convert(
 		/* new middle extent - newext */
 		cur->bc_rec.r.rm_flags &= ~XFS_RMAP_UNWRITTEN;
 		cur->bc_rec.r.rm_flags |= newext;
-		trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno, len,
+		trace_xfs_rmap_insert(mp, xfs_rmap_cur_agno(cur), bno, len,
 				owner, offset, newext);
 		error = xfs_btree_insert(cur, &i);
 		if (error)
@@ -1268,12 +1303,12 @@ xfs_rmap_convert(
 		ASSERT(0);
 	}
 
-	trace_xfs_rmap_convert_done(mp, cur->bc_private.a.agno, bno, len,
+	trace_xfs_rmap_convert_done(mp, xfs_rmap_cur_agno(cur), bno, len,
 			unwritten, oinfo);
 done:
 	if (error)
 		trace_xfs_rmap_convert_error(cur->bc_mp,
-				cur->bc_private.a.agno, error, _RET_IP_);
+				xfs_rmap_cur_agno(cur), error, _RET_IP_);
 	return error;
 }
 
@@ -1309,7 +1344,7 @@ xfs_rmap_convert_shared(
 			(flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK))));
 	oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0;
 	new_endoff = offset + len;
-	trace_xfs_rmap_convert(mp, cur->bc_private.a.agno, bno, len,
+	trace_xfs_rmap_convert(mp, xfs_rmap_cur_agno(cur), bno, len,
 			unwritten, oinfo);
 
 	/*
@@ -1363,7 +1398,7 @@ xfs_rmap_convert_shared(
 		XFS_WANT_CORRUPTED_GOTO(mp, bno + len <= RIGHT.rm_startblock,
 				done);
 		trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
-				cur->bc_private.a.agno, RIGHT.rm_startblock,
+				xfs_rmap_cur_agno(cur), RIGHT.rm_startblock,
 				RIGHT.rm_blockcount, RIGHT.rm_owner,
 				RIGHT.rm_offset, RIGHT.rm_flags);
 		if (xfs_rmap_is_mergeable(&RIGHT, owner, newext))
@@ -1375,11 +1410,11 @@ xfs_rmap_convert_shared(
 			 RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) ==
 	    (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
 	     RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) &&
-	    (unsigned long)LEFT.rm_blockcount + len +
-	     RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX)
+	    LEFT.rm_blockcount + len + RIGHT.rm_blockcount >
+	    xfs_rmap_len_max(cur))
 		state &= ~RMAP_RIGHT_CONTIG;
 
-	trace_xfs_rmap_convert_state(mp, cur->bc_private.a.agno, state,
+	trace_xfs_rmap_convert_state(mp, xfs_rmap_cur_agno(cur), state,
 			_RET_IP_);
 	/*
 	 * Switch out based on the FILLING and CONTIG state bits.
@@ -1646,12 +1681,12 @@ xfs_rmap_convert_shared(
 		ASSERT(0);
 	}
 
-	trace_xfs_rmap_convert_done(mp, cur->bc_private.a.agno, bno, len,
+	trace_xfs_rmap_convert_done(mp, xfs_rmap_cur_agno(cur), bno, len,
 			unwritten, oinfo);
 done:
 	if (error)
 		trace_xfs_rmap_convert_error(cur->bc_mp,
-				cur->bc_private.a.agno, error, _RET_IP_);
+				xfs_rmap_cur_agno(cur), error, _RET_IP_);
 	return error;
 }
 
@@ -1689,7 +1724,7 @@ xfs_rmap_unmap_shared(
 	xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
 	if (unwritten)
 		flags |= XFS_RMAP_UNWRITTEN;
-	trace_xfs_rmap_unmap(mp, cur->bc_private.a.agno, bno, len,
+	trace_xfs_rmap_unmap(mp, xfs_rmap_cur_agno(cur), bno, len,
 			unwritten, oinfo);
 
 	/*
@@ -1813,12 +1848,12 @@ xfs_rmap_unmap_shared(
 			goto out_error;
 	}
 
-	trace_xfs_rmap_unmap_done(mp, cur->bc_private.a.agno, bno, len,
+	trace_xfs_rmap_unmap_done(mp, xfs_rmap_cur_agno(cur), bno, len,
 			unwritten, oinfo);
 out_error:
 	if (error)
 		trace_xfs_rmap_unmap_error(cur->bc_mp,
-				cur->bc_private.a.agno, error, _RET_IP_);
+				xfs_rmap_cur_agno(cur), error, _RET_IP_);
 	return error;
 }
 
@@ -1853,7 +1888,7 @@ xfs_rmap_map_shared(
 	xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
 	if (unwritten)
 		flags |= XFS_RMAP_UNWRITTEN;
-	trace_xfs_rmap_map(mp, cur->bc_private.a.agno, bno, len,
+	trace_xfs_rmap_map(mp, xfs_rmap_cur_agno(cur), bno, len,
 			unwritten, oinfo);
 
 	/* Is there a left record that abuts our range? */
@@ -1876,7 +1911,7 @@ xfs_rmap_map_shared(
 			goto out_error;
 		XFS_WANT_CORRUPTED_GOTO(mp, have_gt == 1, out_error);
 		trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
-			cur->bc_private.a.agno, gtrec.rm_startblock,
+			xfs_rmap_cur_agno(cur), gtrec.rm_startblock,
 			gtrec.rm_blockcount, gtrec.rm_owner,
 			gtrec.rm_offset, gtrec.rm_flags);
 
@@ -1966,12 +2001,12 @@ xfs_rmap_map_shared(
 			goto out_error;
 	}
 
-	trace_xfs_rmap_map_done(mp, cur->bc_private.a.agno, bno, len,
+	trace_xfs_rmap_map_done(mp, xfs_rmap_cur_agno(cur), bno, len,
 			unwritten, oinfo);
 out_error:
 	if (error)
 		trace_xfs_rmap_map_error(cur->bc_mp,
-				cur->bc_private.a.agno, error, _RET_IP_);
+				xfs_rmap_cur_agno(cur), error, _RET_IP_);
 	return error;
 }
 
@@ -1991,7 +2026,7 @@ xfs_rmap_query_range_helper(
 	struct xfs_rmap_irec			irec;
 	int					error;
 
-	error = xfs_rmap_btrec_to_irec(rec, &irec);
+	error = xfs_rmap_btrec_to_irec(cur, rec, &irec);
 	if (error)
 		return error;
 	return query->fn(cur, &irec, query->priv);
@@ -2074,13 +2109,12 @@ xfs_rmap_finish_one(
 			XFS_ERRTAG_RMAP_FINISH_ONE,
 			XFS_RANDOM_RMAP_FINISH_ONE))
 		return -EIO;
-
 	/*
 	 * If we haven't gotten a cursor or the cursor AG doesn't match
 	 * the startblock, get one now.
 	 */
 	rcur = *pcur;
-	if (rcur != NULL && rcur->bc_private.a.agno != agno) {
+	if (rcur != NULL && xfs_rmap_cur_agno(rcur) != agno) {
 		xfs_rmap_finish_one_cleanup(tp, rcur, 0);
 		rcur = NULL;
 		*pcur = NULL;
diff --git a/libxfs/xfs_rmap.h b/libxfs/xfs_rmap.h
index 06f7e73..3574377 100644
--- a/libxfs/xfs_rmap.h
+++ b/libxfs/xfs_rmap.h
@@ -213,7 +213,7 @@ int xfs_rmap_lookup_le_range(struct xfs_btree_cur *cur, xfs_fsblock_t bno,
 		uint64_t owner, uint64_t offset, unsigned int flags,
 		struct xfs_rmap_irec *irec, int	*stat);
 union xfs_btree_rec;
-int xfs_rmap_btrec_to_irec(union xfs_btree_rec *rec,
+int xfs_rmap_btrec_to_irec(struct xfs_btree_cur *cur, union xfs_btree_rec *rec,
 		struct xfs_rmap_irec *irec);
 int xfs_rmap_has_record(struct xfs_btree_cur *cur, xfs_fsblock_t bno,
 		xfs_filblks_t len, bool *exists);

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 10/29] xfs: add a realtime flag to the rmap update log redo items
  2016-08-25 23:58 [PATCH v8 00/29] xfsprogs: add realtime reverse-mapping support Darrick J. Wong
                   ` (8 preceding siblings ...)
  2016-08-25 23:59 ` [PATCH 09/29] xfs: prepare rmap functions to deal with rtrmapbt Darrick J. Wong
@ 2016-08-25 23:59 ` Darrick J. Wong
  2016-08-25 23:59 ` [PATCH 11/29] xfs: add realtime reverse map inode to superblock Darrick J. Wong
                   ` (18 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: Darrick J. Wong @ 2016-08-25 23:59 UTC (permalink / raw)
  To: david, darrick.wong; +Cc: linux-xfs, xfs

Extend the rmap update (RUI) log items with a new realtime flag that
indicates that the updates apply against the realtime rmapbt.  We'll
wire up the actual rmap code later.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 libxfs/xfs_log_format.h |    4 +++-
 libxfs/xfs_rmap.c       |   17 ++++++++++-------
 libxfs/xfs_rmap.h       |    1 +
 3 files changed, 14 insertions(+), 8 deletions(-)


diff --git a/libxfs/xfs_log_format.h b/libxfs/xfs_log_format.h
index 75f9890..34c4cc7 100644
--- a/libxfs/xfs_log_format.h
+++ b/libxfs/xfs_log_format.h
@@ -647,11 +647,13 @@ struct xfs_map_extent {
 #define XFS_RMAP_EXTENT_ATTR_FORK	(1U << 31)
 #define XFS_RMAP_EXTENT_BMBT_BLOCK	(1U << 30)
 #define XFS_RMAP_EXTENT_UNWRITTEN	(1U << 29)
+#define XFS_RMAP_EXTENT_REALTIME	(1U << 28)
 
 #define XFS_RMAP_EXTENT_FLAGS		(XFS_RMAP_EXTENT_TYPE_MASK | \
 					 XFS_RMAP_EXTENT_ATTR_FORK | \
 					 XFS_RMAP_EXTENT_BMBT_BLOCK | \
-					 XFS_RMAP_EXTENT_UNWRITTEN)
+					 XFS_RMAP_EXTENT_UNWRITTEN | \
+					 XFS_RMAP_EXTENT_REALTIME)
 
 /*
  * This is the structure used to lay out an rui log item in the
diff --git a/libxfs/xfs_rmap.c b/libxfs/xfs_rmap.c
index d5057b3..dc1e3a7 100644
--- a/libxfs/xfs_rmap.c
+++ b/libxfs/xfs_rmap.c
@@ -2203,11 +2203,13 @@ __xfs_rmap_add(
 	enum xfs_rmap_intent_type	type,
 	__uint64_t			owner,
 	int				whichfork,
-	struct xfs_bmbt_irec		*bmap)
+	struct xfs_bmbt_irec		*bmap,
+	bool				realtime)
 {
 	struct xfs_rmap_intent	*ri;
 
-	trace_xfs_rmap_defer(mp, XFS_FSB_TO_AGNO(mp, bmap->br_startblock),
+	trace_xfs_rmap_defer(mp, realtime ? NULLAGNUMBER :
+			XFS_FSB_TO_AGNO(mp, bmap->br_startblock),
 			type,
 			XFS_FSB_TO_AGBNO(mp, bmap->br_startblock),
 			owner, whichfork,
@@ -2221,6 +2223,7 @@ __xfs_rmap_add(
 	ri->ri_owner = owner;
 	ri->ri_whichfork = whichfork;
 	ri->ri_bmap = *bmap;
+	ri->ri_realtime = realtime;
 
 	xfs_defer_add(dfops, XFS_DEFER_OPS_TYPE_RMAP, &ri->ri_list);
 	return 0;
@@ -2240,7 +2243,7 @@ xfs_rmap_map_extent(
 
 	return __xfs_rmap_add(mp, dfops, xfs_is_reflink_inode(ip) ?
 			XFS_RMAP_MAP_SHARED : XFS_RMAP_MAP, ip->i_ino,
-			whichfork, PREV);
+			whichfork, PREV, XFS_IS_REALTIME_INODE(ip));
 }
 
 /* Unmap an extent out of a file. */
@@ -2257,7 +2260,7 @@ xfs_rmap_unmap_extent(
 
 	return __xfs_rmap_add(mp, dfops, xfs_is_reflink_inode(ip) ?
 			XFS_RMAP_UNMAP_SHARED : XFS_RMAP_UNMAP, ip->i_ino,
-			whichfork, PREV);
+			whichfork, PREV, XFS_IS_REALTIME_INODE(ip));
 }
 
 /* Convert a data fork extent from unwritten to real or vice versa. */
@@ -2274,7 +2277,7 @@ xfs_rmap_convert_extent(
 
 	return __xfs_rmap_add(mp, dfops, xfs_is_reflink_inode(ip) ?
 			XFS_RMAP_CONVERT_SHARED : XFS_RMAP_CONVERT, ip->i_ino,
-			whichfork, PREV);
+			whichfork, PREV, XFS_IS_REALTIME_INODE(ip));
 }
 
 /* Schedule the creation of an rmap for non-file data. */
@@ -2298,7 +2301,7 @@ xfs_rmap_alloc_extent(
 	bmap.br_state = XFS_EXT_NORM;
 
 	return __xfs_rmap_add(mp, dfops, XFS_RMAP_ALLOC, owner,
-			XFS_DATA_FORK, &bmap);
+			XFS_DATA_FORK, &bmap, false);
 }
 
 /* Schedule the deletion of an rmap for non-file data. */
@@ -2322,7 +2325,7 @@ xfs_rmap_free_extent(
 	bmap.br_state = XFS_EXT_NORM;
 
 	return __xfs_rmap_add(mp, dfops, XFS_RMAP_FREE, owner,
-			XFS_DATA_FORK, &bmap);
+			XFS_DATA_FORK, &bmap, false);
 }
 
 /* Is there a record covering a given extent? */
diff --git a/libxfs/xfs_rmap.h b/libxfs/xfs_rmap.h
index 3574377..0850310 100644
--- a/libxfs/xfs_rmap.h
+++ b/libxfs/xfs_rmap.h
@@ -180,6 +180,7 @@ struct xfs_rmap_intent {
 	__uint64_t				ri_owner;
 	int					ri_whichfork;
 	struct xfs_bmbt_irec			ri_bmap;
+	bool					ri_realtime;
 };
 
 /* functions for updating the rmapbt based on bmbt map/unmap operations */

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 11/29] xfs: add realtime reverse map inode to superblock
  2016-08-25 23:58 [PATCH v8 00/29] xfsprogs: add realtime reverse-mapping support Darrick J. Wong
                   ` (9 preceding siblings ...)
  2016-08-25 23:59 ` [PATCH 10/29] xfs: add a realtime flag to the rmap update log redo items Darrick J. Wong
@ 2016-08-25 23:59 ` Darrick J. Wong
  2016-08-25 23:59 ` [PATCH 12/29] xfs: wire up a new inode fork type for the realtime rmap Darrick J. Wong
                   ` (17 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: Darrick J. Wong @ 2016-08-25 23:59 UTC (permalink / raw)
  To: david, darrick.wong; +Cc: linux-xfs, xfs

Add a field to the superblock to record the rt rmap inode and load
it at mount time.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 include/xfs_mount.h       |    1 +
 libxfs/init.c             |    6 ++++--
 libxfs/xfs_format.h       |   10 +++++++++-
 libxfs/xfs_inode_fork.c   |   11 +++++++++++
 libxfs/xfs_rtrmap_btree.c |    2 +-
 libxfs/xfs_sb.c           |    2 ++
 6 files changed, 28 insertions(+), 4 deletions(-)


diff --git a/include/xfs_mount.h b/include/xfs_mount.h
index fcc0d95..8e9c9f0 100644
--- a/include/xfs_mount.h
+++ b/include/xfs_mount.h
@@ -42,6 +42,7 @@ typedef struct xfs_mount {
 	uint			m_rsumsize;	/* size of rt summary, bytes */
 	struct xfs_inode	*m_rbmip;	/* pointer to bitmap inode */
 	struct xfs_inode	*m_rsumip;	/* pointer to summary inode */
+	struct xfs_inode	*m_rrmapip;	/* realtime rmap inode */
 	struct xfs_buftarg	*m_ddev_targp;
 	struct xfs_buftarg	*m_logdev_targp;
 	struct xfs_buftarg	*m_rtdev_targp;
diff --git a/libxfs/init.c b/libxfs/init.c
index e3f8a5d..3217ec7 100644
--- a/libxfs/init.c
+++ b/libxfs/init.c
@@ -458,7 +458,7 @@ rtmount_init(
 		(uint)sizeof(xfs_suminfo_t) * mp->m_rsumlevels *
 		sbp->sb_rbmblocks;
 	mp->m_rsumsize = roundup(mp->m_rsumsize, sbp->sb_blocksize);
-	mp->m_rbmip = mp->m_rsumip = NULL;
+	mp->m_rbmip = mp->m_rsumip = mp->m_rrmapip = NULL;
 
 	/*
 	 * Allow debugger to be run without the realtime device present.
@@ -830,11 +830,13 @@ libxfs_mount(
 void
 libxfs_rtmount_destroy(xfs_mount_t *mp)
 {
+	if (mp->m_rrmapip)
+		IRELE(mp->m_rrmapip);
 	if (mp->m_rsumip)
 		IRELE(mp->m_rsumip);
 	if (mp->m_rbmip)
 		IRELE(mp->m_rbmip);
-	mp->m_rsumip = mp->m_rbmip = NULL;
+	mp->m_rsumip = mp->m_rbmip = mp->m_rrmapip = NULL;
 }
 
 /*
diff --git a/libxfs/xfs_format.h b/libxfs/xfs_format.h
index 82ff6fc..5fb5e52 100644
--- a/libxfs/xfs_format.h
+++ b/libxfs/xfs_format.h
@@ -183,6 +183,7 @@ typedef struct xfs_sb {
 	xfs_ino_t	sb_pquotino;	/* project quota inode */
 	xfs_lsn_t	sb_lsn;		/* last write sequence */
 	uuid_t		sb_meta_uuid;	/* metadata file system unique id */
+	xfs_ino_t	sb_rrmapino;	/* realtime reverse map inode */
 
 	/* must be padded to 64 bit alignment */
 } xfs_sb_t;
@@ -270,6 +271,7 @@ typedef struct xfs_dsb {
 	__be64		sb_pquotino;	/* project quota inode */
 	__be64		sb_lsn;		/* last write sequence */
 	uuid_t		sb_meta_uuid;	/* metadata file system unique id */
+	__be64		sb_rrmapino;	/* realtime reverse map inode */
 
 	/* must be padded to 64 bit alignment */
 } xfs_dsb_t;
@@ -553,6 +555,11 @@ static inline bool xfs_sb_version_hasrmapbt(struct xfs_sb *sbp)
 		(sbp->sb_features_ro_compat & XFS_SB_FEAT_RO_COMPAT_RMAPBT);
 }
 
+static inline bool xfs_sb_version_hasrtrmapbt(struct xfs_sb *sbp)
+{
+	return sbp->sb_rblocks > 0 && xfs_sb_version_hasrmapbt(sbp);
+}
+
 static inline bool xfs_sb_version_hasreflink(struct xfs_sb *sbp)
 {
 	return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5) &&
@@ -948,7 +955,8 @@ typedef 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		/* uuid_t */
+	XFS_DINODE_FMT_UUID,		/* uuid_t */
+	XFS_DINODE_FMT_RMAP,		/* reverse mapping btree */
 } xfs_dinode_fmt_t;
 
 /*
diff --git a/libxfs/xfs_inode_fork.c b/libxfs/xfs_inode_fork.c
index 6ed0254..b006e2f 100644
--- a/libxfs/xfs_inode_fork.c
+++ b/libxfs/xfs_inode_fork.c
@@ -191,6 +191,13 @@ xfs_iformat_fork(
 		case XFS_DINODE_FMT_BTREE:
 			error = xfs_iformat_btree(ip, dip, XFS_DATA_FORK);
 			break;
+		case XFS_DINODE_FMT_RMAP:
+			if (!xfs_sb_version_hasrtrmapbt(&ip->i_mount->m_sb))
+				return -EFSCORRUPTED;
+			if (ip->i_ino != ip->i_mount->m_sb.sb_rrmapino)
+				return -EFSCORRUPTED;
+			/* to be implemented later */
+			break;
 		default:
 			XFS_ERROR_REPORT("xfs_iformat(6)", XFS_ERRLEVEL_LOW,
 					 ip->i_mount);
@@ -793,6 +800,10 @@ xfs_iflush_fork(
 		}
 		break;
 
+	case XFS_DINODE_FMT_RMAP:
+		/* to be implemented later */
+		break;
+
 	default:
 		ASSERT(0);
 		break;
diff --git a/libxfs/xfs_rtrmap_btree.c b/libxfs/xfs_rtrmap_btree.c
index 66c9190..e4dbe88 100644
--- a/libxfs/xfs_rtrmap_btree.c
+++ b/libxfs/xfs_rtrmap_btree.c
@@ -352,7 +352,7 @@ xfs_rtrmapbt_verify(
 
 	if (!xfs_sb_version_hasrmapbt(&mp->m_sb))
 		return false;
-	if (!xfs_btree_lblock_v5hdr_verify(bp, XFS_RMAP_OWN_UNKNOWN))
+	if (!xfs_btree_lblock_v5hdr_verify(bp, mp->m_sb.sb_rrmapino))
 		return false;
 	level = be16_to_cpu(block->bb_level);
 	if (level > mp->m_rtrmap_maxlevels)
diff --git a/libxfs/xfs_sb.c b/libxfs/xfs_sb.c
index 2e6afe9..14ec707 100644
--- a/libxfs/xfs_sb.c
+++ b/libxfs/xfs_sb.c
@@ -426,6 +426,7 @@ __xfs_sb_from_disk(
 		uuid_copy(&to->sb_meta_uuid, &from->sb_meta_uuid);
 	else
 		uuid_copy(&to->sb_meta_uuid, &from->sb_uuid);
+	to->sb_rrmapino = be64_to_cpu(from->sb_rrmapino);
 	/* Convert on-disk flags to in-memory flags? */
 	if (convert_xquota)
 		xfs_sb_quota_from_disk(to);
@@ -569,6 +570,7 @@ xfs_sb_to_disk(
 		to->sb_lsn = cpu_to_be64(from->sb_lsn);
 		if (xfs_sb_version_hasmetauuid(from))
 			uuid_copy(&to->sb_meta_uuid, &from->sb_meta_uuid);
+		to->sb_rrmapino = cpu_to_be64(from->sb_rrmapino);
 	}
 }
 

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 12/29] xfs: wire up a new inode fork type for the realtime rmap
  2016-08-25 23:58 [PATCH v8 00/29] xfsprogs: add realtime reverse-mapping support Darrick J. Wong
                   ` (10 preceding siblings ...)
  2016-08-25 23:59 ` [PATCH 11/29] xfs: add realtime reverse map inode to superblock Darrick J. Wong
@ 2016-08-25 23:59 ` Darrick J. Wong
  2016-08-25 23:59 ` [PATCH 13/29] xfs: don't assume a left rmap when allocating a new rmap Darrick J. Wong
                   ` (16 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: Darrick J. Wong @ 2016-08-25 23:59 UTC (permalink / raw)
  To: david, darrick.wong; +Cc: linux-xfs, xfs

Plumb in the pieces we need to embed the root of the realtime rmap
btree in an inode's data fork, complete with new fork type and
on-disk interpretation functions.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 libxfs/xfs_format.h       |    8 +
 libxfs/xfs_inode_fork.c   |   48 ++++++++-
 libxfs/xfs_rtrmap_btree.c |  250 +++++++++++++++++++++++++++++++++++++++++++++
 libxfs/xfs_rtrmap_btree.h |   49 +++++++++
 4 files changed, 353 insertions(+), 2 deletions(-)


diff --git a/libxfs/xfs_format.h b/libxfs/xfs_format.h
index 5fb5e52..b3f595e 100644
--- a/libxfs/xfs_format.h
+++ b/libxfs/xfs_format.h
@@ -1478,6 +1478,14 @@ typedef __be32 xfs_rmap_ptr_t;
 #define	XFS_RTRMAP_CRC_MAGIC	0x4d415052	/* 'MAPR' */
 
 /*
+ * rtrmap root header, on-disk form only.
+ */
+struct xfs_rtrmap_root {
+	__be16		bb_level;	/* 0 is a leaf */
+	__be16		bb_numrecs;	/* current # of data records */
+};
+
+/*
  * Data record structure
  */
 struct xfs_rtrmap_rec {
diff --git a/libxfs/xfs_inode_fork.c b/libxfs/xfs_inode_fork.c
index b006e2f..b0dea20 100644
--- a/libxfs/xfs_inode_fork.c
+++ b/libxfs/xfs_inode_fork.c
@@ -28,12 +28,14 @@
 #include "xfs_trace.h"
 #include "xfs_attr_sf.h"
 #include "xfs_da_format.h"
+#include "xfs_rtrmap_btree.h"
 
 kmem_zone_t *xfs_ifork_zone;
 
 STATIC int xfs_iformat_local(xfs_inode_t *, xfs_dinode_t *, int, int);
 STATIC int xfs_iformat_extents(xfs_inode_t *, xfs_dinode_t *, int);
 STATIC int xfs_iformat_btree(xfs_inode_t *, xfs_dinode_t *, int);
+STATIC int xfs_iformat_rmap(struct xfs_inode *, struct xfs_dinode *);
 
 #ifdef DEBUG
 /*
@@ -196,7 +198,7 @@ xfs_iformat_fork(
 				return -EFSCORRUPTED;
 			if (ip->i_ino != ip->i_mount->m_sb.sb_rrmapino)
 				return -EFSCORRUPTED;
-			/* to be implemented later */
+			error = xfs_iformat_rmap(ip, dip);
 			break;
 		default:
 			XFS_ERROR_REPORT("xfs_iformat(6)", XFS_ERRLEVEL_LOW,
@@ -472,6 +474,37 @@ xfs_iformat_btree(
 	return 0;
 }
 
+/* The file is a reverse mapping tree. */
+STATIC int
+xfs_iformat_rmap(
+	struct xfs_inode	*ip,
+	struct xfs_dinode	*dip)
+{
+	struct xfs_rtrmap_root	*dfp;
+	struct xfs_ifork	*ifp;
+	/* REFERENCED */
+	int			size;
+	int			whichfork = XFS_DATA_FORK;
+
+	ifp = XFS_IFORK_PTR(ip, whichfork);
+	dfp = (struct xfs_rtrmap_root *)XFS_DFORK_PTR(dip, whichfork);
+	size = XFS_RTRMAP_BROOT_SPACE(dfp);
+
+	ifp->if_broot_bytes = size;
+	ifp->if_broot = kmem_alloc(size, KM_SLEEP | KM_NOFS);
+	ASSERT(ifp->if_broot != NULL);
+	/*
+	 * Copy and convert from the on-disk structure
+	 * to the in-memory structure.
+	 */
+	xfs_rtrmapbt_from_disk(ip, dfp,
+			XFS_DFORK_SIZE(dip, ip->i_mount, whichfork),
+			ifp->if_broot, size);
+	ifp->if_flags = XFS_IFBROOT;
+
+	return 0;
+}
+
 /*
  * Read in extents from a btree-format inode.
  * Allocate and fill in if_extents.  Real work is done in xfs_bmap.c.
@@ -801,7 +834,18 @@ xfs_iflush_fork(
 		break;
 
 	case XFS_DINODE_FMT_RMAP:
-		/* to be implemented later */
+		ASSERT(whichfork == XFS_DATA_FORK);
+		ASSERT(ip->i_ino == mp->m_sb.sb_rrmapino);
+		if ((iip->ili_fields & brootflag[whichfork]) &&
+		    (ifp->if_broot_bytes > 0)) {
+			ASSERT(ifp->if_broot != NULL);
+			ASSERT(XFS_RTRMAP_ROOT_SPACE(ifp->if_broot) <=
+			        XFS_IFORK_SIZE(ip, whichfork));
+			xfs_rtrmapbt_to_disk(mp, ifp->if_broot,
+				ifp->if_broot_bytes,
+				(struct xfs_rtrmap_root *)cp,
+				XFS_DFORK_SIZE(dip, mp, whichfork));
+		}
 		break;
 
 	default:
diff --git a/libxfs/xfs_rtrmap_btree.c b/libxfs/xfs_rtrmap_btree.c
index e4dbe88..503e64e 100644
--- a/libxfs/xfs_rtrmap_btree.c
+++ b/libxfs/xfs_rtrmap_btree.c
@@ -222,6 +222,42 @@ xfs_rtrmapbt_get_maxrecs(
 	return cur->bc_mp->m_rtrmap_mxr[level != 0];
 }
 
+/*
+ * Calculate number of records in a realtime rmap btree inode root.
+ */
+STATIC int
+xfs_rtrmapbt_root_maxrecs(
+	int			blocklen,
+	bool			leaf)
+{
+	blocklen -= sizeof(struct xfs_rtrmap_root);
+
+	if (leaf)
+		return blocklen / sizeof(struct xfs_rtrmap_rec);
+	return blocklen / (2 * sizeof(struct xfs_rtrmap_key) +
+			sizeof(xfs_rtrmap_ptr_t));
+}
+
+/*
+ * Get the maximum records we could store in the on-disk format.
+ *
+ * For non-root nodes this is equivalent to xfs_bmbt_get_maxrecs, but
+ * for the root node this checks the available space in the dinode fork
+ * so that we can resize the in-memory buffer to match it.  After a
+ * resize to the maximum size this function returns the same value
+ * as xfs_bmbt_get_maxrecs for the root node, too.
+ */
+STATIC int
+xfs_rtrmapbt_get_dmaxrecs(
+	struct xfs_btree_cur	*cur,
+	int			level)
+{
+	if (level != cur->bc_nlevels - 1)
+		return cur->bc_mp->m_rtrmap_mxr[level != 0];
+	return xfs_rtrmapbt_root_maxrecs(cur->bc_private.b.forksize,
+			level == 0);
+}
+
 STATIC void
 xfs_rtrmapbt_init_key_from_rec(
 	union xfs_btree_key	*key,
@@ -339,6 +375,129 @@ xfs_rtrmapbt_diff_two_keys(
 	return 0;
 }
 
+/*
+ * Reallocate the space for if_broot based on the number of records
+ * being added or deleted as indicated in rec_diff.  Move the records
+ * and pointers in if_broot to fit the new size.  When shrinking this
+ * will eliminate holes between the records and pointers created by
+ * the caller.  When growing this will create holes to be filled in
+ * by the caller.
+ *
+ * The caller must not request to add more records than would fit in
+ * the on-disk inode root.  If the if_broot is currently NULL, then
+ * if we are adding records, one will be allocated.  The caller must also
+ * not request that the number of records go below zero, although
+ * it can go to zero.
+ */
+STATIC void
+xfs_rtrmapbt_iroot_realloc(
+	struct xfs_btree_cur	*cur,
+	int			rec_diff)
+{
+	struct xfs_inode	*ip = cur->bc_private.b.ip;
+	int			whichfork = cur->bc_private.b.whichfork;
+	struct xfs_mount	*mp = ip->i_mount;
+	int			cur_max;
+	struct xfs_ifork	*ifp;
+	struct xfs_btree_block	*new_broot;
+	struct xfs_btree_block	*broot;
+	int			new_max;
+	size_t			new_size;
+	char			*np;
+	char			*op;
+	int			level;
+
+	/*
+	 * Handle the degenerate case quietly.
+	 */
+	if (rec_diff == 0) {
+		return;
+	}
+
+	ifp = XFS_IFORK_PTR(ip, whichfork);
+	if (rec_diff > 0) {
+		/*
+		 * If there wasn't any memory allocated before, just
+		 * allocate it now and get out.
+		 */
+		if (ifp->if_broot_bytes == 0) {
+			new_size = XFS_RTRMAP_BROOT_SPACE_CALC(rec_diff,
+					cur->bc_nlevels - 1);
+			ifp->if_broot = kmem_alloc(new_size,
+					KM_SLEEP | KM_NOFS);
+			ifp->if_broot_bytes = (int)new_size;
+			return;
+		}
+
+		/*
+		 * If there is already an existing if_broot, then we need
+		 * to realloc() it and shift the pointers to their new
+		 * location.  The records don't change location because
+		 * they are kept butted up against the btree block header.
+		 */
+		broot = (struct xfs_btree_block *)ifp->if_broot;
+		level = be16_to_cpu(broot->bb_level);
+		cur_max = xfs_rtrmapbt_maxrecs(mp, ifp->if_broot_bytes,
+				level == 0);
+		new_max = cur_max + rec_diff;
+		new_size = XFS_RTRMAP_BROOT_SPACE_CALC(new_max, level);
+		ifp->if_broot = kmem_realloc(ifp->if_broot, new_size,
+				KM_SLEEP | KM_NOFS);
+		if (level > 0) {
+			op = (char *)XFS_RTRMAP_BROOT_PTR_ADDR(ifp->if_broot,
+					1, ifp->if_broot_bytes);
+			np = (char *)XFS_RTRMAP_BROOT_PTR_ADDR(ifp->if_broot,
+					1, (int)new_size);
+			memmove(np, op, cur_max * sizeof(xfs_fsblock_t));
+		}
+		ifp->if_broot_bytes = (int)new_size;
+		ASSERT(XFS_RTRMAP_ROOT_SPACE(ifp->if_broot) <=
+				XFS_IFORK_SIZE(ip, whichfork));
+		return;
+	}
+
+	/*
+	 * rec_diff is less than 0.  In this case, we are shrinking the
+	 * if_broot buffer.  It must already exist.  If we go to zero
+	 * records, just get rid of the root and clear the status bit.
+	 */
+	ASSERT((ifp->if_broot != NULL) && (ifp->if_broot_bytes > 0));
+	broot = (struct xfs_btree_block *)ifp->if_broot;
+	level = be16_to_cpu(broot->bb_level);
+	cur_max = xfs_rtrmapbt_maxrecs(mp, ifp->if_broot_bytes, level == 0);
+	new_max = cur_max + rec_diff;
+	if (new_max < 0)
+		new_max = 0;
+	new_size = XFS_RTRMAP_BROOT_SPACE_CALC(new_max, level);
+	new_broot = kmem_alloc(new_size, KM_SLEEP | KM_NOFS);
+	memcpy(new_broot, ifp->if_broot, XFS_RTRMAP_BLOCK_LEN);
+
+	/* Copy the records or keys and pointers. */
+	if (level > 0) {
+		op = (char *)XFS_RTRMAP_KEY_ADDR(ifp->if_broot, 1);
+		np = (char *)XFS_RTRMAP_KEY_ADDR(new_broot, 1);
+		memcpy(np, op, new_max * 2 * sizeof(struct xfs_rtrmap_key));
+
+		op = (char *)XFS_RTRMAP_BROOT_PTR_ADDR(ifp->if_broot, 1,
+				ifp->if_broot_bytes);
+		np = (char *)XFS_RTRMAP_BROOT_PTR_ADDR(new_broot, 1,
+				(int)new_size);
+		memcpy(np, op, new_max * sizeof(xfs_fsblock_t));
+	} else {
+		op = (char *)XFS_RTRMAP_REC_ADDR(ifp->if_broot, 1);
+		np = (char *)XFS_RTRMAP_REC_ADDR(new_broot, 1);
+		memcpy(np, op, new_max * sizeof(struct xfs_rtrmap_rec));
+	}
+
+	kmem_free(ifp->if_broot);
+	ifp->if_broot = new_broot;
+	ifp->if_broot_bytes = (int)new_size;
+	if (ifp->if_broot)
+		ASSERT(XFS_RTRMAP_ROOT_SPACE(ifp->if_broot) <=
+				XFS_IFORK_SIZE(ip, whichfork));
+	return;
+}
+
 static bool
 xfs_rtrmapbt_verify(
 	struct xfs_buf		*bp)
@@ -441,12 +600,14 @@ static const struct xfs_btree_ops xfs_rtrmapbt_ops = {
 	.free_block		= xfs_rtrmapbt_free_block,
 	.get_minrecs		= xfs_rtrmapbt_get_minrecs,
 	.get_maxrecs		= xfs_rtrmapbt_get_maxrecs,
+	.get_dmaxrecs		= xfs_rtrmapbt_get_dmaxrecs,
 	.init_key_from_rec	= xfs_rtrmapbt_init_key_from_rec,
 	.init_high_key_from_rec	= xfs_rtrmapbt_init_high_key_from_rec,
 	.init_rec_from_cur	= xfs_rtrmapbt_init_rec_from_cur,
 	.init_ptr_from_cur	= xfs_rtrmapbt_init_ptr_from_cur,
 	.key_diff		= xfs_rtrmapbt_key_diff,
 	.buf_ops		= &xfs_rtrmapbt_buf_ops,
+	.iroot_realloc		= xfs_rtrmapbt_iroot_realloc,
 	.diff_two_keys		= xfs_rtrmapbt_diff_two_keys,
 	.keys_inorder		= xfs_rtrmapbt_keys_inorder,
 	.recs_inorder		= xfs_rtrmapbt_recs_inorder,
@@ -512,3 +673,92 @@ xfs_rtrmapbt_compute_maxlevels(
 			mp->m_rtrmap_mnr, mp->m_sb.sb_rblocks);
 	ASSERT(mp->m_rtrmap_maxlevels <= XFS_BTREE_MAXLEVELS);
 }
+
+/*
+ * Convert on-disk form of btree root to in-memory form.
+ */
+void
+xfs_rtrmapbt_from_disk(
+	struct xfs_inode	*ip,
+	struct xfs_rtrmap_root	*dblock,
+	int			dblocklen,
+	struct xfs_btree_block	*rblock,
+	int			rblocklen)
+{
+	struct xfs_mount	*mp = ip->i_mount;
+	int			dmxr;
+	struct xfs_rtrmap_key	*fkp;
+	__be64			*fpp;
+	struct xfs_rtrmap_key	*tkp;
+	__be64			*tpp;
+	struct xfs_rtrmap_rec	*frp;
+	struct xfs_rtrmap_rec	*trp;
+
+	xfs_btree_init_block_int(mp, rblock, XFS_BUF_DADDR_NULL,
+			 XFS_RTRMAP_CRC_MAGIC, 0, 0, ip->i_ino,
+			 XFS_BTREE_LONG_PTRS | XFS_BTREE_CRC_BLOCKS);
+
+	rblock->bb_level = dblock->bb_level;
+	rblock->bb_numrecs = dblock->bb_numrecs;
+
+	if (be16_to_cpu(rblock->bb_level) > 0) {
+		dmxr = xfs_rtrmapbt_maxrecs(mp, dblocklen, 0);
+		fkp = XFS_RTRMAP_ROOT_KEY_ADDR(dblock, 1);
+		tkp = XFS_RTRMAP_KEY_ADDR(rblock, 1);
+		fpp = XFS_RTRMAP_ROOT_PTR_ADDR(dblock, 1, dmxr);
+		tpp = XFS_RTRMAP_BROOT_PTR_ADDR(rblock, 1, rblocklen);
+		dmxr = be16_to_cpu(dblock->bb_numrecs);
+		memcpy(tkp, fkp, 2 * sizeof(*fkp) * dmxr);
+		memcpy(tpp, fpp, sizeof(*fpp) * dmxr);
+	} else {
+		frp = XFS_RTRMAP_ROOT_REC_ADDR(dblock, 1);
+		trp = XFS_RTRMAP_REC_ADDR(rblock, 1);
+		dmxr = be16_to_cpu(dblock->bb_numrecs);
+		memcpy(trp, frp, sizeof(*frp) * dmxr);
+	}
+}
+
+/*
+ * Convert in-memory form of btree root to on-disk form.
+ */
+void
+xfs_rtrmapbt_to_disk(
+	struct xfs_mount	*mp,
+	struct xfs_btree_block	*rblock,
+	int			rblocklen,
+	struct xfs_rtrmap_root	*dblock,
+	int			dblocklen)
+{
+	int			dmxr;
+	struct xfs_rtrmap_key	*fkp;
+	__be64			*fpp;
+	struct xfs_rtrmap_key	*tkp;
+	__be64			*tpp;
+	struct xfs_rtrmap_rec	*frp;
+	struct xfs_rtrmap_rec	*trp;
+
+	ASSERT(rblock->bb_magic == cpu_to_be32(XFS_RTRMAP_CRC_MAGIC));
+	ASSERT(uuid_equal(&rblock->bb_u.l.bb_uuid, &mp->m_sb.sb_meta_uuid));
+	ASSERT(rblock->bb_u.l.bb_blkno == cpu_to_be64(XFS_BUF_DADDR_NULL));
+	ASSERT(rblock->bb_u.l.bb_leftsib == cpu_to_be64(NULLFSBLOCK));
+	ASSERT(rblock->bb_u.l.bb_rightsib == cpu_to_be64(NULLFSBLOCK));
+
+	dblock->bb_level = rblock->bb_level;
+	dblock->bb_numrecs = rblock->bb_numrecs;
+
+	if (be16_to_cpu(rblock->bb_level) > 0) {
+		dmxr = xfs_rtrmapbt_maxrecs(mp, dblocklen, 0);
+		fkp = XFS_RTRMAP_KEY_ADDR(rblock, 1);
+		tkp = XFS_RTRMAP_ROOT_KEY_ADDR(dblock, 1);
+		fpp = XFS_RTRMAP_BROOT_PTR_ADDR(rblock, 1, rblocklen);
+		tpp = XFS_RTRMAP_ROOT_PTR_ADDR(dblock, 1, dmxr);
+		dmxr = be16_to_cpu(rblock->bb_numrecs);
+		memcpy(tkp, fkp, 2 * sizeof(*fkp) * dmxr);
+		memcpy(tpp, fpp, sizeof(*fpp) * dmxr);
+	} else {
+		frp = XFS_RTRMAP_REC_ADDR(rblock, 1);
+		trp = XFS_RTRMAP_ROOT_REC_ADDR(dblock, 1);
+		dmxr = be16_to_cpu(rblock->bb_numrecs);
+		memcpy(trp, frp, sizeof(*frp) * dmxr);
+	}
+}
diff --git a/libxfs/xfs_rtrmap_btree.h b/libxfs/xfs_rtrmap_btree.h
index 5eb19f4..51adc0c 100644
--- a/libxfs/xfs_rtrmap_btree.h
+++ b/libxfs/xfs_rtrmap_btree.h
@@ -54,9 +54,58 @@ struct xfs_mount;
 		 (maxrecs) * 2 * sizeof(struct xfs_rtrmap_key) + \
 		 ((index) - 1) * sizeof(xfs_rtrmap_ptr_t)))
 
+/* Macros for handling the inode root */
+
+#define XFS_RTRMAP_ROOT_REC_ADDR(block, index) \
+	((struct xfs_rtrmap_rec *) \
+		((char *)(block) + \
+		 sizeof(struct xfs_rtrmap_root) + \
+		 ((index) - 1) * sizeof(struct xfs_rtrmap_rec)))
+
+#define XFS_RTRMAP_ROOT_KEY_ADDR(block, index) \
+	((struct xfs_rtrmap_key *) \
+		((char *)(block) + \
+		 sizeof(struct xfs_rtrmap_root) + \
+		 ((index) - 1) * 2 * sizeof(struct xfs_rtrmap_key)))
+
+#define XFS_RTRMAP_ROOT_PTR_ADDR(block, index, maxrecs) \
+	((xfs_rtrmap_ptr_t *) \
+		((char *)(block) + \
+		 sizeof(struct xfs_rtrmap_root) + \
+		 (maxrecs) * 2 * sizeof(struct xfs_rtrmap_key) + \
+		 ((index) - 1) * sizeof(xfs_rtrmap_ptr_t)))
+
+#define XFS_RTRMAP_BROOT_PTR_ADDR(bb, i, sz) \
+	XFS_RTRMAP_PTR_ADDR(bb, i, xfs_rtrmapbt_maxrecs(mp, sz, 0))
+
+#define XFS_RTRMAP_BROOT_SPACE_CALC(nrecs, level) \
+	(int)(XFS_RTRMAP_BLOCK_LEN + ((level) > 0 ? \
+	       ((nrecs) * (2 * sizeof(struct xfs_rtrmap_key) + sizeof(xfs_rtrmap_ptr_t))) : \
+	       ((nrecs) * sizeof(struct xfs_rtrmap_rec))))
+
+#define XFS_RTRMAP_BROOT_SPACE(bb) \
+	(XFS_RTRMAP_BROOT_SPACE_CALC(be16_to_cpu((bb)->bb_numrecs), \
+				     be16_to_cpu((bb)->bb_level)))
+
+#define XFS_RTRMAP_ROOT_SPACE_CALC(nrecs, level) \
+	(int)(sizeof(struct xfs_rtrmap_root) + ((level) > 0 ? \
+	       ((nrecs) * (2 * sizeof(struct xfs_rtrmap_key) + sizeof(xfs_rtrmap_ptr_t))) : \
+	       ((nrecs) * sizeof(struct xfs_rtrmap_rec))))
+
+#define XFS_RTRMAP_ROOT_SPACE(bb) \
+	(XFS_RTRMAP_ROOT_SPACE_CALC(be16_to_cpu((bb)->bb_numrecs), \
+				    be16_to_cpu((bb)->bb_level)))
+
 struct xfs_btree_cur *xfs_rtrmapbt_init_cursor(struct xfs_mount *mp,
 				struct xfs_trans *tp, struct xfs_inode *ip);
 int xfs_rtrmapbt_maxrecs(struct xfs_mount *mp, int blocklen, bool leaf);
 extern void xfs_rtrmapbt_compute_maxlevels(struct xfs_mount *mp);
 
+void xfs_rtrmapbt_from_disk(struct xfs_inode *ip,
+		struct xfs_rtrmap_root *dblock, int dblocklen,
+		struct xfs_btree_block *rblock, int rblocklen);
+void xfs_rtrmapbt_to_disk(struct xfs_mount *mp,
+		struct xfs_btree_block *rblock, int rblocklen,
+		struct xfs_rtrmap_root *dblock, int dblocklen);
+
 #endif	/* __XFS_RTRMAP_BTREE_H__ */

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 13/29] xfs: don't assume a left rmap when allocating a new rmap
  2016-08-25 23:58 [PATCH v8 00/29] xfsprogs: add realtime reverse-mapping support Darrick J. Wong
                   ` (11 preceding siblings ...)
  2016-08-25 23:59 ` [PATCH 12/29] xfs: wire up a new inode fork type for the realtime rmap Darrick J. Wong
@ 2016-08-25 23:59 ` Darrick J. Wong
  2016-08-26  0:00 ` [PATCH 14/29] xfs: wire up rmap map and unmap to the realtime rmapbt Darrick J. Wong
                   ` (15 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: Darrick J. Wong @ 2016-08-25 23:59 UTC (permalink / raw)
  To: david, darrick.wong; +Cc: linux-xfs, xfs

The original rmap code assumed that there would always be at least
one rmap in the rmapbt (the AG sb/agf/agi) and so errored out if
it didn't find one.  This assumption isn't true for rtrmapbt, so
remove the check and just deal with the situation.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 libxfs/xfs_rmap.c |   24 ++++++++++++------------
 1 file changed, 12 insertions(+), 12 deletions(-)


diff --git a/libxfs/xfs_rmap.c b/libxfs/xfs_rmap.c
index dc1e3a7..4ed2f2e 100644
--- a/libxfs/xfs_rmap.c
+++ b/libxfs/xfs_rmap.c
@@ -706,19 +706,19 @@ xfs_rmap_map(
 			&have_lt);
 	if (error)
 		goto out_error;
-	XFS_WANT_CORRUPTED_GOTO(mp, have_lt == 1, out_error);
-
-	error = xfs_rmap_get_rec(cur, &ltrec, &have_lt);
-	if (error)
-		goto out_error;
-	XFS_WANT_CORRUPTED_GOTO(mp, have_lt == 1, out_error);
-	trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
-			xfs_rmap_cur_agno(cur), ltrec.rm_startblock,
-			ltrec.rm_blockcount, ltrec.rm_owner,
-			ltrec.rm_offset, ltrec.rm_flags);
+	if (have_lt) {
+		error = xfs_rmap_get_rec(cur, &ltrec, &have_lt);
+		if (error)
+			goto out_error;
+		XFS_WANT_CORRUPTED_GOTO(mp, have_lt == 1, out_error);
+		trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
+				xfs_rmap_cur_agno(cur), ltrec.rm_startblock,
+				ltrec.rm_blockcount, ltrec.rm_owner,
+				ltrec.rm_offset, ltrec.rm_flags);
 
-	if (!xfs_rmap_is_mergeable(&ltrec, owner, flags))
-		have_lt = 0;
+		if (!xfs_rmap_is_mergeable(&ltrec, owner, flags))
+			have_lt = 0;
+	}
 
 	XFS_WANT_CORRUPTED_GOTO(mp,
 		have_lt == 0 ||

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 14/29] xfs: wire up rmap map and unmap to the realtime rmapbt
  2016-08-25 23:58 [PATCH v8 00/29] xfsprogs: add realtime reverse-mapping support Darrick J. Wong
                   ` (12 preceding siblings ...)
  2016-08-25 23:59 ` [PATCH 13/29] xfs: don't assume a left rmap when allocating a new rmap Darrick J. Wong
@ 2016-08-26  0:00 ` Darrick J. Wong
  2016-08-26  0:00 ` [PATCH 15/29] xfs: scrub " Darrick J. Wong
                   ` (14 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: Darrick J. Wong @ 2016-08-26  0:00 UTC (permalink / raw)
  To: david, darrick.wong; +Cc: linux-xfs, xfs

Connect the map and unmap reverse-mapping operations to the realtime
rmapbt via the deferred operation callbacks.  This enables us to
perform rmap operations against the correct btree.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 libxfs/defer_item.c |    3 ++
 libxfs/xfs_rmap.c   |   63 +++++++++++++++++++++++++++++++++------------------
 libxfs/xfs_rmap.h   |    9 ++++---
 3 files changed, 48 insertions(+), 27 deletions(-)


diff --git a/libxfs/defer_item.c b/libxfs/defer_item.c
index d4cd876..58b646f 100644
--- a/libxfs/defer_item.c
+++ b/libxfs/defer_item.c
@@ -200,13 +200,14 @@ xfs_rmap_update_finish_item(
 	int				error;
 
 	rmap = container_of(item, struct xfs_rmap_intent, ri_list);
-	error = xfs_rmap_finish_one(tp,
+	error = xfs_rmap_finish_one(tp, dop,
 			rmap->ri_type,
 			rmap->ri_owner, rmap->ri_whichfork,
 			rmap->ri_bmap.br_startoff,
 			rmap->ri_bmap.br_startblock,
 			rmap->ri_bmap.br_blockcount,
 			rmap->ri_bmap.br_state,
+			rmap->ri_realtime,
 			(struct xfs_btree_cur **)state);
 	kmem_free(rmap);
 	return error;
diff --git a/libxfs/xfs_rmap.c b/libxfs/xfs_rmap.c
index 4ed2f2e..55744b7 100644
--- a/libxfs/xfs_rmap.c
+++ b/libxfs/xfs_rmap.c
@@ -36,6 +36,7 @@
 #include "xfs_trace.h"
 #include "xfs_bmap.h"
 #include "xfs_inode.h"
+#include "xfs_rtrmap_btree.h"
 
 /* By convention, the rtrmapbt's "AG" number is NULLAGNUMBER. */
 static xfs_agnumber_t
@@ -2060,13 +2061,14 @@ xfs_rmap_finish_one_cleanup(
 	struct xfs_btree_cur	*rcur,
 	int			error)
 {
-	struct xfs_buf		*agbp;
+	struct xfs_buf		*agbp = NULL;
 
 	if (rcur == NULL)
 		return;
-	agbp = rcur->bc_private.a.agbp;
+	if (!(rcur->bc_flags & XFS_BTREE_LONG_PTRS))
+		agbp = rcur->bc_private.a.agbp;
 	xfs_btree_del_cursor(rcur, error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR);
-	if (error)
+	if (error && agbp)
 		xfs_trans_brelse(tp, agbp);
 }
 
@@ -2080,6 +2082,7 @@ xfs_rmap_finish_one_cleanup(
 int
 xfs_rmap_finish_one(
 	struct xfs_trans		*tp,
+	struct xfs_defer_ops		*dfops,
 	enum xfs_rmap_intent_type	type,
 	__uint64_t			owner,
 	int				whichfork,
@@ -2087,6 +2090,7 @@ xfs_rmap_finish_one(
 	xfs_fsblock_t			startblock,
 	xfs_filblks_t			blockcount,
 	xfs_exntst_t			state,
+	bool				realtime,
 	struct xfs_btree_cur		**pcur)
 {
 	struct xfs_mount		*mp = tp->t_mountp;
@@ -2098,9 +2102,8 @@ xfs_rmap_finish_one(
 	xfs_fsblock_t			bno;
 	bool				unwritten;
 
-	agno = XFS_FSB_TO_AGNO(mp, startblock);
-	ASSERT(agno != NULLAGNUMBER);
-	bno = XFS_FSB_TO_AGBNO(mp, startblock);
+	agno = realtime ? NULLAGNUMBER : XFS_FSB_TO_AGNO(mp, startblock);
+	bno = realtime ? startblock : XFS_FSB_TO_AGBNO(mp, startblock);
 
 	trace_xfs_rmap_deferred(mp, agno, type, bno, owner, whichfork,
 			startoff, blockcount, state);
@@ -2120,31 +2123,45 @@ xfs_rmap_finish_one(
 		*pcur = NULL;
 	}
 	if (rcur == NULL) {
-		/*
-		 * Refresh the freelist before we start changing the
-		 * rmapbt, because a shape change could cause us to
-		 * allocate blocks.
-		 */
-		error = xfs_free_extent_fix_freelist(tp, agno, &agbp);
-		if (error)
-			return error;
-		if (!agbp)
-			return -EFSCORRUPTED;
-
-		rcur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno);
-		if (!rcur) {
-			error = -ENOMEM;
-			goto out_cur;
+		if (realtime) {
+			xfs_ilock(mp->m_rrmapip,
+					XFS_ILOCK_EXCL|XFS_ILOCK_RTBITMAP);
+			xfs_trans_ijoin(tp, mp->m_rrmapip, XFS_ILOCK_EXCL);
+			rcur = xfs_rtrmapbt_init_cursor(mp, tp, mp->m_rrmapip);
+			if (!rcur) {
+				error = -ENOMEM;
+				goto out_cur;
+			}
+			rcur->bc_private.b.dfops = dfops;
+			rcur->bc_private.b.flags = 0;
+		} else {
+			/*
+			 * Refresh the freelist before we start changing the
+			 * rmapbt, because a shape change could cause us to
+			 * allocate blocks.
+			 */
+			error = xfs_free_extent_fix_freelist(tp, agno, &agbp);
+			if (error)
+				return error;
+			if (!agbp)
+				return -EFSCORRUPTED;
+
+			rcur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno);
+			if (!rcur) {
+				error = -ENOMEM;
+				goto out_cur;
+			}
 		}
 	}
 	*pcur = rcur;
 
 	xfs_rmap_ino_owner(&oinfo, owner, whichfork, startoff);
 	unwritten = state == XFS_EXT_UNWRITTEN;
-	bno = XFS_FSB_TO_AGBNO(rcur->bc_mp, startblock);
 
 	switch (type) {
 	case XFS_RMAP_ALLOC:
+		ASSERT(!realtime);
+		/* fall through */
 	case XFS_RMAP_MAP:
 		error = xfs_rmap_map(rcur, bno, blockcount, unwritten, &oinfo);
 		break;
@@ -2153,6 +2170,8 @@ xfs_rmap_finish_one(
 				&oinfo);
 		break;
 	case XFS_RMAP_FREE:
+		ASSERT(!realtime);
+		/* fall through */
 	case XFS_RMAP_UNMAP:
 		error = xfs_rmap_unmap(rcur, bno, blockcount, unwritten,
 				&oinfo);
diff --git a/libxfs/xfs_rmap.h b/libxfs/xfs_rmap.h
index 0850310..8d9c48f 100644
--- a/libxfs/xfs_rmap.h
+++ b/libxfs/xfs_rmap.h
@@ -202,10 +202,11 @@ int xfs_rmap_free_extent(struct xfs_mount *mp, struct xfs_defer_ops *dfops,
 
 void xfs_rmap_finish_one_cleanup(struct xfs_trans *tp,
 		struct xfs_btree_cur *rcur, int error);
-int xfs_rmap_finish_one(struct xfs_trans *tp, enum xfs_rmap_intent_type type,
-		__uint64_t owner, int whichfork, xfs_fileoff_t startoff,
-		xfs_fsblock_t startblock, xfs_filblks_t blockcount,
-		xfs_exntst_t state, struct xfs_btree_cur **pcur);
+int xfs_rmap_finish_one(struct xfs_trans *tp, struct xfs_defer_ops *dfops,
+		enum xfs_rmap_intent_type type, __uint64_t owner, int whichfork,
+		xfs_fileoff_t startoff, xfs_fsblock_t startblock,
+		xfs_filblks_t blockcount, xfs_exntst_t state, bool realtime,
+		struct xfs_btree_cur **pcur);
 
 int xfs_rmap_find_left_neighbor(struct xfs_btree_cur *cur, xfs_fsblock_t bno,
 		uint64_t owner, uint64_t offset, unsigned int flags,

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 15/29] xfs: scrub the realtime rmapbt
  2016-08-25 23:58 [PATCH v8 00/29] xfsprogs: add realtime reverse-mapping support Darrick J. Wong
                   ` (13 preceding siblings ...)
  2016-08-26  0:00 ` [PATCH 14/29] xfs: wire up rmap map and unmap to the realtime rmapbt Darrick J. Wong
@ 2016-08-26  0:00 ` Darrick J. Wong
  2016-08-26  0:00 ` [PATCH 16/29] xfs_db: display the realtime rmap btree contents Darrick J. Wong
                   ` (13 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: Darrick J. Wong @ 2016-08-26  0:00 UTC (permalink / raw)
  To: david, darrick.wong; +Cc: linux-xfs, xfs

Check the realtime reverse mapping btree against the rtbitmap, and
modify the rtbitmap scrub to check against the rtrmapbt.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 libxfs/xfs_fs.h |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)


diff --git a/libxfs/xfs_fs.h b/libxfs/xfs_fs.h
index 2c37d57..112afc0 100644
--- a/libxfs/xfs_fs.h
+++ b/libxfs/xfs_fs.h
@@ -575,7 +575,8 @@ struct xfs_scrub_metadata {
 #define XFS_SCRUB_TYPE_BMBTC	13	/* CoW fork block mapping */
 #define XFS_SCRUB_TYPE_RTBITMAP	14	/* realtime bitmap */
 #define XFS_SCRUB_TYPE_RTSUM	15	/* realtime summary */
-#define XFS_SCRUB_TYPE_MAX	15
+#define XFS_SCRUB_TYPE_RTRMAPBT	16	/* realtime reverse mapping btree */
+#define XFS_SCRUB_TYPE_MAX	16
 
 #define XFS_SCRUB_FLAGS_ALL	0x0	/* no flags yet */
 

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 16/29] xfs_db: display the realtime rmap btree contents
  2016-08-25 23:58 [PATCH v8 00/29] xfsprogs: add realtime reverse-mapping support Darrick J. Wong
                   ` (14 preceding siblings ...)
  2016-08-26  0:00 ` [PATCH 15/29] xfs: scrub " Darrick J. Wong
@ 2016-08-26  0:00 ` Darrick J. Wong
  2016-08-26  0:00 ` [PATCH 17/29] xfs_db: support rudimentary checks of the rtrmap btree Darrick J. Wong
                   ` (12 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: Darrick J. Wong @ 2016-08-26  0:00 UTC (permalink / raw)
  To: david, darrick.wong; +Cc: linux-xfs, xfs

Implement all the code we need to dump rtrmapbt contents, starting
from the root inode.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 db/bmroot.c              |  149 ++++++++++++++++++++++++++++++++++++++++++++++
 db/bmroot.h              |    2 +
 db/btblock.c             |  100 +++++++++++++++++++++++++++++++
 db/btblock.h             |    5 ++
 db/field.c               |   13 ++++
 db/field.h               |    6 ++
 db/inode.c               |   18 +++++-
 db/sb.c                  |    1 
 db/type.c                |    5 ++
 db/type.h                |    8 +-
 libxfs/libxfs_api_defs.h |    1 
 man/man8/xfs_db.8        |   60 ++++++++++++++++++-
 12 files changed, 362 insertions(+), 6 deletions(-)


diff --git a/db/bmroot.c b/db/bmroot.c
index 7697e61..8ad3637 100644
--- a/db/bmroot.c
+++ b/db/bmroot.c
@@ -36,6 +36,13 @@ static int	bmrootd_key_offset(void *obj, int startoff, int idx);
 static int	bmrootd_ptr_count(void *obj, int startoff);
 static int	bmrootd_ptr_offset(void *obj, int startoff, int idx);
 
+static int	rtrmaproot_rec_count(void *obj, int startoff);
+static int	rtrmaproot_rec_offset(void *obj, int startoff, int idx);
+static int	rtrmaproot_key_count(void *obj, int startoff);
+static int	rtrmaproot_key_offset(void *obj, int startoff, int idx);
+static int	rtrmaproot_ptr_count(void *obj, int startoff);
+static int	rtrmaproot_ptr_offset(void *obj, int startoff, int idx);
+
 #define	OFF(f)	bitize(offsetof(xfs_bmdr_block_t, bb_ ## f))
 const field_t	bmroota_flds[] = {
 	{ "level", FLDT_UINT16D, OI(OFF(level)), C1, 0, TYP_NONE },
@@ -66,6 +73,20 @@ const field_t	bmrootd_key_flds[] = {
 	{ NULL }
 };
 
+/* realtime rmap btree root */
+const field_t	rtrmaproot_flds[] = {
+	{ "level", FLDT_UINT16D, OI(OFF(level)), C1, 0, TYP_NONE },
+	{ "numrecs", FLDT_UINT16D, OI(OFF(numrecs)), C1, 0, TYP_NONE },
+	{ "recs", FLDT_RTRMAPBTREC, rtrmaproot_rec_offset, rtrmaproot_rec_count,
+	  FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_NONE },
+	{ "keys", FLDT_RTRMAPBTKEY, rtrmaproot_key_offset, rtrmaproot_key_count,
+	  FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_NONE },
+	{ "ptrs", FLDT_RTRMAPBTPTR, rtrmaproot_ptr_offset, rtrmaproot_ptr_count,
+	  FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_RTRMAPBT },
+	{ NULL }
+};
+#undef OFF
+
 static int
 bmroota_key_count(
 	void			*obj,
@@ -253,3 +274,131 @@ bmrootd_size(
 	dip = obj;
 	return bitize((int)XFS_DFORK_DSIZE(dip, mp));
 }
+
+/* realtime rmap root */
+static int
+rtrmaproot_rec_count(
+	void			*obj,
+	int			startoff)
+{
+	struct xfs_rtrmap_root	*block;
+#ifdef DEBUG
+	struct xfs_dinode	*dip = obj;
+#endif
+
+	ASSERT(bitoffs(startoff) == 0);
+	ASSERT(obj == iocur_top->data);
+	block = (struct xfs_rtrmap_root *)((char *)obj + byteize(startoff));
+	ASSERT((char *)block == XFS_DFORK_DPTR(dip));
+	if (be16_to_cpu(block->bb_level) > 0)
+		return 0;
+	return be16_to_cpu(block->bb_numrecs);
+}
+
+static int
+rtrmaproot_rec_offset(
+	void			*obj,
+	int			startoff,
+	int			idx)
+{
+	struct xfs_rtrmap_root	*block;
+	struct xfs_rtrmap_rec	*kp;
+
+	ASSERT(bitoffs(startoff) == 0);
+	ASSERT(obj == iocur_top->data);
+	block = (struct xfs_rtrmap_root *)((char *)obj + byteize(startoff));
+	ASSERT(be16_to_cpu(block->bb_level) == 0);
+	kp = XFS_RTRMAP_ROOT_REC_ADDR(block, idx);
+	return bitize((int)((char *)kp - (char *)block));
+}
+
+static int
+rtrmaproot_key_count(
+	void			*obj,
+	int			startoff)
+{
+	struct xfs_rtrmap_root	*block;
+#ifdef DEBUG
+	struct xfs_dinode	*dip = obj;
+#endif
+
+	ASSERT(bitoffs(startoff) == 0);
+	ASSERT(obj == iocur_top->data);
+	block = (struct xfs_rtrmap_root *)((char *)obj + byteize(startoff));
+	ASSERT((char *)block == XFS_DFORK_DPTR(dip));
+	if (be16_to_cpu(block->bb_level) == 0)
+		return 0;
+	return be16_to_cpu(block->bb_numrecs);
+}
+
+static int
+rtrmaproot_key_offset(
+	void			*obj,
+	int			startoff,
+	int			idx)
+{
+	struct xfs_rtrmap_root	*block;
+	struct xfs_rtrmap_key	*kp;
+
+	ASSERT(bitoffs(startoff) == 0);
+	ASSERT(obj == iocur_top->data);
+	block = (struct xfs_rtrmap_root *)((char *)obj + byteize(startoff));
+	ASSERT(be16_to_cpu(block->bb_level) > 0);
+	kp = XFS_RTRMAP_ROOT_KEY_ADDR(block, idx);
+	return bitize((int)((char *)kp - (char *)block));
+}
+
+static int
+rtrmaproot_ptr_count(
+	void			*obj,
+	int			startoff)
+{
+	struct xfs_rtrmap_root	*block;
+#ifdef DEBUG
+	struct xfs_dinode	*dip = obj;
+#endif
+
+	ASSERT(bitoffs(startoff) == 0);
+	ASSERT(obj == iocur_top->data);
+	block = (struct xfs_rtrmap_root *)((char *)obj + byteize(startoff));
+	ASSERT((char *)block == XFS_DFORK_DPTR(dip));
+	if (be16_to_cpu(block->bb_level) == 0)
+		return 0;
+	return be16_to_cpu(block->bb_numrecs);
+}
+
+static int
+rtrmaproot_ptr_offset(
+	void			*obj,
+	int			startoff,
+	int			idx)
+{
+	struct xfs_rtrmap_root	*block;
+	xfs_rtrmap_ptr_t	*pp;
+	struct xfs_dinode	*dip;
+
+	ASSERT(bitoffs(startoff) == 0);
+	ASSERT(obj == iocur_top->data);
+	dip = obj;
+	block = (struct xfs_rtrmap_root *)((char *)obj + byteize(startoff));
+	ASSERT(be16_to_cpu(block->bb_level) > 0);
+	pp = XFS_RTRMAP_ROOT_PTR_ADDR(block, idx,
+			libxfs_rtrmapbt_maxrecs(mp, XFS_DFORK_DSIZE(dip, mp),
+				0));
+	return bitize((int)((char *)pp - (char *)block));
+}
+
+int
+rtrmaproot_size(
+	void			*obj,
+	int			startoff,
+	int			idx)
+{
+	struct xfs_dinode	*dip;
+
+	ASSERT(bitoffs(startoff) == 0);
+	ASSERT(obj == iocur_top->data);
+	ASSERT(idx == 0);
+	dip = obj;
+	return bitize((int)XFS_DFORK_DSIZE(dip, mp));
+}
diff --git a/db/bmroot.h b/db/bmroot.h
index 4cb4d23..6e105a7 100644
--- a/db/bmroot.h
+++ b/db/bmroot.h
@@ -20,6 +20,8 @@ extern const struct field	bmroota_flds[];
 extern const struct field	bmroota_key_flds[];
 extern const struct field	bmrootd_flds[];
 extern const struct field	bmrootd_key_flds[];
+extern const struct field	rtrmaproot_flds[];
 
 extern int	bmroota_size(void *obj, int startoff, int idx);
 extern int	bmrootd_size(void *obj, int startoff, int idx);
+extern int	rtrmaproot_size(void *obj, int startoff, int idx);
diff --git a/db/btblock.c b/db/btblock.c
index e0c896b..39037a2 100644
--- a/db/btblock.c
+++ b/db/btblock.c
@@ -102,6 +102,12 @@ struct xfs_db_btree {
 		sizeof(struct xfs_rmap_rec),
 		sizeof(__be32),
 	},
+	{	XFS_RTRMAP_CRC_MAGIC,
+		XFS_BTREE_LBLOCK_CRC_LEN,
+		2 * sizeof(struct xfs_rtrmap_key),
+		sizeof(struct xfs_rtrmap_rec),
+		sizeof(__be64),
+	},
 	{	XFS_REFC_CRC_MAGIC,
 		XFS_BTREE_SBLOCK_CRC_LEN,
 		sizeof(struct xfs_refcount_key),
@@ -714,6 +720,100 @@ const field_t	rmapbt_rec_flds[] = {
 };
 #undef ROFF
 
+/* realtime RMAP btree blocks */
+const field_t	rtrmapbt_crc_hfld[] = {
+	{ "", FLDT_RTRMAPBT_CRC, OI(0), C1, 0, TYP_NONE },
+	{ NULL }
+};
+
+#define	OFF(f)	bitize(offsetof(struct xfs_btree_block, bb_ ## f))
+const field_t	rtrmapbt_crc_flds[] = {
+	{ "magic", FLDT_UINT32X, OI(OFF(magic)), C1, 0, TYP_NONE },
+	{ "level", FLDT_UINT16D, OI(OFF(level)), C1, 0, TYP_NONE },
+	{ "numrecs", FLDT_UINT16D, OI(OFF(numrecs)), C1, 0, TYP_NONE },
+	{ "leftsib", FLDT_DFSBNO, OI(OFF(u.l.bb_leftsib)), C1, 0, TYP_RTRMAPBT },
+	{ "rightsib", FLDT_DFSBNO, OI(OFF(u.l.bb_rightsib)), C1, 0, TYP_RTRMAPBT },
+	{ "bno", FLDT_DFSBNO, OI(OFF(u.l.bb_blkno)), C1, 0, TYP_RTRMAPBT },
+	{ "lsn", FLDT_UINT64X, OI(OFF(u.l.bb_lsn)), C1, 0, TYP_NONE },
+	{ "uuid", FLDT_UUID, OI(OFF(u.l.bb_uuid)), C1, 0, TYP_NONE },
+	{ "owner", FLDT_INO, OI(OFF(u.l.bb_owner)), C1, 0, TYP_NONE },
+	{ "crc", FLDT_CRC, OI(OFF(u.l.bb_crc)), C1, 0, TYP_NONE },
+	{ "recs", FLDT_RTRMAPBTREC, btblock_rec_offset, btblock_rec_count,
+	  FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_NONE },
+	{ "keys", FLDT_RTRMAPBTKEY, btblock_key_offset, btblock_key_count,
+	  FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_NONE },
+	{ "ptrs", FLDT_RTRMAPBTPTR, btblock_ptr_offset, btblock_key_count,
+	  FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_RTRMAPBT },
+	{ NULL }
+};
+#undef OFF
+
+#define	KOFF(f)	bitize(offsetof(struct xfs_rtrmap_key, rm_ ## f))
+
+#define RTRMAPBK_STARTBLOCK_BITOFF	0
+#define RTRMAPBK_OWNER_BITOFF		(RTRMAPBK_STARTBLOCK_BITOFF + RTRMAPBT_STARTBLOCK_BITLEN)
+#define RTRMAPBK_ATTRFLAG_BITOFF	(RTRMAPBK_OWNER_BITOFF + RTRMAPBT_OWNER_BITLEN)
+#define RTRMAPBK_BMBTFLAG_BITOFF	(RTRMAPBK_ATTRFLAG_BITOFF + RTRMAPBT_ATTRFLAG_BITLEN)
+#define RTRMAPBK_EXNTFLAG_BITOFF	(RTRMAPBK_BMBTFLAG_BITOFF + RTRMAPBT_BMBTFLAG_BITLEN)
+#define RTRMAPBK_UNUSED_OFFSET_BITOFF	(RTRMAPBK_EXNTFLAG_BITOFF + RTRMAPBT_EXNTFLAG_BITLEN)
+#define RTRMAPBK_OFFSET_BITOFF		(RTRMAPBK_UNUSED_OFFSET_BITOFF + RTRMAPBT_UNUSED_OFFSET_BITLEN)
+
+#define HI_KOFF(f)	bitize(sizeof(struct xfs_rtrmap_key) + offsetof(struct xfs_rtrmap_key, rm_ ## f))
+
+#define RTRMAPBK_STARTBLOCKHI_BITOFF	(bitize(sizeof(struct xfs_rtrmap_key)))
+#define RTRMAPBK_OWNERHI_BITOFF		(RTRMAPBK_STARTBLOCKHI_BITOFF + RTRMAPBT_STARTBLOCK_BITLEN)
+#define RTRMAPBK_ATTRFLAGHI_BITOFF	(RTRMAPBK_OWNERHI_BITOFF + RTRMAPBT_OWNER_BITLEN)
+#define RTRMAPBK_BMBTFLAGHI_BITOFF	(RTRMAPBK_ATTRFLAGHI_BITOFF + RTRMAPBT_ATTRFLAG_BITLEN)
+#define RTRMAPBK_EXNTFLAGHI_BITOFF	(RTRMAPBK_BMBTFLAGHI_BITOFF + RTRMAPBT_BMBTFLAG_BITLEN)
+#define RTRMAPBK_UNUSED_OFFSETHI_BITOFF	(RTRMAPBK_EXNTFLAGHI_BITOFF + RTRMAPBT_EXNTFLAG_BITLEN)
+#define RTRMAPBK_OFFSETHI_BITOFF	(RTRMAPBK_UNUSED_OFFSETHI_BITOFF + RTRMAPBT_UNUSED_OFFSET_BITLEN)
+
+const field_t	rtrmapbt_key_flds[] = {
+	{ "startblock", FLDT_DRTBNO, OI(KOFF(startblock)), C1, 0, TYP_DATA },
+	{ "owner", FLDT_INT64D, OI(KOFF(owner)), C1, 0, TYP_NONE },
+	{ "offset", FLDT_RFILEOFFD, OI(RTRMAPBK_OFFSET_BITOFF), C1, 0, TYP_NONE },
+	{ "attrfork", FLDT_RATTRFORKFLG, OI(RTRMAPBK_ATTRFLAG_BITOFF), C1, 0,
+	  TYP_NONE },
+	{ "bmbtblock", FLDT_RBMBTFLG, OI(RTRMAPBK_BMBTFLAG_BITOFF), C1, 0,
+	  TYP_NONE },
+	{ "startblock_hi", FLDT_DRTBNO, OI(HI_KOFF(startblock)), C1, 0, TYP_DATA },
+	{ "owner_hi", FLDT_INT64D, OI(HI_KOFF(owner)), C1, 0, TYP_NONE },
+	{ "offset_hi", FLDT_RFILEOFFD, OI(RTRMAPBK_OFFSETHI_BITOFF), C1, 0, TYP_NONE },
+	{ "attrfork_hi", FLDT_RATTRFORKFLG, OI(RTRMAPBK_ATTRFLAGHI_BITOFF), C1, 0,
+	  TYP_NONE },
+	{ "bmbtblock_hi", FLDT_RBMBTFLG, OI(RTRMAPBK_BMBTFLAGHI_BITOFF), C1, 0,
+	  TYP_NONE },
+	{ NULL }
+};
+#undef HI_KOFF
+#undef KOFF
+
+#define	ROFF(f)	bitize(offsetof(struct xfs_rtrmap_rec, rm_ ## f))
+
+#define RTRMAPBT_STARTBLOCK_BITOFF	0
+#define RTRMAPBT_BLOCKCOUNT_BITOFF	(RTRMAPBT_STARTBLOCK_BITOFF + RTRMAPBT_STARTBLOCK_BITLEN)
+#define RTRMAPBT_OWNER_BITOFF		(RTRMAPBT_BLOCKCOUNT_BITOFF + RTRMAPBT_BLOCKCOUNT_BITLEN)
+#define RTRMAPBT_ATTRFLAG_BITOFF	(RTRMAPBT_OWNER_BITOFF + RTRMAPBT_OWNER_BITLEN)
+#define RTRMAPBT_BMBTFLAG_BITOFF	(RTRMAPBT_ATTRFLAG_BITOFF + RTRMAPBT_ATTRFLAG_BITLEN)
+#define RTRMAPBT_EXNTFLAG_BITOFF	(RTRMAPBT_BMBTFLAG_BITOFF + RTRMAPBT_BMBTFLAG_BITLEN)
+#define RTRMAPBT_UNUSED_OFFSET_BITOFF	(RTRMAPBT_EXNTFLAG_BITOFF + RTRMAPBT_EXNTFLAG_BITLEN)
+#define RTRMAPBT_OFFSET_BITOFF		(RTRMAPBT_UNUSED_OFFSET_BITOFF + RTRMAPBT_UNUSED_OFFSET_BITLEN)
+
+const field_t	rtrmapbt_rec_flds[] = {
+	{ "startblock", FLDT_DRFSBNO, OI(RTRMAPBT_STARTBLOCK_BITOFF), C1, 0, TYP_DATA },
+	{ "blockcount", FLDT_RTREXTLEN, OI(RTRMAPBT_BLOCKCOUNT_BITOFF), C1, 0, TYP_NONE },
+	{ "owner", FLDT_INT64D, OI(RTRMAPBT_OWNER_BITOFF), C1, 0, TYP_NONE },
+	{ "offset", FLDT_RFILEOFFD, OI(RTRMAPBT_OFFSET_BITOFF), C1, 0, TYP_NONE },
+	{ "extentflag", FLDT_REXTFLG, OI(RTRMAPBT_EXNTFLAG_BITOFF), C1, 0,
+	  TYP_NONE },
+	{ "attrfork", FLDT_RATTRFORKFLG, OI(RTRMAPBT_ATTRFLAG_BITOFF), C1, 0,
+	  TYP_NONE },
+	{ "bmbtblock", FLDT_RBMBTFLG, OI(RTRMAPBT_BMBTFLAG_BITOFF), C1, 0,
+	  TYP_NONE },
+	{ NULL }
+};
+#undef ROFF
+
 /* refcount btree blocks */
 const field_t	refcbt_crc_hfld[] = {
 	{ "", FLDT_REFCBT_CRC, OI(0), C1, 0, TYP_NONE },
diff --git a/db/btblock.h b/db/btblock.h
index fead2f1..2c83487 100644
--- a/db/btblock.h
+++ b/db/btblock.h
@@ -59,6 +59,11 @@ extern const struct field	rmapbt_crc_hfld[];
 extern const struct field	rmapbt_key_flds[];
 extern const struct field	rmapbt_rec_flds[];
 
+extern const struct field	rtrmapbt_crc_flds[];
+extern const struct field	rtrmapbt_crc_hfld[];
+extern const struct field	rtrmapbt_key_flds[];
+extern const struct field	rtrmapbt_rec_flds[];
+
 extern const struct field	refcbt_crc_flds[];
 extern const struct field	refcbt_crc_hfld[];
 extern const struct field	refcbt_key_flds[];
diff --git a/db/field.c b/db/field.c
index e0e7066..baac271 100644
--- a/db/field.c
+++ b/db/field.c
@@ -155,6 +155,8 @@ const ftattr_t	ftattrtab[] = {
 	{ FLDT_CHARS, "chars", fp_num, "%c", SI(bitsz(char)), 0, NULL, NULL },
 	{ FLDT_REXTLEN, "rextlen", fp_num, "%u", SI(RMAPBT_BLOCKCOUNT_BITLEN),
 	  0, NULL, NULL },
+	{ FLDT_RTREXTLEN, "rtrextlen", fp_num, "%llu", SI(bitsz(uint64_t)),
+	  0, NULL, NULL },
 	{ FLDT_RFILEOFFD, "rfileoffd", fp_num, "%llu", SI(RMAPBT_OFFSET_BITLEN),
 	  0, NULL, NULL },
 	{ FLDT_REXTFLG, "rextflag", fp_num, "%u", SI(RMAPBT_EXNTFLAG_BITLEN), 0,
@@ -183,6 +185,17 @@ const ftattr_t	ftattrtab[] = {
 	{ FLDT_RMAPBTREC, "rmapbtrec", fp_sarray, (char *)rmapbt_rec_flds,
 	  SI(bitsz(struct xfs_rmap_rec)), 0, NULL, rmapbt_rec_flds },
 
+	{ FLDT_RTRMAPBT_CRC, "rtrmapbt", NULL, (char *)rtrmapbt_crc_flds, btblock_size,
+	  FTARG_SIZE, NULL, rtrmapbt_crc_flds },
+	{ FLDT_RTRMAPBTKEY, "rtrmapbtkey", fp_sarray, (char *)rtrmapbt_key_flds,
+	  SI(bitize(2 * sizeof(struct xfs_rtrmap_key))), 0, NULL, rtrmapbt_key_flds },
+	{ FLDT_RTRMAPBTPTR, "rtrmapbtptr", fp_num, "%llu",
+	  SI(bitsz(xfs_rtrmap_ptr_t)), 0, fa_dfsbno, NULL },
+	{ FLDT_RTRMAPBTREC, "rtrmapbtrec", fp_sarray, (char *)rtrmapbt_rec_flds,
+	  SI(bitsz(struct xfs_rtrmap_rec)), 0, NULL, rtrmapbt_rec_flds },
+	{ FLDT_RTRMAPROOT, "rtrmaproot", NULL, (char *)rtrmaproot_flds, rtrmaproot_size,
+	  FTARG_SIZE, NULL, rtrmaproot_flds },
+
 	{ FLDT_REFCBT_CRC, "refcntbt", NULL, (char *)refcbt_crc_flds, btblock_size,
 	  FTARG_SIZE, NULL, refcbt_crc_flds },
 	{ FLDT_REFCBTKEY, "refcntbtkey", fp_sarray, (char *)refcbt_key_flds,
diff --git a/db/field.h b/db/field.h
index ae5f490..4537559 100644
--- a/db/field.h
+++ b/db/field.h
@@ -76,6 +76,7 @@ typedef enum fldt	{
 	FLDT_CHARNS,
 	FLDT_CHARS,
 	FLDT_REXTLEN,
+	FLDT_RTREXTLEN,
 	FLDT_RFILEOFFD,
 	FLDT_REXTFLG,
 	FLDT_RATTRFORKFLG,
@@ -89,6 +90,11 @@ typedef enum fldt	{
 	FLDT_RMAPBTKEY,
 	FLDT_RMAPBTPTR,
 	FLDT_RMAPBTREC,
+	FLDT_RTRMAPBT_CRC,
+	FLDT_RTRMAPBTKEY,
+	FLDT_RTRMAPBTPTR,
+	FLDT_RTRMAPBTREC,
+	FLDT_RTRMAPROOT,
 	FLDT_REFCBT_CRC,
 	FLDT_REFCBTKEY,
 	FLDT_REFCBTPTR,
diff --git a/db/inode.c b/db/inode.c
index cac19fc..70019d8 100644
--- a/db/inode.c
+++ b/db/inode.c
@@ -49,6 +49,7 @@ static int	inode_u_muuid_count(void *obj, int startoff);
 static int	inode_u_sfdir2_count(void *obj, int startoff);
 static int	inode_u_sfdir3_count(void *obj, int startoff);
 static int	inode_u_symlink_count(void *obj, int startoff);
+static int	inode_u_rtrmapbt_count(void *obj, int startoff);
 
 static const cmdinfo_t	inode_cmd =
 	{ "inode", NULL, inode_f, 0, 1, 1, "[inode#]",
@@ -204,6 +205,7 @@ const field_t	inode_u_flds[] = {
 	{ "sfdir3", FLDT_DIR3SF, NULL, inode_u_sfdir3_count, FLD_COUNT, TYP_NONE },
 	{ "symlink", FLDT_CHARNS, NULL, inode_u_symlink_count, FLD_COUNT,
 	  TYP_NONE },
+	{ "rtrmapbt", FLDT_RTRMAPROOT, NULL, inode_u_rtrmapbt_count, FLD_COUNT, TYP_NONE },
 	{ NULL }
 };
 
@@ -217,7 +219,7 @@ const field_t	inode_a_flds[] = {
 };
 
 static const char	*dinode_fmt_name[] =
-	{ "dev", "local", "extents", "btree", "uuid" };
+	{ "dev", "local", "extents", "btree", "uuid", "rtrmapbt" };
 static const int	dinode_fmt_name_size =
 	sizeof(dinode_fmt_name) / sizeof(dinode_fmt_name[0]);
 
@@ -585,6 +587,20 @@ inode_u_sfdir3_count(
 	       xfs_sb_version_hasftype(&mp->m_sb);
 }
 
+static int
+inode_u_rtrmapbt_count(
+	void		*obj,
+	int		startoff)
+{
+	xfs_dinode_t	*dip;
+
+	ASSERT(bitoffs(startoff) == 0);
+	ASSERT(obj == iocur_top->data);
+	dip = obj;
+	ASSERT((char *)XFS_DFORK_DPTR(dip) - (char *)dip == byteize(startoff));
+	return dip->di_format == XFS_DINODE_FMT_RMAP;
+}
+
 int
 inode_u_size(
 	void		*obj,
diff --git a/db/sb.c b/db/sb.c
index 8e7722c..eb308ad 100644
--- a/db/sb.c
+++ b/db/sb.c
@@ -125,6 +125,7 @@ const field_t	sb_flds[] = {
 	{ "pquotino", FLDT_INO, OI(OFF(pquotino)), C1, 0, TYP_INODE },
 	{ "lsn", FLDT_UINT64X, OI(OFF(lsn)), C1, 0, TYP_NONE },
 	{ "meta_uuid", FLDT_UUID, OI(OFF(meta_uuid)), C1, 0, TYP_NONE },
+	{ "rrmapino", FLDT_INO, OI(OFF(rrmapino)), C1, 0, TYP_INODE },
 	{ NULL }
 };
 
diff --git a/db/type.c b/db/type.c
index 10fa54e..9d74ded 100644
--- a/db/type.c
+++ b/db/type.c
@@ -61,6 +61,7 @@ static const typ_t	__typtab[] = {
 	{ TYP_BNOBT, "bnobt", handle_struct, bnobt_hfld, NULL, TYP_F_NO_CRC_OFF },
 	{ TYP_CNTBT, "cntbt", handle_struct, cntbt_hfld, NULL, TYP_F_NO_CRC_OFF },
 	{ TYP_RMAPBT, NULL },
+	{ TYP_RTRMAPBT, NULL },
 	{ TYP_REFCBT, NULL },
 	{ TYP_DATA, "data", handle_block, NULL, NULL, TYP_F_NO_CRC_OFF },
 	{ TYP_DIR2, "dir2", handle_struct, dir2_hfld, NULL, TYP_F_NO_CRC_OFF },
@@ -98,6 +99,8 @@ static const typ_t	__typtab_crc[] = {
 		&xfs_allocbt_buf_ops, XFS_BTREE_SBLOCK_CRC_OFF },
 	{ TYP_RMAPBT, "rmapbt", handle_struct, rmapbt_crc_hfld,
 		&xfs_rmapbt_buf_ops, XFS_BTREE_SBLOCK_CRC_OFF },
+	{ TYP_RTRMAPBT, "rtrmapbt", handle_struct, rtrmapbt_crc_hfld,
+		&xfs_rtrmapbt_buf_ops, XFS_BTREE_SBLOCK_CRC_OFF },
 	{ TYP_REFCBT, "refcntbt", handle_struct, refcbt_crc_hfld,
 		&xfs_refcountbt_buf_ops, XFS_BTREE_SBLOCK_CRC_OFF },
 	{ TYP_DATA, "data", handle_block, NULL, NULL, TYP_F_NO_CRC_OFF },
@@ -142,6 +145,8 @@ static const typ_t	__typtab_spcrc[] = {
 		&xfs_allocbt_buf_ops, XFS_BTREE_SBLOCK_CRC_OFF },
 	{ TYP_RMAPBT, "rmapbt", handle_struct, rmapbt_crc_hfld,
 		&xfs_rmapbt_buf_ops, XFS_BTREE_SBLOCK_CRC_OFF },
+	{ TYP_RTRMAPBT, "rtrmapbt", handle_struct, rtrmapbt_crc_hfld,
+		&xfs_rtrmapbt_buf_ops, XFS_BTREE_SBLOCK_CRC_OFF },
 	{ TYP_REFCBT, "refcntbt", handle_struct, refcbt_crc_hfld,
 		&xfs_refcountbt_buf_ops, XFS_BTREE_SBLOCK_CRC_OFF },
 	{ TYP_DATA, "data", handle_block, NULL, NULL, TYP_F_NO_CRC_OFF },
diff --git a/db/type.h b/db/type.h
index 87ff107..5a65900 100644
--- a/db/type.h
+++ b/db/type.h
@@ -24,10 +24,10 @@ struct field;
 typedef enum typnm
 {
 	TYP_AGF, TYP_AGFL, TYP_AGI, TYP_ATTR, TYP_BMAPBTA,
-	TYP_BMAPBTD, TYP_BNOBT, TYP_CNTBT, TYP_RMAPBT, TYP_REFCBT, TYP_DATA,
-	TYP_DIR2, TYP_DQBLK, TYP_INOBT, TYP_INODATA, TYP_INODE,
-	TYP_LOG, TYP_RTBITMAP, TYP_RTSUMMARY, TYP_SB, TYP_SYMLINK,
-	TYP_TEXT, TYP_FINOBT, TYP_NONE
+	TYP_BMAPBTD, TYP_BNOBT, TYP_CNTBT, TYP_RMAPBT, TYP_RTRMAPBT,
+	TYP_REFCBT, TYP_DATA, TYP_DIR2, TYP_DQBLK, TYP_INOBT,
+	TYP_INODATA, TYP_INODE, TYP_LOG, TYP_RTBITMAP, TYP_RTSUMMARY,
+	TYP_SB, TYP_SYMLINK, TYP_TEXT, TYP_FINOBT, TYP_NONE
 } typnm_t;
 
 #define DB_WRITE 1
diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h
index 8d57a66..c66e31b 100644
--- a/libxfs/libxfs_api_defs.h
+++ b/libxfs/libxfs_api_defs.h
@@ -142,5 +142,6 @@
 #define xfs_refcount_get_rec		libxfs_refcount_get_rec
 #define xfs_rmap_lookup_le_range	libxfs_rmap_lookup_le_range
 #define xfs_refc_block			libxfs_refc_block
+#define xfs_rtrmapbt_maxrecs		libxfs_rtrmapbt_maxrecs
 
 #endif /* __LIBXFS_API_DEFS_H__ */
diff --git a/man/man8/xfs_db.8 b/man/man8/xfs_db.8
index 514e3aa..a9d2c81 100644
--- a/man/man8/xfs_db.8
+++ b/man/man8/xfs_db.8
@@ -683,7 +683,7 @@ The possible data types are:
 .BR agf ", " agfl ", " agi ", " attr ", " bmapbta ", " bmapbtd ,
 .BR bnobt ", " cntbt ", " data ", " dir ", " dir2 ", " dqblk ,
 .BR inobt ", " inode ", " log ", " refcntbt ", " rmapbt ", " rtbitmap ,
-.BR rtsummary ", " sb ", " symlink " and " text .
+.BR rtsummary ", " sb ", " symlink ", " rtrmapbt ", and " text .
 See the TYPES section below for more information on these data types.
 .TP
 .BI "uuid [" uuid " | " generate " | " rewrite " | " restore ]
@@ -1764,6 +1764,64 @@ block number within the allocation group to the next level in the Btree.
 .PD
 .RE
 .TP
+.B rtrmapbt
+There is one reverse mapping Btree for the entire realtime device.  The
+.BR startblock " and "
+.B blockcount
+fields are 64 bits wide and record block counts on the realtime device.  The
+root of this Btree is the reverse-mapping inode, which is recorded in the
+superblock
+.B rrmapino
+field.  Blocks are linked to sibling left and right blocks at each level, as
+well as by pointers from parent to child blocks.  Each block has the following
+fields:
+.RS 1.4i
+.PD 0
+.TP 1.2i
+.B magic
+RTRMAP block magic number, 0x4d415052 ('MAPR').
+.TP
+.B level
+level number of this block, 0 is a leaf.
+.TP
+.B numrecs
+number of data entries in the block.
+.TP
+.B leftsib
+left (logically lower) sibling block, 0 if none.
+.TP
+.B rightsib
+right (logically higher) sibling block, 0 if none.
+.TP
+.B recs
+[leaf blocks only] array of reference count records. Each record contains
+.BR startblock ,
+.BR blockcount ,
+.BR owner ,
+.BR offset ,
+.BR attr_fork ,
+.BR bmbt_block ,
+and
+.BR unwritten .
+.TP
+.B keys
+[non-leaf blocks only] array of double-key records. The first ("low") key
+contains the first value of each block in the level below this one. The second
+("high") key contains the largest key that can be used to identify any record
+in the subtree. Each record contains
+.BR startblock ,
+.BR owner ,
+.BR offset ,
+.BR attr_fork ,
+and
+.BR bmbt_block .
+.TP
+.B ptrs
+[non-leaf blocks only] array of child block pointers. Each pointer is a
+block number within the allocation group to the next level in the Btree.
+.PD
+.RE
+.TP
 .B rtbitmap
 If the filesystem has a realtime subvolume, then the
 .B rbmino

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 17/29] xfs_db: support rudimentary checks of the rtrmap btree
  2016-08-25 23:58 [PATCH v8 00/29] xfsprogs: add realtime reverse-mapping support Darrick J. Wong
                   ` (15 preceding siblings ...)
  2016-08-26  0:00 ` [PATCH 16/29] xfs_db: display the realtime rmap btree contents Darrick J. Wong
@ 2016-08-26  0:00 ` Darrick J. Wong
  2016-08-26  0:00 ` [PATCH 18/29] xfs_db: copy the realtime rmap btree Darrick J. Wong
                   ` (11 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: Darrick J. Wong @ 2016-08-26  0:00 UTC (permalink / raw)
  To: david, darrick.wong; +Cc: linux-xfs, xfs

Perform some fairly superficial checks of the rtrmap btree.  We'll
do more sophisticated checks in xfs_repair, but provide enough of
a spot-check here that we can do simple things.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 db/check.c |  191 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 182 insertions(+), 9 deletions(-)


diff --git a/db/check.c b/db/check.c
index 7392852..7ffd5bb 100644
--- a/db/check.c
+++ b/db/check.c
@@ -45,7 +45,7 @@ typedef enum {
 	DBM_LOG,	DBM_MISSING,	DBM_QUOTA,	DBM_RTBITMAP,
 	DBM_RTDATA,	DBM_RTFREE,	DBM_RTSUM,	DBM_SB,
 	DBM_SYMLINK,	DBM_BTFINO,	DBM_BTRMAP,	DBM_BTREFC,
-	DBM_RLDATA,	DBM_COWDATA,
+	DBM_RLDATA,	DBM_COWDATA,	DBM_BTRTRMAP,
 	DBM_NDBM
 } dbm_t;
 
@@ -176,6 +176,8 @@ static const char	*typename[] = {
 	"btrmap",
 	"btrefcnt",
 	"rldata",
+	"cowdata",
+	"btrtrmap",
 	NULL
 };
 static int		verbose;
@@ -316,6 +318,9 @@ static void		process_quota(qtype_t qtype, inodata_t *id,
 				      blkmap_t *blkmap);
 static void		process_rtbitmap(blkmap_t *blkmap);
 static void		process_rtsummary(blkmap_t *blkmap);
+static void		process_rtrmap(struct inodata *id,
+				       struct xfs_dinode *dip,
+				       xfs_rfsblock_t *toti);
 static xfs_ino_t	process_sf_dir_v2(xfs_dinode_t *dip, int *dot,
 					  int *dotdot, inodata_t *id);
 static void		quota_add(xfs_dqid_t *p, xfs_dqid_t *g, xfs_dqid_t *u,
@@ -343,6 +348,12 @@ static void		scanfunc_bmap(struct xfs_btree_block *block,
 				      xfs_rfsblock_t *toti, xfs_extnum_t *nex,
 				      blkmap_t **blkmapp, int isroot,
 				      typnm_t btype);
+static void		scanfunc_rtrmap(struct xfs_btree_block *block,
+				      int level, dbm_t type, xfs_fsblock_t bno,
+				      inodata_t *id, xfs_rfsblock_t *totd,
+				      xfs_rfsblock_t *toti, xfs_extnum_t *nex,
+				      blkmap_t **blkmapp, int isroot,
+				      typnm_t btype);
 static void		scanfunc_bno(struct xfs_btree_block *block, int level,
 				     xfs_agf_t *agf, xfs_agblock_t bno,
 				     int isroot);
@@ -1060,6 +1071,7 @@ blocktrash_f(
 		   (1 << DBM_QUOTA) |
 		   (1 << DBM_RTBITMAP) |
 		   (1 << DBM_RTSUM) |
+		   (1 << DBM_BTRTRMAP) |
 		   (1 << DBM_SYMLINK) |
 		   (1 << DBM_BTFINO) |
 		   (1 << DBM_BTRMAP) |
@@ -2706,7 +2718,7 @@ process_inode(
 		0				/* type 15 unused */
 	};
 	static char		*fmtnames[] = {
-		"dev", "local", "extents", "btree", "uuid"
+		"dev", "local", "extents", "btree", "uuid", "rtrmap"
 	};
 
 	libxfs_inode_from_disk(&xino, dip);
@@ -2761,12 +2773,23 @@ process_inode(
 				be32_to_cpu(dip->di_next_unlinked), ino);
 		error++;
 	}
-	/*
-	 * di_mode is a 16-bit uint so no need to check the < 0 case
-	 */
+
+	/* Check that mode and data fork format match. */
 	mode = be16_to_cpu(dip->di_mode);
-	if ((((mode & S_IFMT) >> 12) > 15) ||
-	    (!(okfmts[(mode & S_IFMT) >> 12] & (1 << xino.i_d.di_format)))) {
+	if (ino == mp->m_sb.sb_rrmapino) {
+		if ((mode & S_IFMT) != S_IFREG ||
+		    xino.i_d.di_format != XFS_DINODE_FMT_RMAP) {
+			if (v)
+				dbprintf(_("bad format %d for rtrmap inode %lld type %#o\n"),
+					xino.i_d.di_format, id->ino, mode & S_IFMT);
+			error++;
+			return;
+		}
+	} else if ((((mode & S_IFMT) >> 12) > 15) ||
+		   (!(okfmts[(mode & S_IFMT) >> 12] & (1 << xino.i_d.di_format)))) {
+		/*
+		 * di_mode is a 16-bit uint so no need to check the < 0 case
+		 */
 		if (v)
 			dbprintf(_("bad format %d for inode %lld type %#o\n"),
 				xino.i_d.di_format, id->ino, mode & S_IFMT);
@@ -2823,8 +2846,10 @@ process_inode(
 			type = DBM_RTSUM;
 			blkmap = blkmap_alloc(xino.i_d.di_nextents);
 			addlink_inode(id);
-		}
-		else if (id->ino == mp->m_sb.sb_uquotino ||
+		} else if (id->ino == mp->m_sb.sb_rrmapino) {
+			type = DBM_BTRTRMAP;
+			addlink_inode(id);
+		} else if (id->ino == mp->m_sb.sb_uquotino ||
 			 id->ino == mp->m_sb.sb_gquotino ||
 			 id->ino == mp->m_sb.sb_pquotino) {
 			type = DBM_QUOTA;
@@ -2861,6 +2886,9 @@ process_inode(
 		process_btinode(id, dip, type, &totdblocks, &totiblocks,
 			&nextents, &blkmap, XFS_DATA_FORK);
 		break;
+	case XFS_DINODE_FMT_RMAP:
+		process_rtrmap(id, dip, &totiblocks);
+		break;
 	}
 	if (XFS_DFORK_Q(dip)) {
 		sbversion |= XFS_SB_VERSION_ATTRBIT;
@@ -3604,6 +3632,71 @@ process_rtsummary(
 	}
 }
 
+static void
+process_rtrmap(
+	struct inodata		*id,
+	struct xfs_dinode	*dip,
+	xfs_rfsblock_t		*toti)
+{
+	xfs_extnum_t		nex = 0;
+	xfs_rfsblock_t		totd = 0;
+	struct xfs_rtrmap_root	*dib;
+	int			whichfork = XFS_DATA_FORK;
+	int			i;
+	xfs_rtrmap_ptr_t	*pp;
+
+	dib = (struct xfs_rtrmap_root *)XFS_DFORK_PTR(dip, whichfork);
+	if (be16_to_cpu(dib->bb_level) >= mp->m_rtrmap_maxlevels) {
+		if (!sflag || id->ilist)
+			dbprintf(_("level for ino %lld rtrmap root too "
+				 "large (%u)\n"),
+				id->ino,
+				be16_to_cpu(dib->bb_level));
+		error++;
+		return;
+	}
+	if (be16_to_cpu(dib->bb_numrecs) > libxfs_rtrmapbt_maxrecs(mp,
+			XFS_DFORK_SIZE(dip, mp, whichfork),
+			be16_to_cpu(dib->bb_level) == 0)) {
+		if (!sflag || id->ilist)
+			dbprintf(_("numrecs for ino %lld rtrmap root too "
+				 "large (%u)\n"),
+				id->ino,
+				be16_to_cpu(dib->bb_numrecs));
+		error++;
+		return;
+	}
+	if (be16_to_cpu(dib->bb_level) == 0) {
+		struct xfs_rtrmap_rec	*rp;
+		xfs_fsblock_t		lastblock;
+
+		rp = XFS_RTRMAP_ROOT_REC_ADDR(dib, 1);
+		lastblock = 0;
+		for (i = 0; i < be16_to_cpu(dib->bb_numrecs); i++) {
+			if (be64_to_cpu(rp[i].rm_startblock) < lastblock) {
+				dbprintf(_(
+		"out-of-order rtrmap btree record %d (%u %u) root\n"),
+					 i, be64_to_cpu(rp[i].rm_startblock),
+					 be32_to_cpu(rp[i].rm_startblock));
+			} else {
+				lastblock = be64_to_cpu(rp[i].rm_startblock) +
+					    be64_to_cpu(rp[i].rm_blockcount);
+			}
+		}
+		return;
+	} else {
+		pp = XFS_RTRMAP_ROOT_PTR_ADDR(dib, 1,
+				libxfs_rtrmapbt_maxrecs(mp,
+					XFS_DFORK_SIZE(dip, mp, whichfork), 0));
+		for (i = 0; i < be16_to_cpu(dib->bb_numrecs); i++)
+			scan_lbtree(get_unaligned_be64(&pp[i]),
+					be16_to_cpu(dib->bb_level),
+					scanfunc_rtrmap, DBM_BTRTRMAP,
+					id, &totd, toti,
+					&nex, NULL, 1, TYP_RTRMAPBT);
+	}
+}
+
 static xfs_ino_t
 process_sf_dir_v2(
 	xfs_dinode_t		*dip,
@@ -4691,6 +4784,86 @@ scanfunc_rmap(
 }
 
 static void
+scanfunc_rtrmap(
+	struct xfs_btree_block	*block,
+	int			level,
+	dbm_t			type,
+	xfs_fsblock_t		bno,
+	inodata_t		*id,
+	xfs_rfsblock_t		*totd,
+	xfs_rfsblock_t		*toti,
+	xfs_extnum_t		*nex,
+	blkmap_t		**blkmapp,
+	int			isroot,
+	typnm_t			btype)
+{
+	xfs_agblock_t		agbno;
+	xfs_agnumber_t		agno;
+	int			i;
+	xfs_rtrmap_ptr_t	*pp;
+	struct xfs_rtrmap_rec	*rp;
+	xfs_fsblock_t		lastblock;
+
+	agno = XFS_FSB_TO_AGNO(mp, bno);
+	agbno = XFS_FSB_TO_AGBNO(mp, bno);
+	if (be32_to_cpu(block->bb_magic) != XFS_RTRMAP_CRC_MAGIC) {
+		dbprintf(_("bad magic # %#x in rtrmapbt block %u/%u\n"),
+			be32_to_cpu(block->bb_magic), agno, bno);
+		serious_error++;
+		return;
+	}
+	if (be16_to_cpu(block->bb_level) != level) {
+		if (!sflag)
+			dbprintf(_("expected level %d got %d in rtrmapbt block "
+				 "%u/%u\n"),
+				level, be16_to_cpu(block->bb_level), agno, bno);
+		error++;
+	}
+	set_dbmap(agno, bno, 1, type, agno, bno);
+	set_inomap(agno, agbno, 1, id);
+	(*toti)++;
+	if (level == 0) {
+		if (be16_to_cpu(block->bb_numrecs) > mp->m_rtrmap_mxr[0] ||
+		    (isroot == 0 && be16_to_cpu(block->bb_numrecs) < mp->m_rtrmap_mnr[0])) {
+			dbprintf(_("bad btree nrecs (%u, min=%u, max=%u) in "
+				 "rtrmapbt block %u/%u\n"),
+				be16_to_cpu(block->bb_numrecs), mp->m_rtrmap_mnr[0],
+				mp->m_rtrmap_mxr[0], agno, bno);
+			serious_error++;
+			return;
+		}
+		rp = XFS_RTRMAP_REC_ADDR(block, 1);
+		lastblock = 0;
+		for (i = 0; i < be16_to_cpu(block->bb_numrecs); i++) {
+			if (be64_to_cpu(rp[i].rm_startblock) < lastblock) {
+				dbprintf(_(
+		"out-of-order rtrmap btree record %d (%u %u) block %u/%u l %llu\n"),
+					 i, be64_to_cpu(rp[i].rm_startblock),
+					 be64_to_cpu(rp[i].rm_blockcount),
+					 agno, bno, lastblock);
+			} else {
+				lastblock = be64_to_cpu(rp[i].rm_startblock) +
+					    be64_to_cpu(rp[i].rm_blockcount);
+			}
+		}
+		return;
+	}
+	if (be16_to_cpu(block->bb_numrecs) > mp->m_rtrmap_mxr[1] ||
+	    (isroot == 0 && be16_to_cpu(block->bb_numrecs) < mp->m_rtrmap_mnr[1])) {
+		dbprintf(_("bad btree nrecs (%u, min=%u, max=%u) in rtrmapbt "
+			 "block %u/%u\n"),
+			be16_to_cpu(block->bb_numrecs), mp->m_rtrmap_mnr[1],
+			mp->m_rtrmap_mxr[1], agno, bno);
+		serious_error++;
+		return;
+	}
+	pp = XFS_RTRMAP_PTR_ADDR(block, 1, mp->m_rtrmap_mxr[1]);
+	for (i = 0; i < be16_to_cpu(block->bb_numrecs); i++)
+		scan_lbtree(be64_to_cpu(pp[i]), level, scanfunc_rtrmap, type, id,
+					totd, toti, nex, blkmapp, 0, btype);
+}
+
+static void
 scanfunc_refcnt(
 	struct xfs_btree_block	*block,
 	int			level,

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 18/29] xfs_db: copy the realtime rmap btree
  2016-08-25 23:58 [PATCH v8 00/29] xfsprogs: add realtime reverse-mapping support Darrick J. Wong
                   ` (16 preceding siblings ...)
  2016-08-26  0:00 ` [PATCH 17/29] xfs_db: support rudimentary checks of the rtrmap btree Darrick J. Wong
@ 2016-08-26  0:00 ` Darrick J. Wong
  2016-08-26  0:00 ` [PATCH 19/29] xfs_db: make fsmap query the realtime reverse mapping tree Darrick J. Wong
                   ` (10 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: Darrick J. Wong @ 2016-08-26  0:00 UTC (permalink / raw)
  To: david, darrick.wong; +Cc: linux-xfs, xfs

Copy the realtime rmapbt when we're metadumping the filesystem.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 db/metadump.c |  124 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 124 insertions(+)


diff --git a/db/metadump.c b/db/metadump.c
index ab64fbd..34f5f47 100644
--- a/db/metadump.c
+++ b/db/metadump.c
@@ -616,6 +616,54 @@ copy_rmap_btree(
 }
 
 static int
+scanfunc_rtrmapbt(
+	struct xfs_btree_block	*block,
+	xfs_agnumber_t		agno,
+	xfs_agblock_t		agbno,
+	int			level,
+	typnm_t			btype,
+	void			*arg)
+{
+	xfs_rtrmap_ptr_t	*pp;
+	int			i;
+	int			numrecs;
+
+	if (level == 0)
+		return 1;
+
+	numrecs = be16_to_cpu(block->bb_numrecs);
+	if (numrecs > mp->m_rtrmap_mxr[1]) {
+		if (show_warnings)
+			print_warning("invalid numrecs (%u) in %s block %u/%u",
+				numrecs, typtab[btype].name, agno, agbno);
+		return 1;
+	}
+
+	pp = XFS_RTRMAP_PTR_ADDR(block, 1, mp->m_rtrmap_mxr[1]);
+	for (i = 0; i < numrecs; i++) {
+		xfs_agnumber_t	pagno;
+		xfs_agblock_t	pbno;
+
+		pagno = XFS_FSB_TO_AGNO(mp, get_unaligned_be64(&pp[i]));
+		pbno = XFS_FSB_TO_AGBNO(mp, get_unaligned_be64(&pp[i]));
+
+		if (pbno == 0 || pbno > mp->m_sb.sb_agblocks ||
+		    pagno > mp->m_sb.sb_agcount) {
+			if (show_warnings)
+				print_warning("invalid block number (%u/%u) "
+						"in inode %llu %s block %u/%u",
+						pagno, pbno, (long long)cur_ino,
+						typtab[btype].name, agno, agbno);
+			continue;
+		}
+		if (!scan_btree(pagno, pbno, level, btype, arg,
+				scanfunc_rtrmapbt))
+			return 0;
+	}
+	return 1;
+}
+
+static int
 scanfunc_refcntbt(
 	struct xfs_btree_block	*block,
 	xfs_agnumber_t		agno,
@@ -2152,6 +2200,79 @@ process_exinode(
 }
 
 static int
+process_rtrmap(
+	struct xfs_dinode	*dip,
+	typnm_t			itype)
+{
+	struct xfs_rtrmap_root	*dib;
+	int			i;
+	xfs_rtrmap_ptr_t	*pp;
+	int			level;
+	int			nrecs;
+	int			maxrecs;
+	int			whichfork;
+	typnm_t			btype;
+
+	if (itype == TYP_ATTR && show_warnings) {
+		print_warning("ignoring rtrmapbt root in inode %llu attr fork",
+				(long long)cur_ino);
+		return 1;
+	}
+
+	whichfork = XFS_DATA_FORK;
+	btype = TYP_RTRMAPBT;
+
+	dib = (struct xfs_rtrmap_root *)XFS_DFORK_PTR(dip, whichfork);
+	level = be16_to_cpu(dib->bb_level);
+	nrecs = be16_to_cpu(dib->bb_numrecs);
+
+	if (level > mp->m_rtrmap_maxlevels) {
+		if (show_warnings)
+			print_warning("invalid level (%u) in inode %lld %s "
+					"root", level, (long long)cur_ino,
+					typtab[btype].name);
+		return 1;
+	}
+
+	if (level == 0)
+		return 1;
+
+	maxrecs = libxfs_rtrmapbt_maxrecs(mp,
+			XFS_DFORK_SIZE(dip, mp, whichfork), 0);
+	if (nrecs > maxrecs) {
+		if (show_warnings)
+			print_warning("invalid numrecs (%u) in inode %lld %s "
+					"root", nrecs, (long long)cur_ino,
+					typtab[btype].name);
+		return 1;
+	}
+
+	pp = XFS_RTRMAP_ROOT_PTR_ADDR(dib, 1, maxrecs);
+	for (i = 0; i < nrecs; i++) {
+		xfs_agnumber_t	ag;
+		xfs_agblock_t	bno;
+
+		ag = XFS_FSB_TO_AGNO(mp, get_unaligned_be64(&pp[i]));
+		bno = XFS_FSB_TO_AGBNO(mp, get_unaligned_be64(&pp[i]));
+
+		if (bno == 0 || bno > mp->m_sb.sb_agblocks ||
+				ag > mp->m_sb.sb_agcount) {
+			if (show_warnings)
+				print_warning("invalid block number (%u/%u) "
+						"in inode %llu %s root", ag,
+						bno, (long long)cur_ino,
+						typtab[btype].name);
+			continue;
+		}
+
+		if (!scan_btree(ag, bno, level, btype, &itype,
+				scanfunc_rtrmapbt))
+			return 0;
+	}
+	return 1;
+}
+
+static int
 process_inode_data(
 	xfs_dinode_t		*dip,
 	typnm_t			itype)
@@ -2177,6 +2298,9 @@ process_inode_data(
 
 		case XFS_DINODE_FMT_BTREE:
 			return process_btinode(dip, itype);
+
+		case XFS_DINODE_FMT_RMAP:
+			return process_rtrmap(dip, itype);
 	}
 	return 1;
 }

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 19/29] xfs_db: make fsmap query the realtime reverse mapping tree
  2016-08-25 23:58 [PATCH v8 00/29] xfsprogs: add realtime reverse-mapping support Darrick J. Wong
                   ` (17 preceding siblings ...)
  2016-08-26  0:00 ` [PATCH 18/29] xfs_db: copy the realtime rmap btree Darrick J. Wong
@ 2016-08-26  0:00 ` Darrick J. Wong
  2016-08-26  0:00 ` [PATCH 20/29] xfs_io: scrub the realtime rmap Darrick J. Wong
                   ` (9 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: Darrick J. Wong @ 2016-08-26  0:00 UTC (permalink / raw)
  To: david, darrick.wong; +Cc: linux-xfs, xfs

Extend the 'fsmap' debugger command to support querying the realtime
rmap btree via a new -r argument.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 db/fsmap.c               |   70 +++++++++++++++++++++++++++++++++++++++++++---
 libxfs/libxfs_api_defs.h |    1 +
 2 files changed, 67 insertions(+), 4 deletions(-)


diff --git a/db/fsmap.c b/db/fsmap.c
index a25461e..bb08421 100644
--- a/db/fsmap.c
+++ b/db/fsmap.c
@@ -36,8 +36,8 @@ fsmap_fn(
 {
 	struct fsmap_info	*info = priv;
 
-	dbprintf(_("%llu: %u/%u len %u owner %lld offset %llu bmbt %d attrfork %d extflag %d\n"),
-		info->nr, info->agno, rec->rm_startblock,
+	dbprintf(_("%llu: %d/%llu len %llu owner %lld offset %llu bmbt %d attrfork %d extflag %d\n"),
+		info->nr, (signed)info->agno, rec->rm_startblock,
 		rec->rm_blockcount, rec->rm_owner, rec->rm_offset,
 		!!(rec->rm_flags & XFS_RMAP_BMBT_BLOCK),
 		!!(rec->rm_flags & XFS_RMAP_ATTR_FORK),
@@ -113,6 +113,61 @@ fsmap(
 	}
 }
 
+static void
+fsmap_rt(
+	xfs_fsblock_t		start_fsb,
+	xfs_fsblock_t		end_fsb)
+{
+	struct fsmap_info	info;
+	xfs_daddr_t		eofs;
+	struct xfs_rmap_irec	low;
+	struct xfs_rmap_irec	high;
+	struct xfs_btree_cur	*bt_cur;
+	struct xfs_inode	*ip;
+	int			error;
+
+	if (mp->m_sb.sb_rblocks == 0)
+		return;
+
+	eofs = XFS_FSB_TO_BB(mp, mp->m_sb.sb_rblocks);
+	if (XFS_FSB_TO_DADDR(mp, end_fsb) >= eofs)
+		end_fsb = XFS_DADDR_TO_FSB(mp, eofs - 1);
+
+	low.rm_startblock = start_fsb;
+	low.rm_owner = 0;
+	low.rm_offset = 0;
+	low.rm_flags = 0;
+	high.rm_startblock = end_fsb;
+	high.rm_owner = ULLONG_MAX;
+	high.rm_offset = ULLONG_MAX;
+	high.rm_flags = XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK |
+			XFS_RMAP_UNWRITTEN;
+
+	info.nr = 0;
+
+	error = -libxfs_iget(mp, NULL, mp->m_sb.sb_rrmapino, 0, &ip, 0);
+	if (error) {
+		dbprintf(_("%d - couldn't iget rtrmap inode.\n"),
+			 error);
+		return;
+	}
+
+	bt_cur = libxfs_rtrmapbt_init_cursor(mp, NULL, ip);
+	if (!bt_cur)
+		goto out_ino;
+
+	info.agno = NULLAGNUMBER;
+	error = -libxfs_rmap_query_range(bt_cur, &low, &high,
+			fsmap_fn, &info);
+	if (error)
+		dbprintf(_("Error %d while querying fsmap btree.\n"),
+			error);
+
+	libxfs_btree_del_cursor(bt_cur, XFS_BTREE_NOERROR);
+out_ino:
+	IRELE(ip);
+}
+
 int
 fsmap_f(
 	int			argc,
@@ -122,14 +177,18 @@ fsmap_f(
 	int			c;
 	xfs_fsblock_t		start_fsb = 0;
 	xfs_fsblock_t		end_fsb = NULLFSBLOCK;
+	bool			is_rt = false;
 
 	if (!xfs_sb_version_hasrmapbt(&mp->m_sb)) {
 		dbprintf(_("Filesystem does not support reverse mapping btree.\n"));
 		return 0;
 	}
 
-	while ((c = getopt(argc, argv, "")) != EOF) {
+	while ((c = getopt(argc, argv, "r")) != EOF) {
 		switch (c) {
+		case 'r':
+			is_rt = true;
+			break;
 		default:
 			dbprintf(_("Bad option for fsmap command.\n"));
 			return 0;
@@ -152,7 +211,10 @@ fsmap_f(
 		}
 	}
 
-	fsmap(start_fsb, end_fsb);
+	if (is_rt)
+		fsmap_rt(start_fsb, end_fsb);
+	else
+		fsmap(start_fsb, end_fsb);
 
 	return 0;
 }
diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h
index c66e31b..a6ea865 100644
--- a/libxfs/libxfs_api_defs.h
+++ b/libxfs/libxfs_api_defs.h
@@ -143,5 +143,6 @@
 #define xfs_rmap_lookup_le_range	libxfs_rmap_lookup_le_range
 #define xfs_refc_block			libxfs_refc_block
 #define xfs_rtrmapbt_maxrecs		libxfs_rtrmapbt_maxrecs
+#define xfs_rtrmapbt_init_cursor	libxfs_rtrmapbt_init_cursor
 
 #endif /* __LIBXFS_API_DEFS_H__ */

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 20/29] xfs_io: scrub the realtime rmap
  2016-08-25 23:58 [PATCH v8 00/29] xfsprogs: add realtime reverse-mapping support Darrick J. Wong
                   ` (18 preceding siblings ...)
  2016-08-26  0:00 ` [PATCH 19/29] xfs_db: make fsmap query the realtime reverse mapping tree Darrick J. Wong
@ 2016-08-26  0:00 ` Darrick J. Wong
  2016-08-26  0:00 ` [PATCH 21/29] xfs_repair: factor rrmapino into superblock size calculations Darrick J. Wong
                   ` (8 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: Darrick J. Wong @ 2016-08-26  0:00 UTC (permalink / raw)
  To: david, darrick.wong; +Cc: linux-xfs, xfs

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 io/scrub.c |    1 +
 1 file changed, 1 insertion(+)


diff --git a/io/scrub.c b/io/scrub.c
index 8b93121..82825de 100644
--- a/io/scrub.c
+++ b/io/scrub.c
@@ -49,6 +49,7 @@ static const struct scrub_descr scrubbers[] = {
 	{"bmapbtc",	false},
 	{"rtbitmap",	false},
 	{"rtsummary",	false},
+	{"rtrmapbt",	false},
 	{NULL, false},
 };
 

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 21/29] xfs_repair: factor rrmapino into superblock size calculations
  2016-08-25 23:58 [PATCH v8 00/29] xfsprogs: add realtime reverse-mapping support Darrick J. Wong
                   ` (19 preceding siblings ...)
  2016-08-26  0:00 ` [PATCH 20/29] xfs_io: scrub the realtime rmap Darrick J. Wong
@ 2016-08-26  0:00 ` Darrick J. Wong
  2016-08-26  0:00 ` [PATCH 22/29] xfs_repair: pass private data pointer to scan_lbtree Darrick J. Wong
                   ` (7 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: Darrick J. Wong @ 2016-08-26  0:00 UTC (permalink / raw)
  To: david, darrick.wong; +Cc: linux-xfs, xfs

Now that we've extended the superblock with a field for the rtrmapbt
inode, we must adjust the superblock size calculation to include it.
This way, repair won't complain about the non-zero contents of
rrmapino.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 repair/agheader.c |    5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)


diff --git a/repair/agheader.c b/repair/agheader.c
index cce376f..8eb7f80 100644
--- a/repair/agheader.c
+++ b/repair/agheader.c
@@ -270,7 +270,10 @@ secondary_sb_whack(
 	 *
 	 * size is the size of data which is valid for this sb.
 	 */
-	if (xfs_sb_version_hasmetauuid(sb))
+	if (xfs_sb_version_hasrmapbt(sb) && mp->m_sb.sb_rblocks > 0)
+		size = offsetof(struct xfs_sb, sb_rrmapino)
+			+ sizeof(sb->sb_rrmapino);
+	else if (xfs_sb_version_hasmetauuid(sb))
 		size = offsetof(xfs_sb_t, sb_meta_uuid)
 			+ sizeof(sb->sb_meta_uuid);
 	else if (xfs_sb_version_hascrc(sb))

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 22/29] xfs_repair: pass private data pointer to scan_lbtree
  2016-08-25 23:58 [PATCH v8 00/29] xfsprogs: add realtime reverse-mapping support Darrick J. Wong
                   ` (20 preceding siblings ...)
  2016-08-26  0:00 ` [PATCH 21/29] xfs_repair: factor rrmapino into superblock size calculations Darrick J. Wong
@ 2016-08-26  0:00 ` Darrick J. Wong
  2016-08-26  0:01 ` [PATCH 23/29] xfs_repair: use realtime rmap btree data to check block types Darrick J. Wong
                   ` (6 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: Darrick J. Wong @ 2016-08-26  0:00 UTC (permalink / raw)
  To: david, darrick.wong; +Cc: linux-xfs, xfs

Pass a private data pointer through scan_lbtree.  We'll use this
later when scanning the rtrmapbt to keep track of scan state.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 repair/dinode.c |    2 +-
 repair/scan.c   |   11 +++++++----
 repair/scan.h   |    7 +++++--
 3 files changed, 13 insertions(+), 7 deletions(-)


diff --git a/repair/dinode.c b/repair/dinode.c
index 11b60ce..843c465 100644
--- a/repair/dinode.c
+++ b/repair/dinode.c
@@ -1007,7 +1007,7 @@ _("bad bmap btree ptr 0x%" PRIx64 " in ino %" PRIu64 "\n"),
 
 		if (scan_lbtree(get_unaligned_be64(&pp[i]), level, scan_bmapbt,
 				type, whichfork, lino, tot, nex, blkmapp,
-				&cursor, 1, check_dups, magic,
+				&cursor, 1, check_dups, magic, NULL,
 				&xfs_bmbt_buf_ops))
 			return(1);
 		/*
diff --git a/repair/scan.c b/repair/scan.c
index f4d6f89..8935be7 100644
--- a/repair/scan.c
+++ b/repair/scan.c
@@ -116,7 +116,8 @@ scan_lbtree(
 				int			isroot,
 				int			check_dups,
 				int			*dirty,
-				__uint64_t		magic),
+				__uint64_t		magic,
+				void			*priv),
 	int		type,
 	int		whichfork,
 	xfs_ino_t	ino,
@@ -127,6 +128,7 @@ scan_lbtree(
 	int		isroot,
 	int		check_dups,
 	__uint64_t	magic,
+	void		*priv,
 	const struct xfs_buf_ops *ops)
 {
 	xfs_buf_t	*bp;
@@ -158,7 +160,7 @@ scan_lbtree(
 	err = (*func)(XFS_BUF_TO_BLOCK(bp), nlevels - 1,
 			type, whichfork, root, ino, tot, nex, blkmapp,
 			bm_cursor, isroot, check_dups, &dirty,
-			magic);
+			magic, priv);
 
 	ASSERT(dirty == 0 || (dirty && !no_modify));
 
@@ -185,7 +187,8 @@ scan_bmapbt(
 	int			isroot,
 	int			check_dups,
 	int			*dirty,
-	__uint64_t		magic)
+	__uint64_t		magic,
+	void			*priv)
 {
 	int			i;
 	int			err;
@@ -469,7 +472,7 @@ _("bad bmap btree ptr 0x%llx in ino %" PRIu64 "\n"),
 
 		err = scan_lbtree(be64_to_cpu(pp[i]), level, scan_bmapbt,
 				type, whichfork, ino, tot, nex, blkmapp,
-				bm_cursor, 0, check_dups, magic,
+				bm_cursor, 0, check_dups, magic, priv,
 				&xfs_bmbt_buf_ops);
 		if (err)
 			return(1);
diff --git a/repair/scan.h b/repair/scan.h
index ea8c0bf..854897c 100644
--- a/repair/scan.h
+++ b/repair/scan.h
@@ -36,7 +36,8 @@ int scan_lbtree(
 				int			isroot,
 				int			check_dups,
 				int			*dirty,
-				__uint64_t		magic),
+				__uint64_t		magic,
+				void			*priv),
 	int		type,
 	int		whichfork,
 	xfs_ino_t	ino,
@@ -47,6 +48,7 @@ int scan_lbtree(
 	int		isroot,
 	int		check_dups,
 	__uint64_t	magic,
+	void		*priv,
 	const struct xfs_buf_ops *ops);
 
 int scan_bmapbt(
@@ -63,7 +65,8 @@ int scan_bmapbt(
 	int			isroot,
 	int			check_dups,
 	int			*dirty,
-	__uint64_t		magic);
+	__uint64_t		magic,
+	void			*priv);
 
 void
 scan_ags(

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 23/29] xfs_repair: use realtime rmap btree data to check block types
  2016-08-25 23:58 [PATCH v8 00/29] xfsprogs: add realtime reverse-mapping support Darrick J. Wong
                   ` (21 preceding siblings ...)
  2016-08-26  0:00 ` [PATCH 22/29] xfs_repair: pass private data pointer to scan_lbtree Darrick J. Wong
@ 2016-08-26  0:01 ` Darrick J. Wong
  2016-08-26  0:01 ` [PATCH 24/29] xfs_repair: extend ag_rmap[] for realtime mapping collection Darrick J. Wong
                   ` (5 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: Darrick J. Wong @ 2016-08-26  0:01 UTC (permalink / raw)
  To: david, darrick.wong; +Cc: linux-xfs, xfs

Use the realtime rmap btree to pre-populate the block type information
so that when repair iterates the primary metadata, we can confirm the
block type.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 repair/dinode.c |  170 +++++++++++++++++++++++-
 repair/dinode.h |    2 
 repair/scan.c   |  391 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 repair/scan.h   |   33 +++++
 4 files changed, 583 insertions(+), 13 deletions(-)


diff --git a/repair/dinode.c b/repair/dinode.c
index 843c465..6718cd2 100644
--- a/repair/dinode.c
+++ b/repair/dinode.c
@@ -423,6 +423,18 @@ verify_agbno(xfs_mount_t	*mp,
 	return verify_ag_bno(sbp, agno, agbno) == 0;
 }
 
+/*
+ * Verify realtime device block number.
+ * Returns 1 for good rtfsb or 0 if it's invalid.
+ */
+int
+verify_drtbno(
+	struct xfs_mount	*mp,
+	xfs_fsblock_t		fsb)
+{
+	return fsb < mp->m_sb.sb_rblocks;
+}
+
 static int
 process_rt_rec(
 	xfs_mount_t		*mp,
@@ -439,7 +451,7 @@ process_rt_rec(
 	/*
 	 * check numeric validity of the extent
 	 */
-	if (irec->br_startblock >= mp->m_sb.sb_rblocks) {
+	if (!verify_drtbno(mp, irec->br_startblock)) {
 		do_warn(
 _("inode %" PRIu64 " - bad rt extent start block number %" PRIu64 ", offset %" PRIu64 "\n"),
 			ino,
@@ -447,7 +459,7 @@ _("inode %" PRIu64 " - bad rt extent start block number %" PRIu64 ", offset %" P
 			irec->br_startoff);
 		return 1;
 	}
-	if (irec->br_startblock + irec->br_blockcount - 1 >= mp->m_sb.sb_rblocks) {
+	if (!verify_drtbno(mp, irec->br_startblock + irec->br_blockcount)) {
 		do_warn(
 _("inode %" PRIu64 " - bad rt extent last block number %" PRIu64 ", offset %" PRIu64 "\n"),
 			ino,
@@ -917,6 +929,145 @@ get_agino_buf(
  * return 1 if inode should be cleared, 0 otherwise
  */
 static int
+process_rtrmap(
+	struct xfs_mount	*mp,
+	xfs_agnumber_t		agno,
+	xfs_agino_t		ino,
+	struct xfs_dinode	*dip,
+	int			type,
+	int			*dirty,
+	xfs_rfsblock_t		*tot,
+	__uint64_t		*nex,
+	blkmap_t		**blkmapp,
+	int			check_dups)
+{
+	struct xfs_rtrmap_root	*dib;
+	xfs_ino_t		lino;
+	xfs_rtrmap_ptr_t	*pp;
+	struct xfs_rtrmap_key	*kp;
+	struct xfs_rtrmap_rec	*rp;
+	int			whichfork = XFS_DATA_FORK;
+	char			*forkname = get_forkname(whichfork);
+	int			i;
+	int			level;
+	int			numrecs;
+	xfs_fsblock_t		bno;
+	struct xfs_rmap_irec	oldkey;
+	struct xfs_rmap_irec	key;
+	struct rmap_priv	priv;
+	int			suspect = 0;
+	int			error;
+
+	/* We rebuild the rtrmapbt, so no need to process blocks again. */
+	if (check_dups) {
+		*tot = be64_to_cpu(dip->di_nblocks);
+		return 0;
+	}
+
+	memset(&priv.high_key, 0xFF, sizeof(priv.high_key));
+	priv.high_key.rm_blockcount = 0;
+	priv.agcnts = NULL;
+	priv.last_rec.rm_owner = XFS_RMAP_OWN_UNKNOWN;
+
+	dib = (struct xfs_rtrmap_root *)XFS_DFORK_PTR(dip, whichfork);
+	lino = XFS_AGINO_TO_INO(mp, agno, ino);
+	*tot = 0;
+	*nex = 0;
+
+	level = be16_to_cpu(dib->bb_level);
+	numrecs = be16_to_cpu(dib->bb_numrecs);
+
+	if (level > mp->m_rtrmap_maxlevels) {
+		do_warn(
+_("bad level %d in inode %" PRIu64 " rtrmap btree root block\n"),
+			level, lino);
+		return 1;
+	}
+
+	/*
+	 * use rtroot/dfork_dsize since the root block is in the data fork
+	 */
+	if (XFS_RTRMAP_ROOT_SPACE_CALC(numrecs, level) >
+	    XFS_DFORK_SIZE(dip, mp, whichfork)) {
+		do_warn(
+_("indicated size of %s rtrmapbt root (%d bytes) greater than space in "
+	  "inode %" PRIu64 " %s fork\n"),
+			forkname, XFS_RTRMAP_ROOT_SPACE_CALC(numrecs, level),
+			lino, forkname);
+		return 1;
+	}
+
+	if (level == 0) {
+		rp = XFS_RTRMAP_ROOT_REC_ADDR(dib, 1);
+		error = process_rtrmap_reclist(mp, rp, numrecs,
+				&priv.last_rec, NULL, "rtrmapbt root");
+		if (error) {
+			rmap_avoid_check();
+			return 1;
+		}
+		return 0;
+	}
+
+	pp = XFS_RTRMAP_ROOT_PTR_ADDR(dib, 1,
+			libxfs_rtrmapbt_maxrecs(mp,
+				XFS_DFORK_SIZE(dip, mp, whichfork), 0));
+
+	/* check for in-order keys */
+	for (i = 0; i < numrecs; i++)  {
+		kp = XFS_RTRMAP_ROOT_KEY_ADDR(dib, i + 1);
+
+		key.rm_flags = 0;
+		key.rm_startblock = be64_to_cpu(kp->rm_startblock);
+		key.rm_owner = be64_to_cpu(kp->rm_owner);
+		if (libxfs_rmap_irec_offset_unpack(be64_to_cpu(kp->rm_offset),
+				&key)) {
+			/* Look for impossible flags. */
+			do_warn(
+_("invalid flags in key %u of rtrmap root ino %" PRIu64 "\n"),
+				i, lino);
+			suspect++;
+			continue;
+		}
+		if (i == 0) {
+			oldkey = key;
+			continue;
+		}
+		if (rmap_diffkeys(&oldkey, &key) > 0) {
+			do_warn(
+_("out of order key %u in rtrmap root ino %" PRIu64 "\n"),
+				i, lino);
+			suspect++;
+			continue;
+		}
+		oldkey = key;
+	}
+
+	/* probe keys */
+	for (i = 0; i < numrecs; i++)  {
+		bno = get_unaligned_be64(&pp[i]);
+
+		if (!verify_dfsbno(mp, bno))  {
+			do_warn(
+_("bad rtrmap btree ptr 0x%" PRIx64 " in ino %" PRIu64 "\n"),
+				bno, lino);
+			return 1;
+		}
+
+		if (scan_lbtree(bno, level, scan_rtrmapbt,
+				type, whichfork, lino, tot, nex, blkmapp,
+				NULL, 1, check_dups, XFS_RTRMAP_CRC_MAGIC,
+				&priv,
+				&xfs_rtrmapbt_buf_ops))
+			return 1;
+	}
+
+	return suspect ? 1 : 0;
+}
+
+/*
+ * return 1 if inode should be cleared, 0 otherwise
+ */
+static int
 process_btinode(
 	xfs_mount_t		*mp,
 	xfs_agnumber_t		agno,
@@ -1545,9 +1696,13 @@ change_dinode_fmt(
 
 static int
 check_dinode_mode_format(
-	xfs_dinode_t *dinoc)
+	struct xfs_mount	*mp,
+	xfs_ino_t		lino,
+	struct xfs_dinode	*dinoc)
 {
-	if (dinoc->di_format >= XFS_DINODE_FMT_UUID)
+	if (lino == mp->m_sb.sb_rrmapino)
+		return dinoc->di_format != XFS_DINODE_FMT_RMAP;
+	else if (dinoc->di_format >= XFS_DINODE_FMT_UUID)
 		return -1;	/* FMT_UUID is not used */
 
 	switch (dinode_fmt(dinoc)) {
@@ -1947,6 +2102,10 @@ process_inode_data_fork(
 			totblocks, nextents, dblkmap, XFS_DATA_FORK,
 			check_dups);
 		break;
+	case XFS_DINODE_FMT_RMAP:
+		err = process_rtrmap(mp, agno, ino, dino, type, dirty,
+			totblocks, nextents, dblkmap, check_dups);
+		break;
 	case XFS_DINODE_FMT_DEV:	/* fall through */
 		err = 0;
 		break;
@@ -1986,6 +2145,7 @@ process_inode_data_fork(
 				XFS_DATA_FORK, 0);
 			break;
 		case XFS_DINODE_FMT_DEV:	/* fall through */
+		case XFS_DINODE_FMT_RMAP:
 			err = 0;
 			break;
 		default:
@@ -2395,7 +2555,7 @@ _("bad (negative) size %" PRId64 " on inode %" PRIu64 "\n"),
 	 * free inodes since technically any format is legal
 	 * as we reset the inode when we re-use it.
 	 */
-	if (di_mode != 0 && check_dinode_mode_format(dino) != 0) {
+	if (di_mode != 0 && check_dinode_mode_format(mp, lino, dino) != 0) {
 		if (!uncertain)
 			do_warn(
 	_("bad inode format in inode %" PRIu64 "\n"), lino);
diff --git a/repair/dinode.h b/repair/dinode.h
index 61d0736..70d5d91 100644
--- a/repair/dinode.h
+++ b/repair/dinode.h
@@ -30,6 +30,8 @@ int
 verify_dfsbno(xfs_mount_t	*mp,
 		xfs_fsblock_t	fsbno);
 
+int verify_drtbno(struct xfs_mount *mp, xfs_fsblock_t fsbno);
+
 void
 convert_extent(
 	xfs_bmbt_rec_t		*rp,
diff --git a/repair/scan.c b/repair/scan.c
index 8935be7..7c88b6f 100644
--- a/repair/scan.c
+++ b/repair/scan.c
@@ -824,7 +824,10 @@ process_rmap_rec(
 			break;
 		default:
 			/* file data */
-			set_bmap_ext(agno, b, blen, XR_E_INUSE1);
+			if (owner == mp->m_sb.sb_rrmapino)
+				set_bmap_ext(agno, b, blen, XR_E_FS_MAP1);
+			else
+				set_bmap_ext(agno, b, blen, XR_E_INUSE1);
 			break;
 		}
 		break;
@@ -896,13 +899,6 @@ _("unknown block (%d,%d-%d) mismatch on %s tree, state - %d,%" PRIx64 "\n"),
 	}
 }
 
-struct rmap_priv {
-	struct aghdr_cnts	*agcnts;
-	struct xfs_rmap_irec	high_key;
-	struct xfs_rmap_irec	last_rec;
-	xfs_agblock_t		nr_blocks;
-};
-
 static bool
 rmap_in_order(
 	xfs_agblock_t	b,
@@ -1218,6 +1214,385 @@ out:
 		rmap_avoid_check();
 }
 
+int
+process_rtrmap_reclist(
+	struct xfs_mount	*mp,
+	struct xfs_rtrmap_rec	*rp,
+	int			numrecs,
+	struct xfs_rmap_irec	*last_rec,
+	struct xfs_rmap_irec	*high_key,
+	const char		*name)
+{
+	int			suspect = 0;
+	int			i;
+	struct xfs_rmap_irec	oldkey;
+	struct xfs_rmap_irec	key;
+
+	for (i = 0; i < numrecs; i++) {
+		xfs_fsblock_t		b, end;
+		xfs_filblks_t		len;
+		uint64_t		owner, offset;
+
+		b = be64_to_cpu(rp[i].rm_startblock);
+		len = be64_to_cpu(rp[i].rm_blockcount);
+		owner = be64_to_cpu(rp[i].rm_owner);
+		offset = be64_to_cpu(rp[i].rm_offset);
+
+		key.rm_flags = 0;
+		key.rm_startblock = b;
+		key.rm_blockcount = len;
+		key.rm_owner = owner;
+		if (libxfs_rmap_irec_offset_unpack(offset, &key)) {
+			/* Look for impossible flags. */
+			do_warn(
+_("invalid flags in record %u of %s\n"),
+				i, name);
+			suspect++;
+			continue;
+		}
+
+
+		end = key.rm_startblock + key.rm_blockcount;
+
+		/* Make sure startblock & len make sense. */
+		if (!verify_drtbno(mp, b)) {
+			do_warn(
+_("invalid start block %llu in record %u of %s\n"),
+				(unsigned long long)b, i, name);
+			suspect++;
+			continue;
+		}
+		if (len == 0 || !verify_drtbno(mp, end - 1)) {
+			do_warn(
+_("invalid length %llu in record %u of %s\n"),
+				(unsigned long long)len, i, name);
+			suspect++;
+			continue;
+		}
+
+		/* We only store inode data in the rtrmap. */
+		if (XFS_RMAP_NON_INODE_OWNER(owner)) {
+			do_warn(
+_("invalid owner %lld in record %u of %s\n"),
+				(long long int)owner, i, name);
+			suspect++;
+			continue;
+		}
+
+		/* Look for impossible record field combinations. */
+		if (key.rm_flags & XFS_RMAP_KEY_FLAGS) {
+			do_warn(
+_("record %d cannot have attr fork/key flags in %s\n"),
+					i, name);
+			suspect++;
+			continue;
+		}
+
+		/* Check for out of order records. */
+		if (i == 0)
+			oldkey = key;
+		else {
+			if (rmap_diffkeys(&oldkey, &key) > 0)
+				do_warn(
+_("out-of-order record %d (%llu %"PRId64" %"PRIu64" %llu) in %s\n"),
+				i, (unsigned long long)b, owner, offset,
+				(unsigned long long)len, name);
+			else
+				oldkey = key;
+		}
+
+		/* Is this mergeable with the previous record? */
+		if (rmaps_are_mergeable(last_rec, &key)) {
+			do_warn(
+_("record %d in %s should be merged with previous record\n"),
+				i, name);
+			last_rec->rm_blockcount += key.rm_blockcount;
+		} else
+			*last_rec = key;
+
+		/* Check that we don't go past the high key. */
+		key.rm_startblock += key.rm_blockcount - 1;
+		key.rm_offset += key.rm_blockcount - 1;
+		key.rm_blockcount = 0;
+		if (high_key && rmap_diffkeys(&key, high_key) > 0) {
+			do_warn(
+_("record %d greater than high key of %s\n"),
+				i, name);
+			suspect++;
+		}
+	}
+
+	return suspect;
+}
+
+int
+scan_rtrmapbt(
+	struct xfs_btree_block	*block,
+	int			level,
+	int			type,
+	int			whichfork,
+	xfs_fsblock_t		fsbno,
+	xfs_ino_t		ino,
+	xfs_rfsblock_t		*tot,
+	__uint64_t		*nex,
+	blkmap_t		**blkmapp,
+	bmap_cursor_t		*bm_cursor,
+	int			isroot,
+	int			check_dups,
+	int			*dirty,
+	__uint64_t		magic,
+	void			*priv)
+{
+	const char		*name = "rtrmap";
+	char			rootname[256];
+	int			i;
+	xfs_rtrmap_ptr_t	*pp;
+	struct xfs_rtrmap_rec	*rp;
+	struct rmap_priv	*rmap_priv = priv;
+	int			hdr_errors = 0;
+	int			numrecs;
+	int			state;
+	struct xfs_rtrmap_key	*kp;
+	struct xfs_rmap_irec	oldkey;
+	struct xfs_rmap_irec	key;
+	xfs_agnumber_t		agno;
+	xfs_agblock_t		agbno;
+	int			suspect = 0;
+	int			error;
+
+	agno = XFS_FSB_TO_AGNO(mp, fsbno);
+	agbno = XFS_FSB_TO_AGBNO(mp, fsbno);
+
+	/* If anything here is bad, just bail. */
+	if (be32_to_cpu(block->bb_magic) != magic) {
+		do_warn(
+_("bad magic # %#x in inode %" PRIu64 " %s block %" PRIu64 "\n"),
+			be32_to_cpu(block->bb_magic), ino, name, fsbno);
+		return 1;
+	}
+	if (be16_to_cpu(block->bb_level) != level) {
+		do_warn(
+_("expected level %d got %d in inode %" PRIu64 ", %s block %" PRIu64 "\n"),
+			level, be16_to_cpu(block->bb_level),
+			ino, name, fsbno);
+		return(1);
+	}
+
+	/* verify owner */
+	if (be64_to_cpu(block->bb_u.l.bb_owner) != ino) {
+		do_warn(
+_("expected owner inode %" PRIu64 ", got %llu, %s block %" PRIu64 "\n"),
+			ino, be64_to_cpu(block->bb_u.l.bb_owner), name, fsbno);
+		return 1;
+	}
+	/* verify block number */
+	if (be64_to_cpu(block->bb_u.l.bb_blkno) !=
+	    XFS_FSB_TO_DADDR(mp, fsbno)) {
+		do_warn(
+_("expected block %" PRIu64 ", got %llu, %s block %" PRIu64 "\n"),
+			XFS_FSB_TO_DADDR(mp, fsbno),
+			be64_to_cpu(block->bb_u.l.bb_blkno), name, fsbno);
+		return 1;
+	}
+	/* verify uuid */
+	if (platform_uuid_compare(&block->bb_u.l.bb_uuid,
+				  &mp->m_sb.sb_meta_uuid) != 0) {
+		do_warn(
+_("wrong FS UUID, %s block %" PRIu64 "\n"),
+			name, fsbno);
+		return 1;
+	}
+
+	/* check for btree blocks multiply claimed */
+	state = get_bmap(agno, agbno);
+	if (!(state == XR_E_UNKNOWN || state == XR_E_FS_MAP1))  {
+		set_bmap(agno, agbno, XR_E_MULT);
+		do_warn(
+_("%s btree block claimed (state %d), agno %d, bno %d, suspect %d\n"),
+				name, state, agno, agbno, suspect);
+		suspect++;
+		goto out;
+	}
+
+	set_bmap(agno, agbno, XR_E_FS_MAP);
+
+	numrecs = be16_to_cpu(block->bb_numrecs);
+
+	/*
+	 * All realtime rmap btree blocks are freed for a fully empty
+	 * filesystem, thus they are counted towards the free data
+	 * block counter.  The root lives in an inode and is thus not
+	 * counted.
+	 */
+	(*tot)++;
+
+	if (level == 0) {
+		if (numrecs > mp->m_rtrmap_mxr[0])  {
+			numrecs = mp->m_rtrmap_mxr[0];
+			hdr_errors++;
+		}
+		if (isroot == 0 && numrecs < mp->m_rtrmap_mnr[0])  {
+			numrecs = mp->m_rtrmap_mnr[0];
+			hdr_errors++;
+		}
+
+		if (hdr_errors) {
+			do_warn(
+_("bad btree nrecs (%u, min=%u, max=%u) in bt%s block %u/%u\n"),
+				be16_to_cpu(block->bb_numrecs),
+				mp->m_rtrmap_mnr[0], mp->m_rtrmap_mxr[0],
+				name, agno, agbno);
+			suspect++;
+		}
+
+		rp = XFS_RTRMAP_REC_ADDR(block, 1);
+		snprintf(rootname, 256, "%s btree block %u/%u", name, agno, agbno);
+		error = process_rtrmap_reclist(mp, rp, numrecs,
+				&rmap_priv->last_rec, &rmap_priv->high_key,
+				rootname);
+		if (error)
+			suspect++;
+		goto out;
+	}
+
+	/*
+	 * interior record
+	 */
+	pp = XFS_RTRMAP_PTR_ADDR(block, 1, mp->m_rtrmap_mxr[1]);
+
+	if (numrecs > mp->m_rtrmap_mxr[1])  {
+		numrecs = mp->m_rtrmap_mxr[1];
+		hdr_errors++;
+	}
+	if (isroot == 0 && numrecs < mp->m_rtrmap_mnr[1])  {
+		numrecs = mp->m_rtrmap_mnr[1];
+		hdr_errors++;
+	}
+
+	/*
+	 * don't pass bogus tree flag down further if this block
+	 * looked ok.  bail out if two levels in a row look bad.
+	 */
+	if (hdr_errors)  {
+		do_warn(
+_("bad btree nrecs (%u, min=%u, max=%u) in bt%s block %u/%u\n"),
+			be16_to_cpu(block->bb_numrecs),
+			mp->m_rtrmap_mnr[1], mp->m_rtrmap_mxr[1],
+			name, agno, agbno);
+		if (suspect)
+			goto out;
+		suspect++;
+	} else if (suspect) {
+		suspect = 0;
+	}
+
+	/* check the node's high keys */
+	for (i = 0; !isroot && i < numrecs; i++) {
+		kp = XFS_RTRMAP_HIGH_KEY_ADDR(block, i + 1);
+
+		key.rm_flags = 0;
+		key.rm_startblock = be64_to_cpu(kp->rm_startblock);
+		key.rm_owner = be64_to_cpu(kp->rm_owner);
+		if (libxfs_rmap_irec_offset_unpack(be64_to_cpu(kp->rm_offset),
+				&key)) {
+			/* Look for impossible flags. */
+			do_warn(
+_("invalid flags in key %u of %s btree block %u/%u\n"),
+				i, name, agno, agbno);
+			suspect++;
+			continue;
+		}
+		if (rmap_diffkeys(&key, &rmap_priv->high_key) > 0) {
+			do_warn(
+_("key %d greater than high key of block (%u/%u) in %s tree\n"),
+				i, agno, agbno, name);
+			suspect++;
+		}
+	}
+
+	/* check for in-order keys */
+	for (i = 0; i < numrecs; i++)  {
+		kp = XFS_RTRMAP_KEY_ADDR(block, i + 1);
+
+		key.rm_flags = 0;
+		key.rm_startblock = be64_to_cpu(kp->rm_startblock);
+		key.rm_owner = be64_to_cpu(kp->rm_owner);
+		if (libxfs_rmap_irec_offset_unpack(be64_to_cpu(kp->rm_offset),
+				&key)) {
+			/* Look for impossible flags. */
+			do_warn(
+_("invalid flags in key %u of %s btree block %u/%u\n"),
+				i, name, agno, agbno);
+			suspect++;
+			continue;
+		}
+		if (i == 0) {
+			oldkey = key;
+			continue;
+		}
+		if (rmap_diffkeys(&oldkey, &key) > 0) {
+			do_warn(
+_("out of order key %u in %s btree block (%u/%u)\n"),
+				i, name, agno, agbno);
+			suspect++;
+		}
+		oldkey = key;
+	}
+
+	for (i = 0; i < numrecs; i++)  {
+		xfs_fsblock_t		pbno = be64_to_cpu(pp[i]);
+
+		/*
+		 * XXX - put sibling detection right here.
+		 * we know our sibling chain is good.  So as we go,
+		 * we check the entry before and after each entry.
+		 * If either of the entries references a different block,
+		 * check the sibling pointer.  If there's a sibling
+		 * pointer mismatch, try and extract as much data
+		 * as possible.
+		 */
+		kp = XFS_RTRMAP_HIGH_KEY_ADDR(block, i + 1);
+		rmap_priv->high_key.rm_flags = 0;
+		rmap_priv->high_key.rm_startblock =
+				be64_to_cpu(kp->rm_startblock);
+		rmap_priv->high_key.rm_owner =
+				be64_to_cpu(kp->rm_owner);
+		if (libxfs_rmap_irec_offset_unpack(be64_to_cpu(kp->rm_offset),
+				&rmap_priv->high_key)) {
+			/* Look for impossible flags. */
+			do_warn(
+_("invalid flags in high key %u of %s btree block %u/%u\n"),
+				i, name, agno, agbno);
+			suspect++;
+			continue;
+		}
+
+		if (!verify_dfsbno(mp, pbno)) {
+			do_warn(
+_("bad %s btree ptr 0x%llx in ino %" PRIu64 "\n"),
+			       name, (unsigned long long)pbno, ino);
+			return 1;
+		}
+
+		error = scan_lbtree(pbno, level, scan_rtrmapbt,
+				type, whichfork, ino, tot, nex, blkmapp,
+				bm_cursor, 0, check_dups, magic,
+				rmap_priv,
+				&xfs_rtrmapbt_buf_ops);
+		if (error) {
+			suspect++;
+			goto out;
+		}
+	}
+
+out:
+	if (hdr_errors || suspect) {
+		rmap_avoid_check();
+		return 1;
+	}
+	return 0;
+}
+
 struct refc_priv {
 	struct xfs_refcount_irec	last_rec;
 	xfs_agblock_t			nr_blocks;
diff --git a/repair/scan.h b/repair/scan.h
index 854897c..f51f950 100644
--- a/repair/scan.h
+++ b/repair/scan.h
@@ -73,4 +73,37 @@ scan_ags(
 	struct xfs_mount	*mp,
 	int			scan_threads);
 
+struct rmap_priv {
+	struct aghdr_cnts	*agcnts;
+	struct xfs_rmap_irec	high_key;
+	struct xfs_rmap_irec	last_rec;
+	xfs_agblock_t		nr_blocks;
+};
+
+int
+process_rtrmap_reclist(
+	struct xfs_mount	*mp,
+	struct xfs_rtrmap_rec	*rp,
+	int			numrecs,
+	struct xfs_rmap_irec	*last_rec,
+	struct xfs_rmap_irec	*high_key,
+	const char		*name);
+
+int scan_rtrmapbt(
+	struct xfs_btree_block	*block,
+	int			level,
+	int			type,
+	int			whichfork,
+	xfs_fsblock_t		bno,
+	xfs_ino_t		ino,
+	xfs_rfsblock_t		*tot,
+	__uint64_t		*nex,
+	struct blkmap		**blkmapp,
+	bmap_cursor_t		*bm_cursor,
+	int			isroot,
+	int			check_dups,
+	int			*dirty,
+	__uint64_t		magic,
+	void			*priv);
+
 #endif /* _XR_SCAN_H */

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 24/29] xfs_repair: extend ag_rmap[] for realtime mapping collection
  2016-08-25 23:58 [PATCH v8 00/29] xfsprogs: add realtime reverse-mapping support Darrick J. Wong
                   ` (22 preceding siblings ...)
  2016-08-26  0:01 ` [PATCH 23/29] xfs_repair: use realtime rmap btree data to check block types Darrick J. Wong
@ 2016-08-26  0:01 ` Darrick J. Wong
  2016-08-26  0:01 ` [PATCH 25/29] xfs_repair: collect relatime reverse-mapping data for refcount/rmap tree rebuilding Darrick J. Wong
                   ` (4 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: Darrick J. Wong @ 2016-08-26  0:01 UTC (permalink / raw)
  To: david, darrick.wong; +Cc: linux-xfs, xfs

Extend the ag_rmap[] infrastructure to have an extra group to store
realtime extent reverse mappings.  Since we're pretending that the
realtime device is AG "-1", we can just play some pointer arithmetic
to make this work out.  In the next patch we'll actually use this
data for something.  Extend the ag_locks[] array in a similar manner.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 repair/dinode.c |    2 +
 repair/incore.c |    9 ++++-
 repair/phase4.c |   10 +++--
 repair/rmap.c   |  105 ++++++++++++++++++++++++++++++++++++-------------------
 repair/rmap.h   |   10 +++++
 5 files changed, 91 insertions(+), 45 deletions(-)


diff --git a/repair/dinode.c b/repair/dinode.c
index 6718cd2..f768cdf 100644
--- a/repair/dinode.c
+++ b/repair/dinode.c
@@ -801,7 +801,7 @@ _("illegal state %d in block map %" PRIu64 "\n"),
 			}
 		}
 		if (collect_rmaps) { /* && !check_dups */
-			error = rmap_add_rec(mp, ino, whichfork, &irec);
+			error = rmap_add_rec(mp, ino, whichfork, &irec, false);
 			if (error)
 				do_error(
 _("couldn't add reverse mapping\n")
diff --git a/repair/incore.c b/repair/incore.c
index cb57316..fbb05ad 100644
--- a/repair/incore.c
+++ b/repair/incore.c
@@ -294,14 +294,17 @@ init_bmaps(xfs_mount_t *mp)
 	if (!ag_bmap)
 		do_error(_("couldn't allocate block map btree roots\n"));
 
-	ag_locks = calloc(mp->m_sb.sb_agcount, sizeof(struct aglock));
+	ag_locks = calloc(mp->m_sb.sb_agcount + 1, sizeof(struct aglock));
 	if (!ag_locks)
 		do_error(_("couldn't allocate block map locks\n"));
 
+	/* One ag_lock per AG, and one more for the realtime device. */
 	for (i = 0; i < mp->m_sb.sb_agcount; i++)  {
 		btree_init(&ag_bmap[i]);
 		pthread_mutex_init(&ag_locks[i].lock, NULL);
 	}
+	pthread_mutex_init(&ag_locks[mp->m_sb.sb_agcount].lock, NULL);
+	ag_locks++;
 
 	init_rt_bmap(mp);
 	reset_bmaps(mp);
@@ -312,6 +315,10 @@ free_bmaps(xfs_mount_t *mp)
 {
 	xfs_agnumber_t i;
 
+	ag_locks--;
+	free(ag_locks);
+	ag_locks = NULL;
+
 	for (i = 0; i < mp->m_sb.sb_agcount; i++)
 		btree_destroy(ag_bmap[i]);
 	free(ag_bmap);
diff --git a/repair/phase4.c b/repair/phase4.c
index 395d373..512f774 100644
--- a/repair/phase4.c
+++ b/repair/phase4.c
@@ -158,7 +158,7 @@ process_ags(
 	int			error;
 
 	do_inode_prefetch(mp, ag_stride, process_ag_func, true, false);
-	for (i = 0; i < mp->m_sb.sb_agcount; i++) {
+	for_each_rmap_group(mp, i) {
 		error = rmap_finish_collecting_fork_recs(mp, i);
 		if (error)
 			do_error(
@@ -248,7 +248,7 @@ process_rmap_data(
 		return;
 
 	create_work_queue(&wq, mp, libxfs_nproc());
-	for (i = 0; i < mp->m_sb.sb_agcount; i++)
+	for_each_rmap_group(mp, i)
 		queue_work(&wq, check_rmap_btrees, i, NULL);
 	destroy_work_queue(&wq);
 
@@ -256,17 +256,17 @@ process_rmap_data(
 		return;
 
 	create_work_queue(&wq, mp, libxfs_nproc());
-	for (i = 0; i < mp->m_sb.sb_agcount; i++)
+	for_each_ag(mp, i)
 		queue_work(&wq, compute_ag_refcounts, i, NULL);
 	destroy_work_queue(&wq);
 
 	create_work_queue(&wq, mp, libxfs_nproc());
-	for (i = 0; i < mp->m_sb.sb_agcount; i++)
+	for_each_ag(mp, i)
 		queue_work(&wq, process_inode_reflink_flags, i, NULL);
 	destroy_work_queue(&wq);
 
 	create_work_queue(&wq, mp, libxfs_nproc());
-	for (i = 0; i < mp->m_sb.sb_agcount; i++)
+	for_each_ag(mp, i)
 		queue_work(&wq, check_refcount_btrees, i, NULL);
 	destroy_work_queue(&wq);
 }
diff --git a/repair/rmap.c b/repair/rmap.c
index 3b3a195..37da251 100644
--- a/repair/rmap.c
+++ b/repair/rmap.c
@@ -45,6 +45,7 @@ struct xfs_ag_rmap {
 	struct xfs_slab	*ar_refcount_items;	/* refcount items, p4-5 */
 };
 
+/* One ag_rmap per AG, and one more for the realtime device. */
 static struct xfs_ag_rmap *ag_rmaps;
 static bool rmapbt_suspect;
 static bool refcbt_suspect;
@@ -83,6 +84,17 @@ rmap_compare(
 }
 
 /*
+ * Return the ag_rmap for a given AG.
+ * Note that NULLAGNUMBER (-1) is the realtime device.
+ */
+static struct xfs_ag_rmap*
+rmap_for_ag(
+	xfs_agnumber_t		agno)
+{
+	return &ag_rmaps[(signed)agno];
+}
+
+/*
  * Returns true if we must reconstruct either the reference count or reverse
  * mapping trees.
  */
@@ -107,11 +119,12 @@ rmaps_init(
 	if (!rmap_needs_work(mp))
 		return;
 
-	ag_rmaps = calloc(mp->m_sb.sb_agcount, sizeof(struct xfs_ag_rmap));
+	/* One ag_rmap per AG, and one more for the realtime device. */
+	ag_rmaps = calloc(mp->m_sb.sb_agcount + 1, sizeof(struct xfs_ag_rmap));
 	if (!ag_rmaps)
 		do_error(_("couldn't allocate per-AG reverse map roots\n"));
 
-	for (i = 0; i < mp->m_sb.sb_agcount; i++) {
+	for (i = 0; i < mp->m_sb.sb_agcount + 1; i++) {
 		error = init_slab(&ag_rmaps[i].ar_rmaps,
 				sizeof(struct xfs_rmap_irec));
 		if (error)
@@ -129,6 +142,7 @@ _("Insufficient memory while allocating raw metadata reverse mapping slabs."));
 			do_error(
 _("Insufficient memory while allocating refcount item slabs."));
 	}
+	ag_rmaps++;
 }
 
 /*
@@ -143,7 +157,8 @@ rmaps_free(
 	if (!rmap_needs_work(mp))
 		return;
 
-	for (i = 0; i < mp->m_sb.sb_agcount; i++) {
+	ag_rmaps--;
+	for (i = 0; i < mp->m_sb.sb_agcount + 1; i++) {
 		free_slab(&ag_rmaps[i].ar_rmaps);
 		free_slab(&ag_rmaps[i].ar_raw_rmaps);
 		free_slab(&ag_rmaps[i].ar_refcount_items);
@@ -186,22 +201,31 @@ rmap_add_rec(
 	struct xfs_mount	*mp,
 	xfs_ino_t		ino,
 	int			whichfork,
-	struct xfs_bmbt_irec	*irec)
+	struct xfs_bmbt_irec	*irec,
+	bool			realtime)
 {
+	struct xfs_ag_rmap	*ag_rmap;
 	struct xfs_rmap_irec	rmap;
 	xfs_agnumber_t		agno;
-	xfs_agblock_t		agbno;
+	xfs_fsblock_t		agbno;
 	struct xfs_rmap_irec	*last_rmap;
 	int			error = 0;
 
 	if (!rmap_needs_work(mp))
 		return 0;
 
-	agno = XFS_FSB_TO_AGNO(mp, irec->br_startblock);
-	agbno = XFS_FSB_TO_AGBNO(mp, irec->br_startblock);
-	ASSERT(agno != NULLAGNUMBER);
-	ASSERT(agno < mp->m_sb.sb_agcount);
-	ASSERT(agbno + irec->br_blockcount <= mp->m_sb.sb_agblocks);
+	if (realtime) {
+		agno = NULLAGNUMBER;
+		agbno = irec->br_startblock;
+		ASSERT(agbno + irec->br_blockcount <= mp->m_sb.sb_rblocks);
+	} else {
+		agno = XFS_FSB_TO_AGNO(mp, irec->br_startblock);
+		agbno = XFS_FSB_TO_AGBNO(mp, irec->br_startblock);
+		ASSERT(agno != NULLAGNUMBER);
+		ASSERT(agno < mp->m_sb.sb_agcount);
+		ASSERT(agbno + irec->br_blockcount <= mp->m_sb.sb_agblocks);
+	}
+	ag_rmap = rmap_for_ag(agno);
 	ASSERT(ino != NULLFSINO);
 	ASSERT(whichfork == XFS_DATA_FORK || whichfork == XFS_ATTR_FORK);
 
@@ -214,13 +238,13 @@ rmap_add_rec(
 	rmap.rm_blockcount = irec->br_blockcount;
 	if (irec->br_state == XFS_EXT_UNWRITTEN)
 		rmap.rm_flags |= XFS_RMAP_UNWRITTEN;
-	last_rmap = &ag_rmaps[agno].ar_last_rmap;
+	last_rmap = &ag_rmap->ar_last_rmap;
 	if (last_rmap->rm_owner == XFS_RMAP_OWN_UNKNOWN)
 		*last_rmap = rmap;
 	else if (rmaps_are_mergeable(last_rmap, &rmap))
 		last_rmap->rm_blockcount += rmap.rm_blockcount;
 	else {
-		error = slab_add(ag_rmaps[agno].ar_rmaps, last_rmap);
+		error = slab_add(ag_rmap->ar_rmaps, last_rmap);
 		if (error)
 			return error;
 		*last_rmap = rmap;
@@ -236,9 +260,10 @@ rmap_finish_collecting_fork_recs(
 	xfs_agnumber_t		agno)
 {
 	if (!rmap_needs_work(mp) ||
-	    ag_rmaps[agno].ar_last_rmap.rm_owner == XFS_RMAP_OWN_UNKNOWN)
+	    rmap_for_ag(agno)->ar_last_rmap.rm_owner == XFS_RMAP_OWN_UNKNOWN)
 		return 0;
-	return slab_add(ag_rmaps[agno].ar_rmaps, &ag_rmaps[agno].ar_last_rmap);
+	return slab_add(rmap_for_ag(agno)->ar_rmaps,
+			&rmap_for_ag(agno)->ar_last_rmap);
 }
 
 /* add a raw rmap; these will be merged later */
@@ -264,7 +289,7 @@ __rmap_add_raw_rec(
 		rmap.rm_flags |= XFS_RMAP_BMBT_BLOCK;
 	rmap.rm_startblock = agbno;
 	rmap.rm_blockcount = len;
-	return slab_add(ag_rmaps[agno].ar_raw_rmaps, &rmap);
+	return slab_add(rmap_for_ag(agno)->ar_raw_rmaps, &rmap);
 }
 
 /*
@@ -322,16 +347,18 @@ rmap_fold_raw_recs(
 	struct xfs_mount	*mp,
 	xfs_agnumber_t		agno)
 {
+	struct xfs_ag_rmap	*ag_rmap;
 	struct xfs_slab_cursor	*cur = NULL;
 	struct xfs_rmap_irec	*prev, *rec;
 	size_t			old_sz;
 	int			error = 0;
 
-	old_sz = slab_count(ag_rmaps[agno].ar_rmaps);
-	if (slab_count(ag_rmaps[agno].ar_raw_rmaps) == 0)
+	ag_rmap = rmap_for_ag(agno);
+	old_sz = slab_count(ag_rmap->ar_rmaps);
+	if (slab_count(ag_rmap->ar_raw_rmaps) == 0)
 		goto no_raw;
-	qsort_slab(ag_rmaps[agno].ar_raw_rmaps, rmap_compare);
-	error = init_slab_cursor(ag_rmaps[agno].ar_raw_rmaps, rmap_compare,
+	qsort_slab(ag_rmap->ar_raw_rmaps, rmap_compare);
+	error = init_slab_cursor(ag_rmap->ar_raw_rmaps, rmap_compare,
 			&cur);
 	if (error)
 		goto err;
@@ -344,26 +371,26 @@ rmap_fold_raw_recs(
 			rec = pop_slab_cursor(cur);
 			continue;
 		}
-		error = slab_add(ag_rmaps[agno].ar_rmaps, prev);
+		error = slab_add(ag_rmap->ar_rmaps, prev);
 		if (error)
 			goto err;
 		prev = rec;
 		rec = pop_slab_cursor(cur);
 	}
 	if (prev) {
-		error = slab_add(ag_rmaps[agno].ar_rmaps, prev);
+		error = slab_add(ag_rmap->ar_rmaps, prev);
 		if (error)
 			goto err;
 	}
-	free_slab(&ag_rmaps[agno].ar_raw_rmaps);
-	error = init_slab(&ag_rmaps[agno].ar_raw_rmaps,
+	free_slab(&ag_rmap->ar_raw_rmaps);
+	error = init_slab(&ag_rmap->ar_raw_rmaps,
 			sizeof(struct xfs_rmap_irec));
 	if (error)
 		do_error(
 _("Insufficient memory while allocating raw metadata reverse mapping slabs."));
 no_raw:
 	if (old_sz)
-		qsort_slab(ag_rmaps[agno].ar_rmaps, rmap_compare);
+		qsort_slab(ag_rmap->ar_rmaps, rmap_compare);
 err:
 	free_slab_cursor(&cur);
 	return error;
@@ -419,6 +446,9 @@ rmap_add_fixed_ag_rec(
 	if (!rmap_needs_work(mp))
 		return 0;
 
+	if (agno == NULLAGNUMBER)
+		return 0;
+
 	/* sb/agi/agf/agfl headers */
 	error = rmap_add_ag_rec(mp, agno, 0, XFS_BNO_BLOCK(mp),
 			XFS_RMAP_OWN_FS);
@@ -493,6 +523,7 @@ rmap_store_ag_btree_rec(
 	struct xfs_trans	*tp;
 	struct xfs_trans_res tres = {0};
 	__be32			*agfl_bno, *b;
+	struct xfs_ag_rmap	*ag_rmap;
 	int			error = 0;
 	struct xfs_owner_info	oinfo;
 
@@ -500,9 +531,9 @@ rmap_store_ag_btree_rec(
 		return 0;
 
 	/* Release the ar_rmaps; they were put into the rmapbt during p5. */
-	free_slab(&ag_rmaps[agno].ar_rmaps);
-	error = init_slab(&ag_rmaps[agno].ar_rmaps,
-				  sizeof(struct xfs_rmap_irec));
+	ag_rmap = rmap_for_ag(agno);
+	free_slab(&ag_rmap->ar_rmaps);
+	error = init_slab(&ag_rmap->ar_rmaps, sizeof(struct xfs_rmap_irec));
 	if (error)
 		goto err;
 
@@ -515,7 +546,7 @@ rmap_store_ag_btree_rec(
 		goto err;
 
 	agfl_bno = XFS_BUF_TO_AGFL_BNO(mp, agflbp);
-	agfl_bno += ag_rmaps[agno].ar_flcount;
+	agfl_bno += ag_rmap->ar_flcount;
 	b = agfl_bno;
 	while (*b != NULLAGBLOCK && b - agfl_bno <= XFS_AGFL_SIZE(mp)) {
 		error = rmap_add_ag_rec(mp, agno, be32_to_cpu(*b), 1,
@@ -533,7 +564,7 @@ rmap_store_ag_btree_rec(
 		goto err;
 
 	/* Create cursors to refcount structures */
-	error = init_slab_cursor(ag_rmaps[agno].ar_rmaps, rmap_compare,
+	error = init_slab_cursor(ag_rmap->ar_rmaps, rmap_compare,
 			&rm_cur);
 	if (error)
 		goto err;
@@ -714,7 +745,7 @@ refcount_emit(
 	int			error;
 	struct xfs_slab		*rlslab;
 
-	rlslab = ag_rmaps[agno].ar_refcount_items;
+	rlslab = rmap_for_ag(agno)->ar_refcount_items;
 	ASSERT(nr_rmaps > 0);
 
 	dbg_printf("REFL: agno=%u pblk=%u, len=%u -> refcount=%zu\n",
@@ -736,7 +767,7 @@ _("Insufficient memory while recreating refcount tree."));
 #define RMAP_END(r)	((r)->rm_startblock + (r)->rm_blockcount)
 int
 compute_refcounts(
-	struct xfs_mount		*mp,
+	struct xfs_mount	*mp,
 	xfs_agnumber_t		agno)
 {
 	struct xfs_bag		*stack_top = NULL;
@@ -754,7 +785,7 @@ compute_refcounts(
 	if (!xfs_sb_version_hasreflink(&mp->m_sb))
 		return 0;
 
-	rmaps = ag_rmaps[agno].ar_rmaps;
+	rmaps = rmap_for_ag(agno)->ar_rmaps;
 
 	error = init_slab_cursor(rmaps, rmap_compare, &rmaps_cur);
 	if (error)
@@ -864,7 +895,7 @@ rmap_record_count(
 	struct xfs_mount		*mp,
 	xfs_agnumber_t		agno)
 {
-	return slab_count(ag_rmaps[agno].ar_rmaps);
+	return slab_count(rmap_for_ag(agno)->ar_rmaps);
 }
 
 /*
@@ -875,7 +906,7 @@ rmap_init_cursor(
 	xfs_agnumber_t		agno,
 	struct xfs_slab_cursor	**cur)
 {
-	return init_slab_cursor(ag_rmaps[agno].ar_rmaps, rmap_compare, cur);
+	return init_slab_cursor(rmap_for_ag(agno)->ar_rmaps, rmap_compare, cur);
 }
 
 /*
@@ -1269,7 +1300,7 @@ refcount_record_count(
 	struct xfs_mount		*mp,
 	xfs_agnumber_t		agno)
 {
-	return slab_count(ag_rmaps[agno].ar_refcount_items);
+	return slab_count(rmap_for_ag(agno)->ar_refcount_items);
 }
 
 /*
@@ -1280,7 +1311,7 @@ init_refcount_cursor(
 	xfs_agnumber_t		agno,
 	struct xfs_slab_cursor	**cur)
 {
-	return init_slab_cursor(ag_rmaps[agno].ar_refcount_items, NULL, cur);
+	return init_slab_cursor(rmap_for_ag(agno)->ar_refcount_items, NULL, cur);
 }
 
 /*
@@ -1461,5 +1492,5 @@ rmap_store_agflcount(
 	if (!rmap_needs_work(mp))
 		return;
 
-	ag_rmaps[agno].ar_flcount = count;
+	rmap_for_ag(agno)->ar_flcount = count;
 }
diff --git a/repair/rmap.h b/repair/rmap.h
index 752ece8..7069b6b 100644
--- a/repair/rmap.h
+++ b/repair/rmap.h
@@ -27,7 +27,8 @@ extern bool rmap_needs_work(struct xfs_mount *);
 extern void rmaps_init(struct xfs_mount *);
 extern void rmaps_free(struct xfs_mount *);
 
-extern int rmap_add_rec(struct xfs_mount *, xfs_ino_t, int, struct xfs_bmbt_irec *);
+extern int rmap_add_rec(struct xfs_mount *, xfs_ino_t, int,
+		struct xfs_bmbt_irec *, bool realtime);
 extern int rmap_finish_collecting_fork_recs(struct xfs_mount *mp,
 		xfs_agnumber_t agno);
 extern int rmap_add_ag_rec(struct xfs_mount *, xfs_agnumber_t agno,
@@ -62,4 +63,11 @@ extern int fix_inode_reflink_flags(struct xfs_mount *, xfs_agnumber_t);
 extern void fix_freelist(struct xfs_mount *, xfs_agnumber_t, bool);
 extern void rmap_store_agflcount(struct xfs_mount *, xfs_agnumber_t, int);
 
+#define for_each_ag(mp, agno) \
+	for ((agno) = 0; (agno) < (mp)->m_sb.sb_agcount; (agno)++)
+
+#define for_each_rmap_group(mp, agno) \
+	for ((agno) = NULLAGNUMBER; (agno) == NULLAGNUMBER || \
+	(agno) < (mp)->m_sb.sb_agcount; (agno)++)
+
 #endif /* RMAP_H_ */

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 25/29] xfs_repair: collect relatime reverse-mapping data for refcount/rmap tree rebuilding
  2016-08-25 23:58 [PATCH v8 00/29] xfsprogs: add realtime reverse-mapping support Darrick J. Wong
                   ` (23 preceding siblings ...)
  2016-08-26  0:01 ` [PATCH 24/29] xfs_repair: extend ag_rmap[] for realtime mapping collection Darrick J. Wong
@ 2016-08-26  0:01 ` Darrick J. Wong
  2016-08-26  0:01 ` [PATCH 26/29] xfs_repair: check existing realtime rmapbt entries against observed rmaps Darrick J. Wong
                   ` (3 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: Darrick J. Wong @ 2016-08-26  0:01 UTC (permalink / raw)
  To: david, darrick.wong; +Cc: linux-xfs, xfs

Collect reverse-mapping data for realtime files so that we can later
check and rebuild the reference count tree and the reverse mapping
tree.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 repair/dinode.c |   15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)


diff --git a/repair/dinode.c b/repair/dinode.c
index f768cdf..04759dc 100644
--- a/repair/dinode.c
+++ b/repair/dinode.c
@@ -594,6 +594,7 @@ process_bmbt_reclist_int(
 	xfs_agblock_t		ebno;
 	xfs_extlen_t		blen;
 	xfs_agnumber_t		locked_agno = -1;
+	struct aglock		*ag_lock;
 	int			error = 1;
 
 	if (type == XR_INO_RTDATA)
@@ -639,8 +640,20 @@ _("zero length extent (off = %" PRIu64 ", fsbno = %" PRIu64 ") in ino %" PRIu64
 			 */
 			if (process_rt_rec(mp, &irec, ino, tot, check_dups))
 				return 1;
+			/* collect reverse mappings for realtime files */
+			if (collect_rmaps && !check_dups) {
+				ag_lock = &ag_locks[(signed)NULLAGNUMBER];
+				pthread_mutex_lock(&ag_lock->lock);
+				error = rmap_add_rec(mp, ino, whichfork,
+						&irec, true);
+				pthread_mutex_unlock(&ag_lock->lock);
+				if (error)
+					do_error(
+_("couldn't add reverse mapping\n")
+						);
+			}
 			/*
-			 * skip rest of loop processing since that'irec.br_startblock
+			 * skip rest of loop processing since that's
 			 * all for regular file forks and attr forks
 			 */
 			continue;

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 26/29] xfs_repair: check existing realtime rmapbt entries against observed rmaps
  2016-08-25 23:58 [PATCH v8 00/29] xfsprogs: add realtime reverse-mapping support Darrick J. Wong
                   ` (24 preceding siblings ...)
  2016-08-26  0:01 ` [PATCH 25/29] xfs_repair: collect relatime reverse-mapping data for refcount/rmap tree rebuilding Darrick J. Wong
@ 2016-08-26  0:01 ` Darrick J. Wong
  2016-08-26  0:01 ` [PATCH 27/29] xfs_repair: find and mark the rtrmapbt inode Darrick J. Wong
                   ` (2 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: Darrick J. Wong @ 2016-08-26  0:01 UTC (permalink / raw)
  To: david, darrick.wong; +Cc: linux-xfs, xfs

Once we've finished collecting reverse mapping observations from the
metadata scan, check those observations against the realtime rmap btree
(particularly if we're in -n mode) to detect rtrmapbt problems.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 repair/rmap.c |   48 +++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 39 insertions(+), 9 deletions(-)


diff --git a/repair/rmap.c b/repair/rmap.c
index 37da251..d6a75d7 100644
--- a/repair/rmap.c
+++ b/repair/rmap.c
@@ -1008,6 +1008,7 @@ rmaps_verify_btree(
 	struct xfs_rmap_irec	*rm_rec;
 	struct xfs_rmap_irec	tmp;
 	struct xfs_perag	*pag;		/* per allocation group data */
+	struct xfs_inode	*ip = NULL;
 
 	if (!xfs_sb_version_hasrmapbt(&mp->m_sb))
 		return 0;
@@ -1016,22 +1017,47 @@ rmaps_verify_btree(
 			do_warn(_("would rebuild corrupt rmap btrees.\n"));
 		return 0;
 	}
+	if (agno == NULLAGNUMBER && mp->m_sb.sb_rblocks == 0) {
+		if (rmap_record_count(mp, NULLAGNUMBER) != 0) {
+			do_error(_("realtime extents but no rtdev?\n"));
+			return -EFSCORRUPTED;
+		}
+		return 0;
+	}
 
-	/* Create cursors to refcount structures */
+	/* Create cursors to rmap structures */
 	error = rmap_init_cursor(agno, &rm_cur);
 	if (error)
 		return error;
 
-	error = -libxfs_alloc_read_agf(mp, NULL, agno, 0, &agbp);
-	if (error)
-		goto err;
+	if (agno == NULLAGNUMBER) {
+		if (mp->m_sb.sb_rrmapino == 0 ||
+		    mp->m_sb.sb_rrmapino == NULLFSINO) {
+			do_warn(
+_("garbage in sb_rrmapino, not checking realtime rmaps\n"));
+			goto err;
+		}
 
-	/* Leave the per-ag data "uninitialized" since we rewrite it later */
-	pag = libxfs_perag_get(mp, agno);
-	pag->pagf_init = 0;
-	libxfs_perag_put(pag);
+		error = -libxfs_iget(mp, NULL, mp->m_sb.sb_rrmapino, 0, &ip, 0);
+		if (error) {
+			do_warn(_("%d - couldn't iget rtrmap inode.\n"),
+				 error);
+			goto err;
+		}
+		mp->m_rrmapip = ip;
+		bt_cur = libxfs_rtrmapbt_init_cursor(mp, NULL, mp->m_rrmapip);
+	} else {
+		error = -libxfs_alloc_read_agf(mp, NULL, agno, 0, &agbp);
+		if (error)
+			goto err;
+
+		/* Leave the per-ag data "uninitialized" since we rewrite it later */
+		pag = libxfs_perag_get(mp, agno);
+		pag->pagf_init = 0;
+		libxfs_perag_put(pag);
 
-	bt_cur = libxfs_rmapbt_init_cursor(mp, NULL, agbp, agno);
+		bt_cur = libxfs_rmapbt_init_cursor(mp, NULL, agbp, agno);
+	}
 	if (!bt_cur) {
 		error = -ENOMEM;
 		goto err;
@@ -1107,6 +1133,10 @@ err:
 		libxfs_btree_del_cursor(bt_cur, XFS_BTREE_NOERROR);
 	if (agbp)
 		libxfs_putbuf(agbp);
+	if (ip) {
+		IRELE(mp->m_rrmapip);
+		mp->m_rrmapip = NULL;
+	}
 	free_slab_cursor(&rm_cur);
 	return 0;
 }

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 27/29] xfs_repair: find and mark the rtrmapbt inode
  2016-08-25 23:58 [PATCH v8 00/29] xfsprogs: add realtime reverse-mapping support Darrick J. Wong
                   ` (25 preceding siblings ...)
  2016-08-26  0:01 ` [PATCH 26/29] xfs_repair: check existing realtime rmapbt entries against observed rmaps Darrick J. Wong
@ 2016-08-26  0:01 ` Darrick J. Wong
  2016-08-26  0:01 ` [PATCH 28/29] xfs_repair: rebuild the realtime rmap btree Darrick J. Wong
  2016-08-26  0:01 ` [PATCH 29/29] mkfs: create the realtime rmap inode Darrick J. Wong
  28 siblings, 0 replies; 30+ messages in thread
From: Darrick J. Wong @ 2016-08-26  0:01 UTC (permalink / raw)
  To: david, darrick.wong; +Cc: linux-xfs, xfs

Make sure that we find the realtime rmapbt inode and mark it
appropriately, just in case we find a rogue inode claiming to
be an rtrmap, or just plain garbage in the superblock field.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 repair/dino_chunks.c |   12 ++++++++++++
 repair/dinode.c      |   41 +++++++++++++++++++++++++++++++++++++++++
 repair/dir2.c        |    5 +++++
 repair/globals.h     |    1 +
 repair/incore.h      |    1 +
 repair/phase1.c      |    1 +
 repair/phase6.c      |   13 +++++++++++++
 repair/rmap.c        |    1 +
 repair/sb.c          |    3 +++
 9 files changed, 78 insertions(+)


diff --git a/repair/dino_chunks.c b/repair/dino_chunks.c
index 4db9512..d08e2ba 100644
--- a/repair/dino_chunks.c
+++ b/repair/dino_chunks.c
@@ -924,6 +924,18 @@ next_readbuf:
 	_("would clear realtime summary inode %" PRIu64 "\n"),
 						ino);
 				}
+			} else if (mp->m_sb.sb_rrmapino == ino) {
+				need_rrmapino = 1;
+
+				if (!no_modify)  {
+					do_warn(
+	_("cleared realtime rmap inode %" PRIu64 "\n"),
+						ino);
+				} else  {
+					do_warn(
+	_("would clear realtime rmap inode %" PRIu64 "\n"),
+						ino);
+				}
 			} else if (!no_modify)  {
 				do_warn(_("cleared inode %" PRIu64 "\n"),
 					ino);
diff --git a/repair/dinode.c b/repair/dinode.c
index 04759dc..25c2ba0 100644
--- a/repair/dinode.c
+++ b/repair/dinode.c
@@ -266,6 +266,12 @@ clear_dinode(xfs_mount_t *mp, xfs_dinode_t *dino, xfs_ino_t ino_num)
 	dirty = clear_dinode_core(mp, dino, ino_num);
 	dirty += clear_dinode_unlinked(mp, dino);
 
+	if (ino_num == mp->m_sb.sb_rrmapino) {
+		mp->m_sb.sb_rrmapino = NULLFSINO;
+		need_rrmapino = 1;
+		rmap_avoid_check();
+	}
+
 	/* and clear the forks */
 
 	if (dirty && !no_modify)
@@ -1838,6 +1844,27 @@ _("bad # of extents (%u) for realtime bitmap inode %" PRIu64 "\n"),
 		}
 		return 0;
 	}
+	if (lino == mp->m_sb.sb_rrmapino) {
+		if (*type != XR_INO_RTRMAP) {
+			do_warn(
+_("realtime rmap inode %" PRIu64 " has bad type 0x%x, "),
+				lino, dinode_fmt(dinoc));
+			if (!no_modify)  {
+				do_warn(_("resetting to regular file\n"));
+				change_dinode_fmt(dinoc, S_IFREG);
+				*dirty = 1;
+			} else  {
+				do_warn(_("would reset to regular file\n"));
+			}
+		}
+		if (mp->m_sb.sb_rblocks == 0 && dinoc->di_nextents != 0)  {
+			do_warn(
+_("bad # of extents (%u) for realtime rmap inode %" PRIu64 "\n"),
+				be32_to_cpu(dinoc->di_nextents), lino);
+			return 1;
+		}
+		return 0;
+	}
 	return 0;
 }
 
@@ -1928,6 +1955,18 @@ _("realtime summary inode %" PRIu64 " has bad size %" PRId64 " (should be %d)\n"
 		}
 		break;
 
+	case XR_INO_RTRMAP:
+		/*
+		 * if we have no rmapbt, any inode claiming
+		 * to be a real-time file is bogus
+		 */
+		if (!xfs_sb_version_hasrmapbt(&mp->m_sb)) {
+			do_warn(
+_("found inode %" PRIu64 " claiming to be a rtrmapbt file, but rmapbt is disabled\n"), lino);
+			return 1;
+		}
+		break;
+
 	default:
 		break;
 	}
@@ -2774,6 +2813,8 @@ _("bad (negative) size %" PRId64 " on inode %" PRIu64 "\n"),
 			type = XR_INO_RTBITMAP;
 		else if (lino == mp->m_sb.sb_rsumino)
 			type = XR_INO_RTSUM;
+		else if (lino == mp->m_sb.sb_rrmapino)
+			type = XR_INO_RTRMAP;
 		else
 			type = XR_INO_DATA;
 		break;
diff --git a/repair/dir2.c b/repair/dir2.c
index a2fe5c6..a120868 100644
--- a/repair/dir2.c
+++ b/repair/dir2.c
@@ -236,6 +236,9 @@ process_sf_dir2(
 		} else if (lino == mp->m_sb.sb_rsumino)  {
 			junkit = 1;
 			junkreason = _("realtime summary");
+		} else if (lino == mp->m_sb.sb_rrmapino)  {
+			junkit = 1;
+			junkreason = _("realtime rmap");
 		} else if (lino == mp->m_sb.sb_uquotino)  {
 			junkit = 1;
 			junkreason = _("user quota");
@@ -695,6 +698,8 @@ process_dir2_data(
 			clearreason = _("realtime bitmap");
 		} else if (ent_ino == mp->m_sb.sb_rsumino) {
 			clearreason = _("realtime summary");
+		} else if (ent_ino == mp->m_sb.sb_rrmapino) {
+			clearreason = _("realtime rmap");
 		} else if (ent_ino == mp->m_sb.sb_uquotino) {
 			clearreason = _("user quota");
 		} else if (ent_ino == mp->m_sb.sb_gquotino) {
diff --git a/repair/globals.h b/repair/globals.h
index efd1d03..0ea9a7d 100644
--- a/repair/globals.h
+++ b/repair/globals.h
@@ -118,6 +118,7 @@ EXTERN int		need_root_dotdot;
 
 EXTERN int		need_rbmino;
 EXTERN int		need_rsumino;
+EXTERN int		need_rrmapino;
 
 EXTERN int		lost_quotas;
 EXTERN int		have_uquotino;
diff --git a/repair/incore.h b/repair/incore.h
index c23a3a3..0858fd1 100644
--- a/repair/incore.h
+++ b/repair/incore.h
@@ -229,6 +229,7 @@ int		count_bcnt_extents(xfs_agnumber_t);
 #define XR_INO_SOCK	9		/* socket */
 #define XR_INO_FIFO	10		/* fifo */
 #define XR_INO_MOUNTPOINT 11		/* mountpoint */
+#define XR_INO_RTRMAP	12		/* realtime rmap */
 
 /* inode allocation tree */
 
diff --git a/repair/phase1.c b/repair/phase1.c
index 126d0b3..3404b0b 100644
--- a/repair/phase1.c
+++ b/repair/phase1.c
@@ -62,6 +62,7 @@ phase1(xfs_mount_t *mp)
 	need_root_dotdot = 0;
 	need_rbmino = 0;
 	need_rsumino = 0;
+	need_rrmapino = 0;
 	lost_quotas = 0;
 
 	/*
diff --git a/repair/phase6.c b/repair/phase6.c
index 560f9bb..6981b35 100644
--- a/repair/phase6.c
+++ b/repair/phase6.c
@@ -3074,6 +3074,19 @@ mark_standalone_inodes(xfs_mount_t *mp)
 			add_inode_reached(irec, offset);
 		}
 	}
+
+	if (xfs_sb_version_hasrmapbt(&mp->m_sb) && mp->m_sb.sb_rblocks > 0) {
+		irec = find_inode_rec(mp,
+				XFS_INO_TO_AGNO(mp, mp->m_sb.sb_rrmapino),
+				XFS_INO_TO_AGINO(mp, mp->m_sb.sb_rrmapino));
+
+		offset = XFS_INO_TO_AGINO(mp, mp->m_sb.sb_rrmapino) -
+				irec->ino_startnum;
+
+		ASSERT(irec != NULL);
+
+		add_inode_reached(irec, offset);
+	}
 }
 
 static void
diff --git a/repair/rmap.c b/repair/rmap.c
index d6a75d7..9f9a47c 100644
--- a/repair/rmap.c
+++ b/repair/rmap.c
@@ -1035,6 +1035,7 @@ rmaps_verify_btree(
 		    mp->m_sb.sb_rrmapino == NULLFSINO) {
 			do_warn(
 _("garbage in sb_rrmapino, not checking realtime rmaps\n"));
+			need_rrmapino = 1;
 			goto err;
 		}
 
diff --git a/repair/sb.c b/repair/sb.c
index ac13a66..5a2bb60 100644
--- a/repair/sb.c
+++ b/repair/sb.c
@@ -37,6 +37,7 @@ copy_sb(xfs_sb_t *source, xfs_sb_t *dest)
 	xfs_ino_t	rootino;
 	xfs_ino_t	rbmino;
 	xfs_ino_t	rsumino;
+	xfs_ino_t	rrmapino;
 	xfs_ino_t	uquotino;
 	xfs_ino_t	gquotino;
 	xfs_ino_t	pquotino;
@@ -45,6 +46,7 @@ copy_sb(xfs_sb_t *source, xfs_sb_t *dest)
 	rootino = dest->sb_rootino;
 	rbmino = dest->sb_rbmino;
 	rsumino = dest->sb_rsumino;
+	rrmapino = dest->sb_rrmapino;
 	uquotino = dest->sb_uquotino;
 	gquotino = dest->sb_gquotino;
 	pquotino = dest->sb_pquotino;
@@ -56,6 +58,7 @@ copy_sb(xfs_sb_t *source, xfs_sb_t *dest)
 	dest->sb_rootino = rootino;
 	dest->sb_rbmino = rbmino;
 	dest->sb_rsumino = rsumino;
+	dest->sb_rrmapino = rrmapino;
 	dest->sb_uquotino = uquotino;
 	dest->sb_gquotino = gquotino;
 	dest->sb_pquotino = pquotino;

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 28/29] xfs_repair: rebuild the realtime rmap btree
  2016-08-25 23:58 [PATCH v8 00/29] xfsprogs: add realtime reverse-mapping support Darrick J. Wong
                   ` (26 preceding siblings ...)
  2016-08-26  0:01 ` [PATCH 27/29] xfs_repair: find and mark the rtrmapbt inode Darrick J. Wong
@ 2016-08-26  0:01 ` Darrick J. Wong
  2016-08-26  0:01 ` [PATCH 29/29] mkfs: create the realtime rmap inode Darrick J. Wong
  28 siblings, 0 replies; 30+ messages in thread
From: Darrick J. Wong @ 2016-08-26  0:01 UTC (permalink / raw)
  To: david, darrick.wong; +Cc: linux-xfs, xfs

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 libxfs/libxfs_api_defs.h |    1 +
 repair/phase6.c          |   73 ++++++++++++++++++++++++++++++++++++++++++++++
 repair/rmap.c            |   68 +++++++++++++++++++++++++++++++++++++++++++
 repair/rmap.h            |    2 +
 repair/xfs_repair.c      |    5 +++
 5 files changed, 148 insertions(+), 1 deletion(-)


diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h
index a6ea865..44b9065 100644
--- a/libxfs/libxfs_api_defs.h
+++ b/libxfs/libxfs_api_defs.h
@@ -144,5 +144,6 @@
 #define xfs_refc_block			libxfs_refc_block
 #define xfs_rtrmapbt_maxrecs		libxfs_rtrmapbt_maxrecs
 #define xfs_rtrmapbt_init_cursor	libxfs_rtrmapbt_init_cursor
+#define xfs_rmap_map_extent		libxfs_rmap_map_extent
 
 #endif /* __LIBXFS_API_DEFS_H__ */
diff --git a/repair/phase6.c b/repair/phase6.c
index 6981b35..25d6801 100644
--- a/repair/phase6.c
+++ b/repair/phase6.c
@@ -29,6 +29,8 @@
 #include "dinode.h"
 #include "progress.h"
 #include "versions.h"
+#include "slab.h"
+#include "rmap.h"
 
 static struct cred		zerocr;
 static struct fsxattr 		zerofsx;
@@ -831,6 +833,61 @@ mk_rsumino(xfs_mount_t *mp)
 	IRELE(ip);
 }
 
+static void
+mk_rrmapino(
+	struct xfs_mount	*mp)
+{
+	struct xfs_trans	*tp;
+	struct xfs_inode	*ip;
+	struct cred		creds = {0};
+	struct fsxattr		fsxattrs = {0};
+	struct xfs_btree_block	*block;
+	int			error;
+
+	if (!xfs_sb_version_hasrmapbt(&mp->m_sb) || mp->m_sb.sb_rblocks == 0)
+		return;
+
+	error = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_ichange, 0, 0, 0, &tp);
+	if (error)
+		res_failed(error);
+
+	if (mp->m_sb.sb_rrmapino == 0 ||
+	    mp->m_sb.sb_rrmapino == NULLFSINO ||
+	    need_rrmapino) {
+		/* Allocate a new inode. */
+		error = -libxfs_inode_alloc(&tp, NULL, S_IFREG, 1, 0,
+				&creds, &fsxattrs, &ip);
+		if (error) {
+			do_error(_("Realtime rmap inode allocation failed -- error %d"),
+				 error);
+		}
+		mp->m_sb.sb_rrmapino = ip->i_ino;
+		ip->i_df.if_broot_bytes = XFS_RTRMAP_BROOT_SPACE_CALC(0, 0);
+		ip->i_df.if_broot = kmem_alloc(ip->i_df.if_broot_bytes,
+				KM_SLEEP | KM_NOFS);
+	} else {
+		/* Grab the existing inode. */
+		error = -libxfs_trans_iget(mp, tp, mp->m_sb.sb_rrmapino,
+				0, 0, &ip);
+		if (error)
+			do_error(_("Could not iget realtime rmapbt inode -- error %d"),
+				error);
+	}
+
+	/* Reset the btree root. */
+	ip->i_d.di_size = 0;
+	ip->i_d.di_nblocks = 0;
+	ip->i_d.di_format = XFS_DINODE_FMT_RMAP;
+	block = ip->i_df.if_broot;
+	block->bb_numrecs = cpu_to_be16(0);
+	block->bb_level = cpu_to_be16(0);
+
+	libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE | XFS_ILOG_DBROOT);
+	libxfs_log_sb(tp);
+	libxfs_trans_commit(tp);
+	IRELE(ip);
+}
+
 /*
  * makes a new root directory.
  */
@@ -3248,6 +3305,18 @@ phase6(xfs_mount_t *mp)
 		}
 	}
 
+	/*
+	 * We always reinitialize the rrmapbt inode, but if it was bad we
+	 * ought to say something.
+	 */
+	if (no_modify) {
+		if (need_rrmapino)
+			do_warn(_("would reinitialize realtime rmap btree\n"));
+	} else {
+		need_rrmapino = 0;
+		mk_rrmapino(mp);
+	}
+
 	if (!no_modify)  {
 		do_log(
 _("        - resetting contents of realtime bitmap and summary inodes\n"));
@@ -3260,6 +3329,10 @@ _("        - resetting contents of realtime bitmap and summary inodes\n"));
 			do_warn(
 			_("Warning:  realtime bitmap may be inconsistent\n"));
 		}
+
+		if (rmap_populate_realtime_rmapbt(mp))
+			do_warn(
+			_("Warning:  realtime rmapbt may be inconsistent\n"));
 	}
 
 	mark_standalone_inodes(mp);
diff --git a/repair/rmap.c b/repair/rmap.c
index 9f9a47c..f5ab167 100644
--- a/repair/rmap.c
+++ b/repair/rmap.c
@@ -1525,3 +1525,71 @@ rmap_store_agflcount(
 
 	rmap_for_ag(agno)->ar_flcount = count;
 }
+
+/* Store the realtime reverse-mappings in the rtrmapbt. */
+int
+rmap_populate_realtime_rmapbt(
+	struct xfs_mount	*mp)
+{
+	struct xfs_trans	*tp;
+	struct xfs_inode	*ip;
+	struct xfs_inode	fakei;
+	struct xfs_slab_cursor	*rmap_cur;
+	struct xfs_defer_ops	dfops;
+	xfs_fsblock_t		firstfsb;
+	struct xfs_rmap_irec	*rm_rec;
+	struct xfs_bmbt_irec	imap;
+	int			error;
+
+	if (!xfs_sb_version_hasrmapbt(&mp->m_sb) || mp->m_sb.sb_rblocks == 0)
+		return 0;
+
+	error = rmap_init_cursor(NULLAGNUMBER, &rmap_cur);
+	if (error) {
+		error = -ENOMEM;
+		goto out;
+	}
+
+	error = -libxfs_iget(mp, NULL, mp->m_sb.sb_rrmapino, 0, &ip, 0);
+	if (error)
+		goto out_inode;
+
+	mp->m_rrmapip = ip;
+	fakei.i_d.di_flags = XFS_DIFLAG_REALTIME;
+	fakei.i_d.di_flags2 = 0;
+
+	libxfs_defer_init(&dfops, &firstfsb);
+	while ((rm_rec = pop_slab_cursor(rmap_cur))) {
+		imap.br_startoff = rm_rec->rm_offset;
+		imap.br_startblock = rm_rec->rm_startblock;
+		imap.br_blockcount = rm_rec->rm_blockcount;
+		imap.br_state = (rm_rec->rm_flags & XFS_RMAP_UNWRITTEN ?
+				XFS_EXT_UNWRITTEN : XFS_EXT_NORM);
+		fakei.i_ino = rm_rec->rm_owner;
+		error = -libxfs_rmap_map_extent(mp, &dfops, &fakei,
+				XFS_DATA_FORK, &imap);
+		if (error)
+			goto out_defer;
+	}
+
+	error = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate, 0, 0, 0, &tp);
+	if (error)
+		goto out_defer;
+
+	error = -libxfs_defer_finish(&tp, &dfops, NULL);
+	if (error)
+		goto out_cancel;
+
+	error = -libxfs_trans_commit(tp);
+	goto out_inode;
+
+out_cancel:
+	libxfs_trans_cancel(tp);
+out_defer:
+	libxfs_defer_cancel(&dfops);
+out_inode:
+	mp->m_rrmapip = NULL;
+	IRELE(ip);
+out:
+	return error;
+}
diff --git a/repair/rmap.h b/repair/rmap.h
index 7069b6b..9fb6ba2 100644
--- a/repair/rmap.h
+++ b/repair/rmap.h
@@ -70,4 +70,6 @@ extern void rmap_store_agflcount(struct xfs_mount *, xfs_agnumber_t, int);
 	for ((agno) = NULLAGNUMBER; (agno) == NULLAGNUMBER || \
 	(agno) < (mp)->m_sb.sb_agcount; (agno)++)
 
+extern int rmap_populate_realtime_rmapbt(struct xfs_mount *mp);
+
 #endif /* RMAP_H_ */
diff --git a/repair/xfs_repair.c b/repair/xfs_repair.c
index 4d92b90..9a2f7c7 100644
--- a/repair/xfs_repair.c
+++ b/repair/xfs_repair.c
@@ -936,11 +936,14 @@ main(int argc, char **argv)
 	/*
 	 * Done with the block usage maps, toss them...
 	 */
-	rmaps_free(mp);
+	if (mp->m_sb.sb_rblocks == 0)
+		rmaps_free(mp);
 	free_bmaps(mp);
 
 	if (!bad_ino_btree)  {
 		phase6(mp);
+		if (mp->m_sb.sb_rblocks != 0)
+			rmaps_free(mp);
 		timestamp(PHASE_END, 6, NULL);
 
 		phase7(mp, phase2_threads);

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 29/29] mkfs: create the realtime rmap inode
  2016-08-25 23:58 [PATCH v8 00/29] xfsprogs: add realtime reverse-mapping support Darrick J. Wong
                   ` (27 preceding siblings ...)
  2016-08-26  0:01 ` [PATCH 28/29] xfs_repair: rebuild the realtime rmap btree Darrick J. Wong
@ 2016-08-26  0:01 ` Darrick J. Wong
  28 siblings, 0 replies; 30+ messages in thread
From: Darrick J. Wong @ 2016-08-26  0:01 UTC (permalink / raw)
  To: david, darrick.wong; +Cc: linux-xfs, xfs

Create a realtime rmapbt inode if we format the fs with realtime
and rmap.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 libxfs/libxfs_api_defs.h |    1 +
 mkfs/proto.c             |   51 +++++++++++++++++++++++++++++++---------------
 mkfs/xfs_mkfs.c          |   19 +++++++++++------
 3 files changed, 47 insertions(+), 24 deletions(-)


diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h
index 44b9065..e567076 100644
--- a/libxfs/libxfs_api_defs.h
+++ b/libxfs/libxfs_api_defs.h
@@ -145,5 +145,6 @@
 #define xfs_rtrmapbt_maxrecs		libxfs_rtrmapbt_maxrecs
 #define xfs_rtrmapbt_init_cursor	libxfs_rtrmapbt_init_cursor
 #define xfs_rmap_map_extent		libxfs_rmap_map_extent
+#define xfs_btree_compute_maxlevels	libxfs_btree_compute_maxlevels
 
 #endif /* __LIBXFS_API_DEFS_H__ */
diff --git a/mkfs/proto.c b/mkfs/proto.c
index 1de77f8..bf31483 100644
--- a/mkfs/proto.c
+++ b/mkfs/proto.c
@@ -626,24 +626,25 @@ parse_proto(
  */
 static void
 rtinit(
-	xfs_mount_t	*mp)
+	struct xfs_mount	*mp)
 {
-	xfs_fileoff_t	bno;
-	xfs_fileoff_t	ebno;
-	xfs_bmbt_irec_t	*ep;
-	int		error;
-	xfs_fsblock_t	first;
+	xfs_fileoff_t		bno;
+	xfs_fileoff_t		ebno;
+	struct xfs_bmbt_irec	*ep;
+	int			error;
+	xfs_fsblock_t		first;
 	struct xfs_defer_ops	dfops;
-	int		i;
-	xfs_bmbt_irec_t	map[XFS_BMAP_MAX_NMAP];
-	xfs_extlen_t	nsumblocks;
-	int		nmap;
-	xfs_inode_t	*rbmip;
-	xfs_inode_t	*rsumip;
-	xfs_trans_t	*tp;
-	struct cred	creds;
-	struct fsxattr	fsxattrs;
-	struct xfs_trans_res tres = {0};
+	int			i;
+	struct xfs_bmbt_irec	map[XFS_BMAP_MAX_NMAP];
+	xfs_extlen_t		nsumblocks;
+	int			nmap;
+	struct xfs_inode	*rbmip;
+	struct xfs_inode	*rsumip;
+	struct xfs_inode	*rrmapip;
+	struct xfs_trans	*tp;
+	struct cred		creds;
+	struct fsxattr		fsxattrs;
+	struct xfs_trans_res	tres = {0};
 
 	/*
 	 * First, allocate the inodes.
@@ -680,8 +681,24 @@ rtinit(
 	rsumip->i_d.di_size = mp->m_rsumsize;
 	libxfs_trans_log_inode(tp, rsumip, XFS_ILOG_CORE);
 	libxfs_log_sb(tp);
-	libxfs_trans_commit(tp);
 	mp->m_rsumip = rsumip;
+
+	/* If we have rmap and a realtime device, create a rtrmapbt inode. */
+	if (xfs_sb_version_hasrmapbt(&mp->m_sb) && mp->m_sb.sb_rblocks > 0) {
+		error = -libxfs_inode_alloc(&tp, NULL, S_IFREG, 1, 0,
+				&creds, &fsxattrs, &rrmapip);
+		if (error) {
+			fail(_("Realtime rmap inode allocation failed"), error);
+		}
+		mp->m_sb.sb_rrmapino = rrmapip->i_ino;
+		rrmapip->i_d.di_size = 0;
+		rrmapip->i_d.di_format = XFS_DINODE_FMT_RMAP;
+		libxfs_trans_log_inode(tp, rrmapip, XFS_ILOG_CORE);
+		libxfs_log_sb(tp);
+		mp->m_rrmapip = rrmapip;
+	}
+	libxfs_trans_commit(tp);
+
 	/*
 	 * Next, give the bitmap file some zero-filled blocks.
 	 */
diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
index fc565c0..e7bc044 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -2141,13 +2141,6 @@ _("reflink not supported without CRC support\n"));
 	}
 
 
-	if (sb_feat.rmapbt && xi.rtname) {
-		fprintf(stderr,
-_("rmapbt not supported with realtime devices\n"));
-		usage();
-		sb_feat.rmapbt = false;
-	}
-
 	if (nsflag || nlflag) {
 		if (dirblocksize < blocksize ||
 					dirblocksize > XFS_MAX_BLOCKSIZE) {
@@ -2908,6 +2901,18 @@ _("size %s specified for log subvolume is too large, maximum is %lld blocks\n"),
 		exit(1);
 	}
 
+	/* The realtime rmapbt mustn't grow taller than max btree height. */
+	if (xfs_sb_version_hasrtrmapbt(&mp->m_sb) &&
+	    libxfs_btree_compute_maxlevels(mp, mp->m_rtrmap_mnr,
+			mp->m_sb.sb_rblocks) > XFS_BTREE_MAXLEVELS) {
+		fprintf(stderr,
+_("%s: max realtime rmapbt height (%d) exceeds configured maximum (%d)\n"),
+			progname, libxfs_btree_compute_maxlevels(mp,
+			mp->m_rtrmap_mnr, mp->m_sb.sb_rblocks),
+			XFS_BTREE_MAXLEVELS);
+		exit(1);
+	}
+
 	/*
 	 * XXX: this code is effectively shared with the kernel growfs code.
 	 * These initialisations should be pulled into libxfs to keep the

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply related	[flat|nested] 30+ messages in thread

end of thread, other threads:[~2016-08-26  0:01 UTC | newest]

Thread overview: 30+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-08-25 23:58 [PATCH v8 00/29] xfsprogs: add realtime reverse-mapping support Darrick J. Wong
2016-08-25 23:58 ` [PATCH 01/29] xfs: refactor long-format btree header verification routines Darrick J. Wong
2016-08-25 23:58 ` [PATCH 02/29] xfs: make iroot_realloc a btree function Darrick J. Wong
2016-08-25 23:58 ` [PATCH 03/29] xfs: support storing records in the inode core root Darrick J. Wong
2016-08-25 23:59 ` [PATCH 04/29] xfs: widen xfs_refcount_irec fields to handle realtime rmapbt Darrick J. Wong
2016-08-25 23:59 ` [PATCH 05/29] xfs: introduce realtime rmap btree definitions Darrick J. Wong
2016-08-25 23:59 ` [PATCH 06/29] xfs: define the on-disk realtime rmap btree format Darrick J. Wong
2016-08-25 23:59 ` [PATCH 07/29] xfs: realtime rmap btree transaction reservations Darrick J. Wong
2016-08-25 23:59 ` [PATCH 08/29] xfs: add realtime rmap btree operations Darrick J. Wong
2016-08-25 23:59 ` [PATCH 09/29] xfs: prepare rmap functions to deal with rtrmapbt Darrick J. Wong
2016-08-25 23:59 ` [PATCH 10/29] xfs: add a realtime flag to the rmap update log redo items Darrick J. Wong
2016-08-25 23:59 ` [PATCH 11/29] xfs: add realtime reverse map inode to superblock Darrick J. Wong
2016-08-25 23:59 ` [PATCH 12/29] xfs: wire up a new inode fork type for the realtime rmap Darrick J. Wong
2016-08-25 23:59 ` [PATCH 13/29] xfs: don't assume a left rmap when allocating a new rmap Darrick J. Wong
2016-08-26  0:00 ` [PATCH 14/29] xfs: wire up rmap map and unmap to the realtime rmapbt Darrick J. Wong
2016-08-26  0:00 ` [PATCH 15/29] xfs: scrub " Darrick J. Wong
2016-08-26  0:00 ` [PATCH 16/29] xfs_db: display the realtime rmap btree contents Darrick J. Wong
2016-08-26  0:00 ` [PATCH 17/29] xfs_db: support rudimentary checks of the rtrmap btree Darrick J. Wong
2016-08-26  0:00 ` [PATCH 18/29] xfs_db: copy the realtime rmap btree Darrick J. Wong
2016-08-26  0:00 ` [PATCH 19/29] xfs_db: make fsmap query the realtime reverse mapping tree Darrick J. Wong
2016-08-26  0:00 ` [PATCH 20/29] xfs_io: scrub the realtime rmap Darrick J. Wong
2016-08-26  0:00 ` [PATCH 21/29] xfs_repair: factor rrmapino into superblock size calculations Darrick J. Wong
2016-08-26  0:00 ` [PATCH 22/29] xfs_repair: pass private data pointer to scan_lbtree Darrick J. Wong
2016-08-26  0:01 ` [PATCH 23/29] xfs_repair: use realtime rmap btree data to check block types Darrick J. Wong
2016-08-26  0:01 ` [PATCH 24/29] xfs_repair: extend ag_rmap[] for realtime mapping collection Darrick J. Wong
2016-08-26  0:01 ` [PATCH 25/29] xfs_repair: collect relatime reverse-mapping data for refcount/rmap tree rebuilding Darrick J. Wong
2016-08-26  0:01 ` [PATCH 26/29] xfs_repair: check existing realtime rmapbt entries against observed rmaps Darrick J. Wong
2016-08-26  0:01 ` [PATCH 27/29] xfs_repair: find and mark the rtrmapbt inode Darrick J. Wong
2016-08-26  0:01 ` [PATCH 28/29] xfs_repair: rebuild the realtime rmap btree Darrick J. Wong
2016-08-26  0:01 ` [PATCH 29/29] mkfs: create the realtime rmap inode Darrick J. Wong

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.