* [PATCH 01/19] xfs: make iroot_realloc a btree function
2017-08-31 20:33 [PATCH v9 00/19] xfs: add realtime reverse-mapping support Darrick J. Wong
@ 2017-08-31 20:33 ` Darrick J. Wong
2017-08-31 20:33 ` [PATCH 02/19] xfs: support storing records in the inode core root Darrick J. Wong
` (17 subsequent siblings)
18 siblings, 0 replies; 20+ messages in thread
From: Darrick J. Wong @ 2017-08-31 20:33 UTC (permalink / raw)
To: darrick.wong; +Cc: linux-xfs
From: Darrick J. Wong <darrick.wong@oracle.com>
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>
---
fs/xfs/libxfs/xfs_bmap.c | 8 +-
fs/xfs/libxfs/xfs_bmap_btree.c | 137 ++++++++++++++++++++++++++++++++++++++++
fs/xfs/libxfs/xfs_bmap_btree.h | 2 +
fs/xfs/libxfs/xfs_btree.c | 12 +---
fs/xfs/libxfs/xfs_btree.h | 7 ++
fs/xfs/libxfs/xfs_inode_fork.c | 129 --------------------------------------
fs/xfs/libxfs/xfs_inode_fork.h | 1
7 files changed, 154 insertions(+), 142 deletions(-)
diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
index 2a58e1a..673b6b9 100644
--- a/fs/xfs/libxfs/xfs_bmap.c
+++ b/fs/xfs/libxfs/xfs_bmap.c
@@ -687,7 +687,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);
+ cur->bc_ops->iroot_realloc(cur, -1);
ASSERT(ifp->if_broot == NULL);
ASSERT((ifp->if_flags & XFS_IFBROOT) == 0);
XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_EXTENTS);
@@ -733,7 +733,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;
/*
@@ -773,13 +773,13 @@ xfs_bmap_extents_to_btree(
args.wasdel = wasdel;
*logflagsp = 0;
if ((error = xfs_alloc_vextent(&args))) {
- xfs_iroot_realloc(ip, -1, whichfork);
+ cur->bc_ops->iroot_realloc(cur, -1);
xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
return error;
}
if (WARN_ON_ONCE(args.fsbno == NULLFSBLOCK)) {
- xfs_iroot_realloc(ip, -1, whichfork);
+ cur->bc_ops->iroot_realloc(cur, -1);
xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
return -ENOSPC;
}
diff --git a/fs/xfs/libxfs/xfs_bmap_btree.c b/fs/xfs/libxfs/xfs_bmap_btree.c
index 0d5dd7b..4f2598a 100644
--- a/fs/xfs/libxfs/xfs_bmap_btree.c
+++ b/fs/xfs/libxfs/xfs_bmap_btree.c
@@ -617,6 +617,142 @@ 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));
+}
+
+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 void *
xfs_bmbt_verify(
struct xfs_buf *bp)
@@ -735,6 +871,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/fs/xfs/libxfs/xfs_bmap_btree.h b/fs/xfs/libxfs/xfs_bmap_btree.h
index d6dae86..9980c0d 100644
--- a/fs/xfs/libxfs/xfs_bmap_btree.h
+++ b/fs/xfs/libxfs/xfs_bmap_btree.h
@@ -148,5 +148,7 @@ static inline bool xfs_bmbt_validate_extent(struct xfs_mount *mp, int whichfork,
extern unsigned long long xfs_bmbt_calc_size(struct xfs_mount *mp,
unsigned long long len);
+extern void xfs_bmbt_iroot_realloc(struct xfs_inode *ip, int rec_diff,
+ int whichfork);
#endif /* __XFS_BMAP_BTREE_H__ */
diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c
index 277e2fc..3437905 100644
--- a/fs/xfs/libxfs/xfs_btree.c
+++ b/fs/xfs/libxfs/xfs_btree.c
@@ -3029,9 +3029,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);
@@ -3206,7 +3204,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 */
@@ -3625,8 +3623,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;
}
@@ -3840,8 +3837,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/fs/xfs/libxfs/xfs_btree.h b/fs/xfs/libxfs/xfs_btree.h
index 6b36f20..2636252 100644
--- a/fs/xfs/libxfs/xfs_btree.h
+++ b/fs/xfs/libxfs/xfs_btree.h
@@ -161,6 +161,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/fs/xfs/libxfs/xfs_inode_fork.c b/fs/xfs/libxfs/xfs_inode_fork.c
index ec9df5f..3ca2d0f 100644
--- a/fs/xfs/libxfs/xfs_inode_fork.c
+++ b/fs/xfs/libxfs/xfs_inode_fork.c
@@ -373,135 +373,6 @@ xfs_iread_extents(
ifp->if_flags |= XFS_IFEXTENTS;
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/fs/xfs/libxfs/xfs_inode_fork.h b/fs/xfs/libxfs/xfs_inode_fork.h
index abab8fb..bbf4ba7 100644
--- a/fs/xfs/libxfs/xfs_inode_fork.h
+++ b/fs/xfs/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);
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH 02/19] xfs: support storing records in the inode core root
2017-08-31 20:33 [PATCH v9 00/19] xfs: add realtime reverse-mapping support Darrick J. Wong
2017-08-31 20:33 ` [PATCH 01/19] xfs: make iroot_realloc a btree function Darrick J. Wong
@ 2017-08-31 20:33 ` Darrick J. Wong
2017-08-31 20:33 ` [PATCH 03/19] xfs: widen xfs_refcount_irec fields to handle realtime rmapbt Darrick J. Wong
` (16 subsequent siblings)
18 siblings, 0 replies; 20+ messages in thread
From: Darrick J. Wong @ 2017-08-31 20:33 UTC (permalink / raw)
To: darrick.wong; +Cc: linux-xfs
From: Darrick J. Wong <darrick.wong@oracle.com>
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>
---
fs/xfs/libxfs/xfs_btree.c | 201 +++++++++++++++++++++++++++++++++------------
fs/xfs/libxfs/xfs_btree.h | 1
2 files changed, 150 insertions(+), 52 deletions(-)
diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c
index 3437905..d0a357e 100644
--- a/fs/xfs/libxfs/xfs_btree.c
+++ b/fs/xfs/libxfs/xfs_btree.c
@@ -171,6 +171,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
@@ -1440,10 +1445,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);
}
@@ -2957,8 +2967,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 */
@@ -2974,10 +2987,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) {
@@ -3003,43 +3021,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);
@@ -3562,15 +3630,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;
@@ -3584,14 +3652,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;
/*
@@ -3622,30 +3695,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) {
@@ -3654,7 +3752,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/fs/xfs/libxfs/xfs_btree.h b/fs/xfs/libxfs/xfs_btree.h
index 2636252..39d2143 100644
--- a/fs/xfs/libxfs/xfs_btree.h
+++ b/fs/xfs/libxfs/xfs_btree.h
@@ -251,6 +251,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
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH 03/19] xfs: widen xfs_refcount_irec fields to handle realtime rmapbt
2017-08-31 20:33 [PATCH v9 00/19] xfs: add realtime reverse-mapping support Darrick J. Wong
2017-08-31 20:33 ` [PATCH 01/19] xfs: make iroot_realloc a btree function Darrick J. Wong
2017-08-31 20:33 ` [PATCH 02/19] xfs: support storing records in the inode core root Darrick J. Wong
@ 2017-08-31 20:33 ` Darrick J. Wong
2017-08-31 20:33 ` [PATCH 04/19] xfs: introduce realtime rmap btree definitions Darrick J. Wong
` (15 subsequent siblings)
18 siblings, 0 replies; 20+ messages in thread
From: Darrick J. Wong @ 2017-08-31 20:33 UTC (permalink / raw)
To: darrick.wong; +Cc: linux-xfs
From: Darrick J. Wong <darrick.wong@oracle.com>
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>
---
fs/xfs/libxfs/xfs_format.h | 4 +--
fs/xfs/libxfs/xfs_rmap.c | 70 ++++++++++++++++++++++----------------------
fs/xfs/libxfs/xfs_rmap.h | 32 ++++++++++----------
fs/xfs/scrub/ialloc.c | 2 +
fs/xfs/xfs_trace.h | 38 ++++++++++++------------
5 files changed, 73 insertions(+), 73 deletions(-)
diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h
index d4d9bef..294aa65 100644
--- a/fs/xfs/libxfs/xfs_format.h
+++ b/fs/xfs/libxfs/xfs_format.h
@@ -1435,8 +1435,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/fs/xfs/libxfs/xfs_rmap.c b/fs/xfs/libxfs/xfs_rmap.c
index d14af8b..a3c2cc9 100644
--- a/fs/xfs/libxfs/xfs_rmap.c
+++ b/fs/xfs/libxfs/xfs_rmap.c
@@ -46,8 +46,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,
@@ -68,8 +68,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,
@@ -115,8 +115,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)
@@ -151,8 +151,8 @@ xfs_rmap_insert(
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)
@@ -252,7 +252,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,
@@ -330,7 +330,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,
@@ -387,8 +387,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)
{
@@ -528,7 +528,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, <rec);
@@ -638,8 +638,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)
{
@@ -862,8 +862,8 @@ xfs_rmap_alloc(
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)
{
@@ -1287,8 +1287,8 @@ xfs_rmap_convert(
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)
{
@@ -1674,8 +1674,8 @@ xfs_rmap_convert_shared(
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)
{
@@ -1792,7 +1792,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,
@@ -1836,8 +1836,8 @@ xfs_rmap_unmap_shared(
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)
{
@@ -2104,7 +2104,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);
@@ -2292,8 +2292,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;
@@ -2316,8 +2316,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;
@@ -2366,8 +2366,8 @@ xfs_rmap_compare(
int
xfs_rmap_has_record(
struct xfs_btree_cur *cur,
- xfs_agblock_t bno,
- xfs_extlen_t len,
+ xfs_fsblock_t bno,
+ xfs_filblks_t len,
bool *exists)
{
union xfs_btree_irec low;
@@ -2385,8 +2385,8 @@ xfs_rmap_has_record(
int
xfs_rmap_record_exists(
struct xfs_btree_cur *cur,
- xfs_agblock_t bno,
- xfs_extlen_t len,
+ xfs_fsblock_t bno,
+ xfs_filblks_t len,
struct xfs_owner_info *oinfo,
bool *has_rmap)
{
@@ -2450,8 +2450,8 @@ xfs_rmap_has_other_keys_helper(
int
xfs_rmap_has_other_keys(
struct xfs_btree_cur *cur,
- xfs_agblock_t bno,
- xfs_extlen_t len,
+ xfs_fsblock_t bno,
+ xfs_filblks_t len,
struct xfs_owner_info *oinfo,
bool *has_rmap)
{
diff --git a/fs/xfs/libxfs/xfs_rmap.h b/fs/xfs/libxfs/xfs_rmap.h
index 180b127..6b32f65 100644
--- a/fs/xfs/libxfs/xfs_rmap.h
+++ b/fs/xfs/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);
@@ -195,10 +195,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,
@@ -208,10 +208,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);
int xfs_rmap_compare(const struct xfs_rmap_irec *a,
@@ -219,13 +219,13 @@ int xfs_rmap_compare(const struct xfs_rmap_irec *a,
union xfs_btree_rec;
int xfs_rmap_btrec_to_irec(union xfs_btree_rec *rec,
struct xfs_rmap_irec *irec);
-int xfs_rmap_has_record(struct xfs_btree_cur *cur, xfs_agblock_t bno,
- xfs_extlen_t len, bool *exists);
-int xfs_rmap_record_exists(struct xfs_btree_cur *cur, xfs_agblock_t bno,
- xfs_extlen_t len, struct xfs_owner_info *oinfo,
+int xfs_rmap_has_record(struct xfs_btree_cur *cur, xfs_fsblock_t bno,
+ xfs_filblks_t len, bool *exists);
+int xfs_rmap_record_exists(struct xfs_btree_cur *cur, xfs_fsblock_t bno,
+ xfs_filblks_t len, struct xfs_owner_info *oinfo,
bool *has_rmap);
-int xfs_rmap_has_other_keys(struct xfs_btree_cur *cur, xfs_agblock_t bno,
- xfs_extlen_t len, struct xfs_owner_info *oinfo,
+int xfs_rmap_has_other_keys(struct xfs_btree_cur *cur, xfs_fsblock_t bno,
+ xfs_filblks_t len, struct xfs_owner_info *oinfo,
bool *has_rmap);
int xfs_rmap_map_raw(struct xfs_btree_cur *cur, struct xfs_rmap_irec *rmap);
diff --git a/fs/xfs/scrub/ialloc.c b/fs/xfs/scrub/ialloc.c
index 7503ade..c7228dc 100644
--- a/fs/xfs/scrub/ialloc.c
+++ b/fs/xfs/scrub/ialloc.c
@@ -565,7 +565,7 @@ xfs_repair_ialloc_extent_fn(
blks_per_cluster = xfs_icluster_size_fsb(mp);
nr_inodes = XFS_OFFBNO_TO_AGINO(mp, blks_per_cluster, 0);
- if (rec->rm_startblock % blks_per_cluster != 0)
+ if ((unsigned int)rec->rm_startblock % blks_per_cluster != 0)
return -EFSCORRUPTED;
trace_xfs_repair_ialloc_extent_fn(mp, cur->bc_private.a.agno,
diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h
index bcc3cdf..0bc7494 100644
--- a/fs/xfs/xfs_trace.h
+++ b/fs/xfs/xfs_trace.h
@@ -2426,14 +2426,14 @@ DEFINE_BMAP_FREE_DEFERRED_EVENT(xfs_bmap_free_deferred);
/* rmap tracepoints */
DECLARE_EVENT_CLASS(xfs_rmap_class,
TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno,
- xfs_agblock_t agbno, xfs_extlen_t len, bool unwritten,
+ xfs_fsblock_t bno, xfs_filblks_t len, bool unwritten,
struct xfs_owner_info *oinfo),
- TP_ARGS(mp, agno, agbno, len, unwritten, oinfo),
+ TP_ARGS(mp, agno, bno, len, unwritten, oinfo),
TP_STRUCT__entry(
__field(dev_t, dev)
__field(xfs_agnumber_t, agno)
- __field(xfs_agblock_t, agbno)
- __field(xfs_extlen_t, len)
+ __field(xfs_fsblock_t, bno)
+ __field(xfs_filblks_t, len)
__field(uint64_t, owner)
__field(uint64_t, offset)
__field(unsigned long, flags)
@@ -2441,7 +2441,7 @@ DECLARE_EVENT_CLASS(xfs_rmap_class,
TP_fast_assign(
__entry->dev = mp->m_super->s_dev;
__entry->agno = agno;
- __entry->agbno = agbno;
+ __entry->bno = bno;
__entry->len = len;
__entry->owner = oinfo->oi_owner;
__entry->offset = oinfo->oi_offset;
@@ -2449,10 +2449,10 @@ DECLARE_EVENT_CLASS(xfs_rmap_class,
if (unwritten)
__entry->flags |= XFS_RMAP_UNWRITTEN;
),
- TP_printk("dev %d:%d agno %u agbno %u len %u owner %lld offset %llu flags 0x%lx",
+ TP_printk("dev %d:%d agno %d bno %llu len %llu owner %lld offset %llu flags 0x%lx",
MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->agno,
- __entry->agbno,
+ __entry->bno,
__entry->len,
__entry->owner,
__entry->offset,
@@ -2461,9 +2461,9 @@ DECLARE_EVENT_CLASS(xfs_rmap_class,
#define DEFINE_RMAP_EVENT(name) \
DEFINE_EVENT(xfs_rmap_class, name, \
TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, \
- xfs_agblock_t agbno, xfs_extlen_t len, bool unwritten, \
+ xfs_fsblock_t bno, xfs_filblks_t len, bool unwritten, \
struct xfs_owner_info *oinfo), \
- TP_ARGS(mp, agno, agbno, len, unwritten, oinfo))
+ TP_ARGS(mp, agno, bno, len, unwritten, oinfo))
/* simple AG-based error/%ip tracepoint class */
DECLARE_EVENT_CLASS(xfs_ag_error_class,
@@ -2482,7 +2482,7 @@ DECLARE_EVENT_CLASS(xfs_ag_error_class,
__entry->error = error;
__entry->caller_ip = caller_ip;
),
- TP_printk("dev %d:%d agno %u error %d caller %ps",
+ TP_printk("dev %d:%d agno %d error %d caller %ps",
MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->agno,
__entry->error,
@@ -2508,14 +2508,14 @@ DEFINE_AG_ERROR_EVENT(xfs_rmap_convert_state);
DECLARE_EVENT_CLASS(xfs_rmapbt_class,
TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno,
- xfs_agblock_t agbno, xfs_extlen_t len,
+ xfs_fsblock_t bno, xfs_filblks_t len,
uint64_t owner, uint64_t offset, unsigned int flags),
- TP_ARGS(mp, agno, agbno, len, owner, offset, flags),
+ TP_ARGS(mp, agno, bno, len, owner, offset, flags),
TP_STRUCT__entry(
__field(dev_t, dev)
__field(xfs_agnumber_t, agno)
- __field(xfs_agblock_t, agbno)
- __field(xfs_extlen_t, len)
+ __field(xfs_fsblock_t, bno)
+ __field(xfs_filblks_t, len)
__field(uint64_t, owner)
__field(uint64_t, offset)
__field(unsigned int, flags)
@@ -2523,16 +2523,16 @@ DECLARE_EVENT_CLASS(xfs_rmapbt_class,
TP_fast_assign(
__entry->dev = mp->m_super->s_dev;
__entry->agno = agno;
- __entry->agbno = agbno;
+ __entry->bno = bno;
__entry->len = len;
__entry->owner = owner;
__entry->offset = offset;
__entry->flags = flags;
),
- TP_printk("dev %d:%d agno %u agbno %u len %u owner %lld offset %llu flags 0x%x",
+ TP_printk("dev %d:%d agno %d bno %llu len %llu owner %lld offset %llu flags 0x%x",
MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->agno,
- __entry->agbno,
+ __entry->bno,
__entry->len,
__entry->owner,
__entry->offset,
@@ -2541,9 +2541,9 @@ DECLARE_EVENT_CLASS(xfs_rmapbt_class,
#define DEFINE_RMAPBT_EVENT(name) \
DEFINE_EVENT(xfs_rmapbt_class, name, \
TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, \
- xfs_agblock_t agbno, xfs_extlen_t len, \
+ xfs_fsblock_t bno, xfs_filblks_t len, \
uint64_t owner, uint64_t offset, unsigned int flags), \
- TP_ARGS(mp, agno, agbno, len, owner, offset, flags))
+ TP_ARGS(mp, agno, bno, len, owner, offset, flags))
#define DEFINE_RMAP_DEFERRED_EVENT DEFINE_MAP_EXTENT_DEFERRED_EVENT
DEFINE_RMAP_DEFERRED_EVENT(xfs_rmap_defer);
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH 04/19] xfs: introduce realtime rmap btree definitions
2017-08-31 20:33 [PATCH v9 00/19] xfs: add realtime reverse-mapping support Darrick J. Wong
` (2 preceding siblings ...)
2017-08-31 20:33 ` [PATCH 03/19] xfs: widen xfs_refcount_irec fields to handle realtime rmapbt Darrick J. Wong
@ 2017-08-31 20:33 ` Darrick J. Wong
2017-08-31 20:33 ` [PATCH 05/19] xfs: define the on-disk realtime rmap btree format Darrick J. Wong
` (14 subsequent siblings)
18 siblings, 0 replies; 20+ messages in thread
From: Darrick J. Wong @ 2017-08-31 20:33 UTC (permalink / raw)
To: darrick.wong; +Cc: linux-xfs
From: Darrick J. Wong <darrick.wong@oracle.com>
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>
---
fs/xfs/libxfs/xfs_btree.c | 4 ++--
fs/xfs/libxfs/xfs_btree.h | 1 +
fs/xfs/libxfs/xfs_format.h | 7 +++++++
fs/xfs/libxfs/xfs_types.h | 3 ++-
4 files changed, 12 insertions(+), 3 deletions(-)
diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c
index d0a357e..c0614e4 100644
--- a/fs/xfs/libxfs/xfs_btree.c
+++ b/fs/xfs/libxfs/xfs_btree.c
@@ -45,10 +45,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 }
};
uint32_t
diff --git a/fs/xfs/libxfs/xfs_btree.h b/fs/xfs/libxfs/xfs_btree.h
index 39d2143..e7bbf760 100644
--- a/fs/xfs/libxfs/xfs_btree.h
+++ b/fs/xfs/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)
uint32_t xfs_btree_magic(int crc, xfs_btnum_t btnum);
diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h
index 294aa65..c9138d5 100644
--- a/fs/xfs/libxfs/xfs_format.h
+++ b/fs/xfs/libxfs/xfs_format.h
@@ -1462,6 +1462,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/fs/xfs/libxfs/xfs_types.h b/fs/xfs/libxfs/xfs_types.h
index 0220159..9fa4236 100644
--- a/fs/xfs/libxfs/xfs_types.h
+++ b/fs/xfs/libxfs/xfs_types.h
@@ -112,7 +112,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 {
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH 05/19] xfs: define the on-disk realtime rmap btree format
2017-08-31 20:33 [PATCH v9 00/19] xfs: add realtime reverse-mapping support Darrick J. Wong
` (3 preceding siblings ...)
2017-08-31 20:33 ` [PATCH 04/19] xfs: introduce realtime rmap btree definitions Darrick J. Wong
@ 2017-08-31 20:33 ` Darrick J. Wong
2017-08-31 20:34 ` [PATCH 06/19] xfs: realtime rmap btree transaction reservations Darrick J. Wong
` (13 subsequent siblings)
18 siblings, 0 replies; 20+ messages in thread
From: Darrick J. Wong @ 2017-08-31 20:33 UTC (permalink / raw)
To: darrick.wong; +Cc: linux-xfs
From: Darrick J. Wong <darrick.wong@oracle.com>
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>
---
fs/xfs/Makefile | 1
fs/xfs/libxfs/xfs_btree.c | 1
fs/xfs/libxfs/xfs_btree.h | 3 +
fs/xfs/libxfs/xfs_format.h | 48 +++++++++
fs/xfs/libxfs/xfs_rtrmap_btree.c | 205 ++++++++++++++++++++++++++++++++++++++
fs/xfs/libxfs/xfs_rtrmap_btree.h | 62 +++++++++++
fs/xfs/libxfs/xfs_sb.c | 6 +
fs/xfs/libxfs/xfs_shared.h | 1
fs/xfs/xfs_mount.c | 2
fs/xfs/xfs_mount.h | 3 +
fs/xfs/xfs_ondisk.h | 2
11 files changed, 334 insertions(+)
create mode 100644 fs/xfs/libxfs/xfs_rtrmap_btree.c
create mode 100644 fs/xfs/libxfs/xfs_rtrmap_btree.h
diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile
index 2dc82d5..35a2ddf 100644
--- a/fs/xfs/Makefile
+++ b/fs/xfs/Makefile
@@ -56,6 +56,7 @@ xfs-y += $(addprefix libxfs/, \
xfs_ag_resv.o \
xfs_rmap.o \
xfs_rmap_btree.o \
+ xfs_rtrmap_btree.o \
xfs_refcount.o \
xfs_refcount_btree.o \
xfs_sb.o \
diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c
index c0614e4..b7a3589 100644
--- a/fs/xfs/libxfs/xfs_btree.c
+++ b/fs/xfs/libxfs/xfs_btree.c
@@ -1240,6 +1240,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/fs/xfs/libxfs/xfs_btree.h b/fs/xfs/libxfs/xfs_btree.h
index e7bbf760..44a14b7 100644
--- a/fs/xfs/libxfs/xfs_btree.h
+++ b/fs/xfs/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/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h
index c9138d5..c5760ca 100644
--- a/fs/xfs/libxfs/xfs_format.h
+++ b/fs/xfs/libxfs/xfs_format.h
@@ -1469,6 +1469,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/fs/xfs/libxfs/xfs_rtrmap_btree.c b/fs/xfs/libxfs/xfs_rtrmap_btree.c
new file mode 100644
index 0000000..c65db0b
--- /dev/null
+++ b/fs/xfs/libxfs/xfs_rtrmap_btree.c
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2017 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 "xfs.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_error.h"
+#include "xfs_extent_busy.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 void *
+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);
+ void *failed_at;
+ int level;
+
+ if (block->bb_magic != cpu_to_be32(XFS_RTRMAP_CRC_MAGIC))
+ return __this_address;
+
+ if (!xfs_sb_version_hasrmapbt(&mp->m_sb))
+ return __this_address;
+ if ((failed_at = xfs_btree_lblock_v5hdr_verify(bp,
+ XFS_RMAP_OWN_UNKNOWN)))
+ return failed_at;
+ level = be16_to_cpu(block->bb_level);
+ if (level > mp->m_rtrmap_maxlevels)
+ return __this_address;
+
+ return xfs_btree_lblock_verify(bp, mp->m_rtrmap_mxr[level != 0]);
+}
+
+static void
+xfs_rtrmapbt_read_verify(
+ struct xfs_buf *bp)
+{
+ void *failed_at = __this_address;
+
+ if (!xfs_btree_lblock_verify_crc(bp))
+ xfs_buf_ioerror(bp, -EFSBADCRC);
+ else if ((failed_at = xfs_rtrmapbt_verify(bp)))
+ xfs_buf_ioerror(bp, -EFSCORRUPTED);
+
+ if (bp->b_error) {
+ trace_xfs_btree_corrupt(bp, _RET_IP_);
+ xfs_verifier_error(bp, failed_at);
+ }
+}
+
+static void
+xfs_rtrmapbt_write_verify(
+ struct xfs_buf *bp)
+{
+ void *failed_at;
+
+ if ((failed_at = xfs_rtrmapbt_verify(bp))) {
+ trace_xfs_btree_corrupt(bp, _RET_IP_);
+ xfs_buf_ioerror(bp, -EFSCORRUPTED);
+ xfs_verifier_error(bp, failed_at);
+ 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,
+ .verify_struct = xfs_rtrmapbt_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_statoff = XFS_STATS_CALC_INDEX(xs_rmap_2);
+
+ 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/fs/xfs/libxfs/xfs_rtrmap_btree.h b/fs/xfs/libxfs/xfs_rtrmap_btree.h
new file mode 100644
index 0000000..9cc4f66
--- /dev/null
+++ b/fs/xfs/libxfs/xfs_rtrmap_btree.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2017 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/fs/xfs/libxfs/xfs_sb.c b/fs/xfs/libxfs/xfs_sb.c
index 9b49640..063ecfc 100644
--- a/fs/xfs/libxfs/xfs_sb.c
+++ b/fs/xfs/libxfs/xfs_sb.c
@@ -40,6 +40,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.
@@ -748,6 +749,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/fs/xfs/libxfs/xfs_shared.h b/fs/xfs/libxfs/xfs_shared.h
index 536fb35..3c5fe7d 100644
--- a/fs/xfs/libxfs/xfs_shared.h
+++ b/fs/xfs/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;
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index ea7d4b4..9caf1b1 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -46,6 +46,7 @@
#include "xfs_refcount_btree.h"
#include "xfs_reflink.h"
#include "xfs_extent_busy.h"
+#include "xfs_rtrmap_btree.h"
static DEFINE_MUTEX(xfs_uuid_table_mutex);
@@ -699,6 +700,7 @@ xfs_mountfs(
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);
xfs_set_maxicount(mp);
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index 37a6c97..72a5360 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -124,12 +124,15 @@ typedef struct xfs_mount {
uint m_inobt_mnr[2]; /* min inobt btree records */
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; /* max inobt btree levels. */
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/fs/xfs/xfs_ondisk.h b/fs/xfs/xfs_ondisk.h
index 0c381d7..88c771e 100644
--- a/fs/xfs/xfs_ondisk.h
+++ b/fs/xfs/xfs_ondisk.h
@@ -53,6 +53,8 @@ xfs_check_ondisk_structs(void)
XFS_CHECK_STRUCT_SIZE(struct xfs_refcount_rec, 12);
XFS_CHECK_STRUCT_SIZE(struct xfs_rmap_key, 20);
XFS_CHECK_STRUCT_SIZE(struct xfs_rmap_rec, 24);
+ XFS_CHECK_STRUCT_SIZE(struct xfs_rtrmap_key, 24);
+ XFS_CHECK_STRUCT_SIZE(struct xfs_rtrmap_rec, 32);
XFS_CHECK_STRUCT_SIZE(struct xfs_timestamp, 8);
XFS_CHECK_STRUCT_SIZE(xfs_alloc_key_t, 8);
XFS_CHECK_STRUCT_SIZE(xfs_alloc_ptr_t, 4);
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH 06/19] xfs: realtime rmap btree transaction reservations
2017-08-31 20:33 [PATCH v9 00/19] xfs: add realtime reverse-mapping support Darrick J. Wong
` (4 preceding siblings ...)
2017-08-31 20:33 ` [PATCH 05/19] xfs: define the on-disk realtime rmap btree format Darrick J. Wong
@ 2017-08-31 20:34 ` Darrick J. Wong
2017-08-31 20:34 ` [PATCH 07/19] xfs: add realtime rmap btree operations Darrick J. Wong
` (12 subsequent siblings)
18 siblings, 0 replies; 20+ messages in thread
From: Darrick J. Wong @ 2017-08-31 20:34 UTC (permalink / raw)
To: darrick.wong; +Cc: linux-xfs
From: Darrick J. Wong <darrick.wong@oracle.com>
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>
---
fs/xfs/libxfs/xfs_trans_resv.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/fs/xfs/libxfs/xfs_trans_resv.c b/fs/xfs/libxfs/xfs_trans_resv.c
index 6bd916b..cb9bc1a 100644
--- a/fs/xfs/libxfs/xfs_trans_resv.c
+++ b/fs/xfs/libxfs/xfs_trans_resv.c
@@ -83,7 +83,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);
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH 07/19] xfs: add realtime rmap btree operations
2017-08-31 20:33 [PATCH v9 00/19] xfs: add realtime reverse-mapping support Darrick J. Wong
` (5 preceding siblings ...)
2017-08-31 20:34 ` [PATCH 06/19] xfs: realtime rmap btree transaction reservations Darrick J. Wong
@ 2017-08-31 20:34 ` Darrick J. Wong
2017-08-31 20:34 ` [PATCH 08/19] xfs: prepare rmap functions to deal with rtrmapbt Darrick J. Wong
` (11 subsequent siblings)
18 siblings, 0 replies; 20+ messages in thread
From: Darrick J. Wong @ 2017-08-31 20:34 UTC (permalink / raw)
To: darrick.wong; +Cc: linux-xfs
From: Darrick J. Wong <darrick.wong@oracle.com>
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>
---
fs/xfs/libxfs/xfs_rtrmap_btree.c | 319 ++++++++++++++++++++++++++++++++++++++
1 file changed, 319 insertions(+)
diff --git a/fs/xfs/libxfs/xfs_rtrmap_btree.c b/fs/xfs/libxfs/xfs_rtrmap_btree.c
index c65db0b..31d61d3 100644
--- a/fs/xfs/libxfs/xfs_rtrmap_btree.c
+++ b/fs/xfs/libxfs/xfs_rtrmap_btree.c
@@ -31,12 +31,14 @@
#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_error.h"
#include "xfs_extent_busy.h"
#include "xfs_ag_resv.h"
+#include "xfs_bmap.h"
/*
* Realtime Reverse map btree.
@@ -70,6 +72,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 void *
xfs_rtrmapbt_verify(
struct xfs_buf *bp)
@@ -134,12 +405,60 @@ const struct xfs_buf_ops xfs_rtrmapbt_buf_ops = {
.verify_struct = xfs_rtrmapbt_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,
};
/*
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH 08/19] xfs: prepare rmap functions to deal with rtrmapbt
2017-08-31 20:33 [PATCH v9 00/19] xfs: add realtime reverse-mapping support Darrick J. Wong
` (6 preceding siblings ...)
2017-08-31 20:34 ` [PATCH 07/19] xfs: add realtime rmap btree operations Darrick J. Wong
@ 2017-08-31 20:34 ` Darrick J. Wong
2017-08-31 20:34 ` [PATCH 09/19] xfs: add a realtime flag to the rmap update log redo items Darrick J. Wong
` (10 subsequent siblings)
18 siblings, 0 replies; 20+ messages in thread
From: Darrick J. Wong @ 2017-08-31 20:34 UTC (permalink / raw)
To: darrick.wong; +Cc: linux-xfs
From: Darrick J. Wong <darrick.wong@oracle.com>
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>
---
fs/xfs/libxfs/xfs_rmap.c | 178 +++++++++++++++++++++++++++-------------------
fs/xfs/libxfs/xfs_rmap.h | 2 -
fs/xfs/scrub/rmap.c | 2 -
3 files changed, 108 insertions(+), 74 deletions(-)
diff --git a/fs/xfs/libxfs/xfs_rmap.c b/fs/xfs/libxfs/xfs_rmap.c
index a3c2cc9..bf63a25 100644
--- a/fs/xfs/libxfs/xfs_rmap.c
+++ b/fs/xfs/libxfs/xfs_rmap.c
@@ -39,6 +39,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.
@@ -96,19 +114,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;
}
@@ -124,7 +150,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);
@@ -144,7 +170,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;
}
@@ -160,7 +186,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);
@@ -175,22 +201,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);
+ }
}
/*
@@ -209,7 +244,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 {
@@ -228,7 +263,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);
@@ -280,7 +315,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);
@@ -288,7 +323,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;
@@ -304,7 +339,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);
@@ -353,14 +388,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;
@@ -407,7 +442,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);
/*
@@ -425,7 +460,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;
@@ -473,7 +508,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);
@@ -548,7 +583,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,
@@ -560,11 +595,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;
}
@@ -661,7 +696,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);
/*
@@ -680,7 +715,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);
@@ -707,7 +742,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(>rec, owner, flags))
@@ -734,8 +769,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.
@@ -746,7 +781,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,
@@ -794,7 +829,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)
@@ -802,11 +837,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;
}
@@ -886,7 +921,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);
/*
@@ -904,7 +939,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);
@@ -940,7 +975,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 &&
@@ -970,7 +1005,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 &&
@@ -984,11 +1019,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 */
@@ -1012,7 +1047,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);
@@ -1024,7 +1059,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);
@@ -1048,7 +1083,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);
@@ -1076,7 +1111,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);
@@ -1149,7 +1184,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)
@@ -1200,7 +1235,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)
@@ -1228,7 +1263,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);
@@ -1249,7 +1284,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)
@@ -1270,12 +1305,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;
}
@@ -1311,7 +1346,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);
/*
@@ -1365,7 +1400,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))
@@ -1377,11 +1412,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.
@@ -1648,12 +1683,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;
}
@@ -1691,7 +1726,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);
/*
@@ -1815,12 +1850,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;
}
@@ -1855,7 +1890,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? */
@@ -1878,7 +1913,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);
@@ -1968,12 +2003,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;
}
@@ -2021,7 +2056,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);
@@ -2117,13 +2152,12 @@ xfs_rmap_finish_one(
if (XFS_TEST_ERROR(false, mp,
XFS_ERRTAG_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/fs/xfs/libxfs/xfs_rmap.h b/fs/xfs/libxfs/xfs_rmap.h
index 6b32f65..8b1791e 100644
--- a/fs/xfs/libxfs/xfs_rmap.h
+++ b/fs/xfs/libxfs/xfs_rmap.h
@@ -217,7 +217,7 @@ int xfs_rmap_lookup_le_range(struct xfs_btree_cur *cur, xfs_fsblock_t bno,
int xfs_rmap_compare(const struct xfs_rmap_irec *a,
const struct xfs_rmap_irec *b);
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);
diff --git a/fs/xfs/scrub/rmap.c b/fs/xfs/scrub/rmap.c
index 9cc463b..4b8cf1a 100644
--- a/fs/xfs/scrub/rmap.c
+++ b/fs/xfs/scrub/rmap.c
@@ -324,7 +324,7 @@ xfs_scrub_rmapbt_helper(
bool has_inodes;
int error;
- error = xfs_rmap_btrec_to_irec(rec, &irec);
+ error = xfs_rmap_btrec_to_irec(bs->cur, rec, &irec);
if (!xfs_scrub_btree_op_ok(bs->sc, bs->cur, 0, &error))
goto out;
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH 09/19] xfs: add a realtime flag to the rmap update log redo items
2017-08-31 20:33 [PATCH v9 00/19] xfs: add realtime reverse-mapping support Darrick J. Wong
` (7 preceding siblings ...)
2017-08-31 20:34 ` [PATCH 08/19] xfs: prepare rmap functions to deal with rtrmapbt Darrick J. Wong
@ 2017-08-31 20:34 ` Darrick J. Wong
2017-08-31 20:34 ` [PATCH 10/19] xfs: add realtime rmap btree block detection to log recovery Darrick J. Wong
` (9 subsequent siblings)
18 siblings, 0 replies; 20+ messages in thread
From: Darrick J. Wong @ 2017-08-31 20:34 UTC (permalink / raw)
To: darrick.wong; +Cc: linux-xfs
From: Darrick J. Wong <darrick.wong@oracle.com>
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>
---
fs/xfs/libxfs/xfs_log_format.h | 4 +++-
fs/xfs/libxfs/xfs_rmap.c | 17 ++++++++++-------
fs/xfs/libxfs/xfs_rmap.h | 1 +
fs/xfs/xfs_rmap_item.c | 4 +++-
fs/xfs/xfs_trans.h | 2 +-
fs/xfs/xfs_trans_rmap.c | 9 +++++++--
6 files changed, 25 insertions(+), 12 deletions(-)
diff --git a/fs/xfs/libxfs/xfs_log_format.h b/fs/xfs/libxfs/xfs_log_format.h
index 8372e9b..73d3c65 100644
--- a/fs/xfs/libxfs/xfs_log_format.h
+++ b/fs/xfs/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/fs/xfs/libxfs/xfs_rmap.c b/fs/xfs/libxfs/xfs_rmap.c
index bf63a25..efcd63d 100644
--- a/fs/xfs/libxfs/xfs_rmap.c
+++ b/fs/xfs/libxfs/xfs_rmap.c
@@ -2246,11 +2246,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,
@@ -2264,6 +2266,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;
@@ -2283,7 +2286,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. */
@@ -2300,7 +2303,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. */
@@ -2317,7 +2320,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. */
@@ -2341,7 +2344,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. */
@@ -2365,7 +2368,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);
}
/* Compare rmap records. Returns -1 if a < b, 1 if a > b, and 0 if equal. */
diff --git a/fs/xfs/libxfs/xfs_rmap.h b/fs/xfs/libxfs/xfs_rmap.h
index 8b1791e..1e58e02 100644
--- a/fs/xfs/libxfs/xfs_rmap.h
+++ b/fs/xfs/libxfs/xfs_rmap.h
@@ -182,6 +182,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 */
diff --git a/fs/xfs/xfs_rmap_item.c b/fs/xfs/xfs_rmap_item.c
index f3b139c..13490b5 100644
--- a/fs/xfs/xfs_rmap_item.c
+++ b/fs/xfs/xfs_rmap_item.c
@@ -428,6 +428,7 @@ xfs_rui_recover(
xfs_exntst_t state;
struct xfs_trans *tp;
struct xfs_btree_cur *rcur = NULL;
+ bool rt;
ASSERT(!test_bit(XFS_RUI_RECOVERED, &ruip->rui_flags));
@@ -481,6 +482,7 @@ xfs_rui_recover(
XFS_EXT_UNWRITTEN : XFS_EXT_NORM;
whichfork = (rmap->me_flags & XFS_RMAP_EXTENT_ATTR_FORK) ?
XFS_ATTR_FORK : XFS_DATA_FORK;
+ rt = !!(rmap->me_flags & XFS_RMAP_EXTENT_REALTIME);
switch (rmap->me_flags & XFS_RMAP_EXTENT_TYPE_MASK) {
case XFS_RMAP_EXTENT_MAP:
type = XFS_RMAP_MAP;
@@ -513,7 +515,7 @@ xfs_rui_recover(
error = xfs_trans_log_finish_rmap_update(tp, rudp, type,
rmap->me_owner, whichfork,
rmap->me_startoff, rmap->me_startblock,
- rmap->me_len, state, &rcur);
+ rmap->me_len, state, rt, &rcur);
if (error)
goto abort_error;
diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h
index 6bdad6f..cef1971 100644
--- a/fs/xfs/xfs_trans.h
+++ b/fs/xfs/xfs_trans.h
@@ -247,7 +247,7 @@ int xfs_trans_log_finish_rmap_update(struct xfs_trans *tp,
struct xfs_rud_log_item *rudp, 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);
+ xfs_exntst_t state, bool rt, struct xfs_btree_cur **pcur);
/* refcount updates */
enum xfs_refcount_intent_type;
diff --git a/fs/xfs/xfs_trans_rmap.c b/fs/xfs/xfs_trans_rmap.c
index 9b577be..aab0d31 100644
--- a/fs/xfs/xfs_trans_rmap.c
+++ b/fs/xfs/xfs_trans_rmap.c
@@ -37,13 +37,16 @@ xfs_trans_set_rmap_flags(
struct xfs_map_extent *rmap,
enum xfs_rmap_intent_type type,
int whichfork,
- xfs_exntst_t state)
+ xfs_exntst_t state,
+ bool rt)
{
rmap->me_flags = 0;
if (state == XFS_EXT_UNWRITTEN)
rmap->me_flags |= XFS_RMAP_EXTENT_UNWRITTEN;
if (whichfork == XFS_ATTR_FORK)
rmap->me_flags |= XFS_RMAP_EXTENT_ATTR_FORK;
+ if (rt)
+ rmap->me_flags |= XFS_RMAP_EXTENT_REALTIME;
switch (type) {
case XFS_RMAP_MAP:
rmap->me_flags |= XFS_RMAP_EXTENT_MAP;
@@ -102,6 +105,7 @@ xfs_trans_log_finish_rmap_update(
xfs_fsblock_t startblock,
xfs_filblks_t blockcount,
xfs_exntst_t state,
+ bool rt,
struct xfs_btree_cur **pcur)
{
int error;
@@ -190,7 +194,7 @@ xfs_rmap_update_log_item(
map->me_startoff = rmap->ri_bmap.br_startoff;
map->me_len = rmap->ri_bmap.br_blockcount;
xfs_trans_set_rmap_flags(map, rmap->ri_type, rmap->ri_whichfork,
- rmap->ri_bmap.br_state);
+ rmap->ri_bmap.br_state, rmap->ri_realtime);
}
/* Get an RUD so we can process all the deferred rmap updates. */
@@ -223,6 +227,7 @@ xfs_rmap_update_finish_item(
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;
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH 10/19] xfs: add realtime rmap btree block detection to log recovery
2017-08-31 20:33 [PATCH v9 00/19] xfs: add realtime reverse-mapping support Darrick J. Wong
` (8 preceding siblings ...)
2017-08-31 20:34 ` [PATCH 09/19] xfs: add a realtime flag to the rmap update log redo items Darrick J. Wong
@ 2017-08-31 20:34 ` Darrick J. Wong
2017-08-31 20:34 ` [PATCH 11/19] xfs: add realtime reverse map inode to superblock Darrick J. Wong
` (8 subsequent siblings)
18 siblings, 0 replies; 20+ messages in thread
From: Darrick J. Wong @ 2017-08-31 20:34 UTC (permalink / raw)
To: darrick.wong; +Cc: linux-xfs
From: Darrick J. Wong <darrick.wong@oracle.com>
Identify rtrmapbt blocks in the log correctly so that we can
validate them during log recovery.
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
fs/xfs/xfs_log_recover.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
index 6c72bdf..cfe37fc 100644
--- a/fs/xfs/xfs_log_recover.c
+++ b/fs/xfs/xfs_log_recover.c
@@ -2257,6 +2257,7 @@ xlog_recover_get_buf_lsn(
uuid = &btb->bb_u.s.bb_uuid;
break;
}
+ case XFS_RTRMAP_CRC_MAGIC:
case XFS_BMAP_CRC_MAGIC:
case XFS_BMAP_MAGIC: {
struct xfs_btree_block *btb = blk;
@@ -2419,6 +2420,9 @@ xlog_recover_validate_buf_type(
case XFS_BMAP_MAGIC:
bp->b_ops = &xfs_bmbt_buf_ops;
break;
+ case XFS_RTRMAP_CRC_MAGIC:
+ bp->b_ops = &xfs_rtrmapbt_buf_ops;
+ break;
case XFS_RMAP_CRC_MAGIC:
bp->b_ops = &xfs_rmapbt_buf_ops;
break;
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH 11/19] xfs: add realtime reverse map inode to superblock
2017-08-31 20:33 [PATCH v9 00/19] xfs: add realtime reverse-mapping support Darrick J. Wong
` (9 preceding siblings ...)
2017-08-31 20:34 ` [PATCH 10/19] xfs: add realtime rmap btree block detection to log recovery Darrick J. Wong
@ 2017-08-31 20:34 ` Darrick J. Wong
2017-08-31 20:34 ` [PATCH 12/19] xfs: wire up a new inode fork type for the realtime rmap Darrick J. Wong
` (7 subsequent siblings)
18 siblings, 0 replies; 20+ messages in thread
From: Darrick J. Wong @ 2017-08-31 20:34 UTC (permalink / raw)
To: darrick.wong; +Cc: linux-xfs
From: Darrick J. Wong <darrick.wong@oracle.com>
Add a field to the superblock to record the rt rmapbt inode and load
it at mount time. The rtrmapbt inode will have a unique extent format
code, which means that we also have to update the inode validation and
flush routines to look for it.
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
fs/xfs/libxfs/xfs_format.h | 10 +++++++++-
fs/xfs/libxfs/xfs_inode_fork.c | 11 +++++++++++
fs/xfs/libxfs/xfs_rtrmap_btree.c | 2 +-
fs/xfs/libxfs/xfs_sb.c | 2 ++
fs/xfs/xfs_inode.c | 9 ++++++++-
fs/xfs/xfs_inode_item.c | 2 ++
fs/xfs/xfs_itable.c | 1 +
fs/xfs/xfs_log_recover.c | 13 ++++++++++++-
fs/xfs/xfs_mount.h | 1 +
fs/xfs/xfs_ondisk.h | 2 +-
fs/xfs/xfs_rtalloc.c | 21 +++++++++++++++++++++
11 files changed, 69 insertions(+), 5 deletions(-)
diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h
index c5760ca..bfa86f7 100644
--- a/fs/xfs/libxfs/xfs_format.h
+++ b/fs/xfs/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 &&
@@ -946,7 +953,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/fs/xfs/libxfs/xfs_inode_fork.c b/fs/xfs/libxfs/xfs_inode_fork.c
index 3ca2d0f..ad9e7a3 100644
--- a/fs/xfs/libxfs/xfs_inode_fork.c
+++ b/fs/xfs/libxfs/xfs_inode_fork.c
@@ -87,6 +87,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:
return -EFSCORRUPTED;
}
@@ -671,6 +678,10 @@ xfs_iflush_fork(
}
break;
+ case XFS_DINODE_FMT_RMAP:
+ /* to be implemented later */
+ break;
+
default:
ASSERT(0);
break;
diff --git a/fs/xfs/libxfs/xfs_rtrmap_btree.c b/fs/xfs/libxfs/xfs_rtrmap_btree.c
index 31d61d3..d640184 100644
--- a/fs/xfs/libxfs/xfs_rtrmap_btree.c
+++ b/fs/xfs/libxfs/xfs_rtrmap_btree.c
@@ -356,7 +356,7 @@ xfs_rtrmapbt_verify(
if (!xfs_sb_version_hasrmapbt(&mp->m_sb))
return __this_address;
if ((failed_at = xfs_btree_lblock_v5hdr_verify(bp,
- XFS_RMAP_OWN_UNKNOWN)))
+ mp->m_sb.sb_rrmapino)))
return failed_at;
level = be16_to_cpu(block->bb_level);
if (level > mp->m_rtrmap_maxlevels)
diff --git a/fs/xfs/libxfs/xfs_sb.c b/fs/xfs/libxfs/xfs_sb.c
index 063ecfc..84dba50 100644
--- a/fs/xfs/libxfs/xfs_sb.c
+++ b/fs/xfs/libxfs/xfs_sb.c
@@ -431,6 +431,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);
@@ -574,6 +575,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);
}
}
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index 4e05325..9207d61 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -3525,7 +3525,14 @@ xfs_iflush_int(
__func__, ip->i_ino, be16_to_cpu(dip->di_magic), dip);
goto corrupt_out;
}
- if (S_ISREG(VFS_I(ip)->i_mode)) {
+ if (ip->i_ino == mp->m_sb.sb_rrmapino) {
+ if (ip->i_d.di_format != XFS_DINODE_FMT_RMAP) {
+ xfs_alert_tag(mp, XFS_PTAG_IFLUSH,
+ "%s: Bad rtrmap inode %llu, ptr 0x%p",
+ __func__, ip->i_ino, ip);
+ goto corrupt_out;
+ }
+ } else if (S_ISREG(VFS_I(ip)->i_mode)) {
if (XFS_TEST_ERROR(
(ip->i_d.di_format != XFS_DINODE_FMT_EXTENTS) &&
(ip->i_d.di_format != XFS_DINODE_FMT_BTREE),
diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c
index 013cc78..d111240 100644
--- a/fs/xfs/xfs_inode_item.c
+++ b/fs/xfs/xfs_inode_item.c
@@ -56,6 +56,7 @@ xfs_inode_item_data_fork_size(
}
break;
case XFS_DINODE_FMT_BTREE:
+ case XFS_DINODE_FMT_RMAP:
if ((iip->ili_fields & XFS_ILOG_DBROOT) &&
ip->i_df.if_broot_bytes > 0) {
*nbytes += ip->i_df.if_broot_bytes;
@@ -179,6 +180,7 @@ xfs_inode_item_format_data_fork(
}
break;
case XFS_DINODE_FMT_BTREE:
+ case XFS_DINODE_FMT_RMAP:
iip->ili_fields &=
~(XFS_ILOG_DDATA | XFS_ILOG_DEXT |
XFS_ILOG_DEV | XFS_ILOG_UUID);
diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
index c393a2f..55642cd 100644
--- a/fs/xfs/xfs_itable.c
+++ b/fs/xfs/xfs_itable.c
@@ -37,6 +37,7 @@ xfs_internal_inum(
xfs_ino_t ino)
{
return (ino == mp->m_sb.sb_rbmino || ino == mp->m_sb.sb_rsumino ||
+ ino == mp->m_sb.sb_rrmapino ||
(xfs_sb_version_hasquota(&mp->m_sb) &&
xfs_is_quota_inode(&mp->m_sb, ino)));
}
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
index cfe37fc..f415a2b 100644
--- a/fs/xfs/xfs_log_recover.c
+++ b/fs/xfs/xfs_log_recover.c
@@ -3075,7 +3075,18 @@ xlog_recover_inode_pass2(
/* Take the opportunity to reset the flush iteration count */
ldip->di_flushiter = 0;
- if (unlikely(S_ISREG(ldip->di_mode))) {
+ if (in_f->ilf_ino == mp->m_sb.sb_rrmapino) {
+ if (ldip->di_format != XFS_DINODE_FMT_RMAP) {
+ XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(3)",
+ XFS_ERRLEVEL_LOW, mp, ldip);
+ xfs_alert(mp,
+ "%s: Bad rtrmapbt inode log record, rec ptr 0x%p, "
+ "ino ptr = 0x%p, ino bp = 0x%p, ino %Ld",
+ __func__, item, dip, bp, in_f->ilf_ino);
+ error = -EFSCORRUPTED;
+ goto out_release;
+ }
+ } else if (unlikely(S_ISREG(ldip->di_mode))) {
if ((ldip->di_format != XFS_DINODE_FMT_EXTENTS) &&
(ldip->di_format != XFS_DINODE_FMT_BTREE)) {
XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(3)",
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index 72a5360..7821b6e 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -103,6 +103,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; /* pointer to rmap inode */
struct xfs_inode *m_rootip; /* pointer to root directory */
struct xfs_quotainfo *m_quotainfo; /* disk quota information */
xfs_buftarg_t *m_ddev_targp; /* saves taking the address */
diff --git a/fs/xfs/xfs_ondisk.h b/fs/xfs/xfs_ondisk.h
index 88c771e..779b5f0 100644
--- a/fs/xfs/xfs_ondisk.h
+++ b/fs/xfs/xfs_ondisk.h
@@ -45,7 +45,7 @@ xfs_check_ondisk_structs(void)
XFS_CHECK_STRUCT_SIZE(struct xfs_dinode, 176);
XFS_CHECK_STRUCT_SIZE(struct xfs_disk_dquot, 104);
XFS_CHECK_STRUCT_SIZE(struct xfs_dqblk, 136);
- XFS_CHECK_STRUCT_SIZE(struct xfs_dsb, 264);
+ XFS_CHECK_STRUCT_SIZE(struct xfs_dsb, 272);
XFS_CHECK_STRUCT_SIZE(struct xfs_dsymlink_hdr, 56);
XFS_CHECK_STRUCT_SIZE(struct xfs_inobt_key, 4);
XFS_CHECK_STRUCT_SIZE(struct xfs_inobt_rec, 16);
diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c
index 9147219..5e14fd2 100644
--- a/fs/xfs/xfs_rtalloc.c
+++ b/fs/xfs/xfs_rtalloc.c
@@ -1227,6 +1227,25 @@ xfs_rtmount_inodes(
return error;
}
ASSERT(mp->m_rsumip != NULL);
+
+ /* If we have rmap and a realtime device, look for the rtrmapbt. */
+ if (xfs_sb_version_hasrmapbt(&mp->m_sb) && mp->m_sb.sb_rblocks > 0) {
+ ASSERT(sbp->sb_rrmapino != NULLFSINO);
+ error = xfs_iget(mp, NULL, sbp->sb_rrmapino, 0, 0,
+ &mp->m_rrmapip);
+ if (error) {
+ if (mp->m_rrmapip)
+ IRELE(mp->m_rrmapip);
+ return error;
+ }
+ ASSERT(mp->m_rrmapip != NULL);
+ if (mp->m_rrmapip->i_d.di_format != XFS_DINODE_FMT_RMAP) {
+ IRELE(mp->m_rrmapip);
+ mp->m_rrmapip = NULL;
+ return -EFSCORRUPTED;
+ }
+ }
+
return 0;
}
@@ -1234,6 +1253,8 @@ void
xfs_rtunmount_inodes(
struct xfs_mount *mp)
{
+ if (mp->m_rrmapip)
+ IRELE(mp->m_rrmapip);
if (mp->m_rbmip)
IRELE(mp->m_rbmip);
if (mp->m_rsumip)
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH 12/19] xfs: wire up a new inode fork type for the realtime rmap
2017-08-31 20:33 [PATCH v9 00/19] xfs: add realtime reverse-mapping support Darrick J. Wong
` (10 preceding siblings ...)
2017-08-31 20:34 ` [PATCH 11/19] xfs: add realtime reverse map inode to superblock Darrick J. Wong
@ 2017-08-31 20:34 ` Darrick J. Wong
2017-08-31 20:34 ` [PATCH 13/19] xfs: don't assume a left rmap when allocating a new rmap Darrick J. Wong
` (6 subsequent siblings)
18 siblings, 0 replies; 20+ messages in thread
From: Darrick J. Wong @ 2017-08-31 20:34 UTC (permalink / raw)
To: darrick.wong; +Cc: linux-xfs
From: Darrick J. Wong <darrick.wong@oracle.com>
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>
---
fs/xfs/libxfs/xfs_format.h | 8 +
fs/xfs/libxfs/xfs_inode_fork.c | 48 +++++++
fs/xfs/libxfs/xfs_rtrmap_btree.c | 248 ++++++++++++++++++++++++++++++++++++++
fs/xfs/libxfs/xfs_rtrmap_btree.h | 51 ++++++++
4 files changed, 353 insertions(+), 2 deletions(-)
diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h
index bfa86f7..ffc26bb 100644
--- a/fs/xfs/libxfs/xfs_format.h
+++ b/fs/xfs/libxfs/xfs_format.h
@@ -1477,6 +1477,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/fs/xfs/libxfs/xfs_inode_fork.c b/fs/xfs/libxfs/xfs_inode_fork.c
index ad9e7a3..e5ea9ae 100644
--- a/fs/xfs/libxfs/xfs_inode_fork.c
+++ b/fs/xfs/libxfs/xfs_inode_fork.c
@@ -37,12 +37,14 @@
#include "xfs_dir2_priv.h"
#include "xfs_attr_leaf.h"
#include "xfs_shared.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 *ip, struct xfs_dinode *dip);
/*
* Move inode type and inode format specific information from the
@@ -92,7 +94,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:
return -EFSCORRUPTED;
@@ -343,6 +345,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.
@@ -679,7 +712,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/fs/xfs/libxfs/xfs_rtrmap_btree.c b/fs/xfs/libxfs/xfs_rtrmap_btree.c
index d640184..0a4385b 100644
--- a/fs/xfs/libxfs/xfs_rtrmap_btree.c
+++ b/fs/xfs/libxfs/xfs_rtrmap_btree.c
@@ -224,6 +224,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,
@@ -341,6 +377,127 @@ 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));
+}
+
static void *
xfs_rtrmapbt_verify(
struct xfs_buf *bp)
@@ -450,12 +607,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,
@@ -522,3 +681,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_BTNUM_RTRMAP, 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/fs/xfs/libxfs/xfs_rtrmap_btree.h b/fs/xfs/libxfs/xfs_rtrmap_btree.h
index 9cc4f66..01bacb1 100644
--- a/fs/xfs/libxfs/xfs_rtrmap_btree.h
+++ b/fs/xfs/libxfs/xfs_rtrmap_btree.h
@@ -54,9 +54,60 @@ 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__ */
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH 13/19] xfs: don't assume a left rmap when allocating a new rmap
2017-08-31 20:33 [PATCH v9 00/19] xfs: add realtime reverse-mapping support Darrick J. Wong
` (11 preceding siblings ...)
2017-08-31 20:34 ` [PATCH 12/19] xfs: wire up a new inode fork type for the realtime rmap Darrick J. Wong
@ 2017-08-31 20:34 ` Darrick J. Wong
2017-08-31 20:34 ` [PATCH 14/19] xfs: wire up rmap map and unmap to the realtime rmapbt Darrick J. Wong
` (5 subsequent siblings)
18 siblings, 0 replies; 20+ messages in thread
From: Darrick J. Wong @ 2017-08-31 20:34 UTC (permalink / raw)
To: darrick.wong; +Cc: linux-xfs
From: Darrick J. Wong <darrick.wong@oracle.com>
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>
---
fs/xfs/libxfs/xfs_rmap.c | 24 ++++++++++++------------
1 file changed, 12 insertions(+), 12 deletions(-)
diff --git a/fs/xfs/libxfs/xfs_rmap.c b/fs/xfs/libxfs/xfs_rmap.c
index efcd63d..2ce9bf55 100644
--- a/fs/xfs/libxfs/xfs_rmap.c
+++ b/fs/xfs/libxfs/xfs_rmap.c
@@ -708,19 +708,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, <rec, &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, <rec, &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(<rec, owner, flags))
- have_lt = 0;
+ if (!xfs_rmap_is_mergeable(<rec, owner, flags))
+ have_lt = 0;
+ }
XFS_WANT_CORRUPTED_GOTO(mp,
have_lt == 0 ||
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH 14/19] xfs: wire up rmap map and unmap to the realtime rmapbt
2017-08-31 20:33 [PATCH v9 00/19] xfs: add realtime reverse-mapping support Darrick J. Wong
` (12 preceding siblings ...)
2017-08-31 20:34 ` [PATCH 13/19] xfs: don't assume a left rmap when allocating a new rmap Darrick J. Wong
@ 2017-08-31 20:34 ` Darrick J. Wong
2017-08-31 20:34 ` [PATCH 15/19] xfs: enable realtime rmap btree Darrick J. Wong
` (4 subsequent siblings)
18 siblings, 0 replies; 20+ messages in thread
From: Darrick J. Wong @ 2017-08-31 20:34 UTC (permalink / raw)
To: darrick.wong; +Cc: linux-xfs
From: Darrick J. Wong <darrick.wong@oracle.com>
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>
---
fs/xfs/libxfs/xfs_rmap.c | 64 ++++++++++++++++++++++++++++++----------------
fs/xfs/libxfs/xfs_rmap.h | 9 ++++--
fs/xfs/xfs_rmap_item.c | 8 +++++-
fs/xfs/xfs_trans.h | 9 ++++--
fs/xfs/xfs_trans_rmap.c | 7 +++--
5 files changed, 63 insertions(+), 34 deletions(-)
diff --git a/fs/xfs/libxfs/xfs_rmap.c b/fs/xfs/libxfs/xfs_rmap.c
index 2ce9bf55..c56a463 100644
--- a/fs/xfs/libxfs/xfs_rmap.c
+++ b/fs/xfs/libxfs/xfs_rmap.c
@@ -38,6 +38,7 @@
#include "xfs_extent_busy.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
@@ -2104,13 +2105,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);
}
@@ -2124,6 +2126,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,
@@ -2131,20 +2134,21 @@ 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;
struct xfs_btree_cur *rcur;
struct xfs_buf *agbp = NULL;
+ int lockmode;
int error = 0;
xfs_agnumber_t agno;
struct xfs_owner_info oinfo;
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);
@@ -2163,31 +2167,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) {
+ lockmode = XFS_ILOCK_EXCL | XFS_ILOCK_RTBITMAP;
+ xfs_ilock(mp->m_rrmapip, lockmode);
+ xfs_trans_ijoin(tp, mp->m_rrmapip, lockmode);
+ 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;
@@ -2196,6 +2214,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/fs/xfs/libxfs/xfs_rmap.h b/fs/xfs/libxfs/xfs_rmap.h
index 1e58e02..d8d5fbb 100644
--- a/fs/xfs/libxfs/xfs_rmap.h
+++ b/fs/xfs/libxfs/xfs_rmap.h
@@ -204,10 +204,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,
diff --git a/fs/xfs/xfs_rmap_item.c b/fs/xfs/xfs_rmap_item.c
index 13490b5..c453f03 100644
--- a/fs/xfs/xfs_rmap_item.c
+++ b/fs/xfs/xfs_rmap_item.c
@@ -429,6 +429,8 @@ xfs_rui_recover(
struct xfs_trans *tp;
struct xfs_btree_cur *rcur = NULL;
bool rt;
+ struct xfs_defer_ops dfops;
+ xfs_fsblock_t firstfsb;
ASSERT(!test_bit(XFS_RUI_RECOVERED, &ruip->rui_flags));
@@ -476,6 +478,7 @@ xfs_rui_recover(
return error;
rudp = xfs_trans_get_rud(tp, ruip);
+ xfs_defer_init(&dfops, &firstfsb);
for (i = 0; i < ruip->rui_format.rui_nextents; i++) {
rmap = &ruip->rui_format.rui_extents[i];
state = (rmap->me_flags & XFS_RMAP_EXTENT_UNWRITTEN) ?
@@ -512,7 +515,7 @@ xfs_rui_recover(
error = -EFSCORRUPTED;
goto abort_error;
}
- error = xfs_trans_log_finish_rmap_update(tp, rudp, type,
+ error = xfs_trans_log_finish_rmap_update(tp, &dfops, rudp, type,
rmap->me_owner, whichfork,
rmap->me_startoff, rmap->me_startblock,
rmap->me_len, state, rt, &rcur);
@@ -522,6 +525,9 @@ xfs_rui_recover(
}
xfs_rmap_finish_one_cleanup(tp, rcur, error);
+ error = xfs_defer_finish(&tp, &dfops, NULL);
+ if (error)
+ goto abort_error;
set_bit(XFS_RUI_RECOVERED, &ruip->rui_flags);
error = xfs_trans_commit(tp);
return error;
diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h
index cef1971..720f595 100644
--- a/fs/xfs/xfs_trans.h
+++ b/fs/xfs/xfs_trans.h
@@ -244,10 +244,11 @@ void xfs_rmap_update_init_defer_op(void);
struct xfs_rud_log_item *xfs_trans_get_rud(struct xfs_trans *tp,
struct xfs_rui_log_item *ruip);
int xfs_trans_log_finish_rmap_update(struct xfs_trans *tp,
- struct xfs_rud_log_item *rudp, 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 rt, struct xfs_btree_cur **pcur);
+ struct xfs_defer_ops *dfops, struct xfs_rud_log_item *rudp,
+ 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 rt,
+ struct xfs_btree_cur **pcur);
/* refcount updates */
enum xfs_refcount_intent_type;
diff --git a/fs/xfs/xfs_trans_rmap.c b/fs/xfs/xfs_trans_rmap.c
index aab0d31..746feec 100644
--- a/fs/xfs/xfs_trans_rmap.c
+++ b/fs/xfs/xfs_trans_rmap.c
@@ -97,6 +97,7 @@ xfs_trans_get_rud(
int
xfs_trans_log_finish_rmap_update(
struct xfs_trans *tp,
+ struct xfs_defer_ops *dfops,
struct xfs_rud_log_item *rudp,
enum xfs_rmap_intent_type type,
uint64_t owner,
@@ -110,8 +111,8 @@ xfs_trans_log_finish_rmap_update(
{
int error;
- error = xfs_rmap_finish_one(tp, type, owner, whichfork, startoff,
- startblock, blockcount, state, pcur);
+ error = xfs_rmap_finish_one(tp, dfops, type, owner, whichfork, startoff,
+ startblock, blockcount, state, rt, pcur);
/*
* Mark the transaction dirty, even on error. This ensures the
@@ -220,7 +221,7 @@ xfs_rmap_update_finish_item(
int error;
rmap = container_of(item, struct xfs_rmap_intent, ri_list);
- error = xfs_trans_log_finish_rmap_update(tp, done_item,
+ error = xfs_trans_log_finish_rmap_update(tp, dop, done_item,
rmap->ri_type,
rmap->ri_owner, rmap->ri_whichfork,
rmap->ri_bmap.br_startoff,
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH 15/19] xfs: enable realtime rmap btree
2017-08-31 20:33 [PATCH v9 00/19] xfs: add realtime reverse-mapping support Darrick J. Wong
` (13 preceding siblings ...)
2017-08-31 20:34 ` [PATCH 14/19] xfs: wire up rmap map and unmap to the realtime rmapbt Darrick J. Wong
@ 2017-08-31 20:34 ` Darrick J. Wong
2017-08-31 20:35 ` [PATCH 16/19] xfs: wire up getfsmap to the realtime reverse mapping btree Darrick J. Wong
` (3 subsequent siblings)
18 siblings, 0 replies; 20+ messages in thread
From: Darrick J. Wong @ 2017-08-31 20:34 UTC (permalink / raw)
To: darrick.wong; +Cc: linux-xfs
From: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
fs/xfs/xfs_super.c | 9 +--------
1 file changed, 1 insertion(+), 8 deletions(-)
diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c
index 5044352..fd31943 100644
--- a/fs/xfs/xfs_super.c
+++ b/fs/xfs/xfs_super.c
@@ -1662,16 +1662,9 @@ xfs_fs_fill_super(
"DAX and reflink have not been tested together!");
}
- if (xfs_sb_version_hasrmapbt(&mp->m_sb)) {
- if (mp->m_sb.sb_rblocks) {
- xfs_alert(mp,
- "EXPERIMENTAL reverse mapping btree not compatible with realtime device!");
- error = -EINVAL;
- goto out_filestream_unmount;
- }
+ if (xfs_sb_version_hasrmapbt(&mp->m_sb))
xfs_alert(mp,
"EXPERIMENTAL reverse mapping btree feature enabled. Use at your own risk!");
- }
if (xfs_sb_version_hasreflink(&mp->m_sb))
xfs_alert(mp,
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH 16/19] xfs: wire up getfsmap to the realtime reverse mapping btree
2017-08-31 20:33 [PATCH v9 00/19] xfs: add realtime reverse-mapping support Darrick J. Wong
` (14 preceding siblings ...)
2017-08-31 20:34 ` [PATCH 15/19] xfs: enable realtime rmap btree Darrick J. Wong
@ 2017-08-31 20:35 ` Darrick J. Wong
2017-08-31 20:35 ` [PATCH 17/19] xfs: scrub the realtime rmapbt Darrick J. Wong
` (2 subsequent siblings)
18 siblings, 0 replies; 20+ messages in thread
From: Darrick J. Wong @ 2017-08-31 20:35 UTC (permalink / raw)
To: darrick.wong; +Cc: linux-xfs
From: Darrick J. Wong <darrick.wong@oracle.com>
Connect the getfsmap ioctl to the realtime rmapbt.
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
fs/xfs/xfs_fsmap.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 64 insertions(+), 1 deletion(-)
diff --git a/fs/xfs/xfs_fsmap.c b/fs/xfs/xfs_fsmap.c
index 814ed729..b886e62 100644
--- a/fs/xfs/xfs_fsmap.c
+++ b/fs/xfs/xfs_fsmap.c
@@ -42,6 +42,7 @@
#include "xfs_refcount_btree.h"
#include "xfs_alloc_btree.h"
#include "xfs_rtalloc.h"
+#include "xfs_rtrmap_btree.h"
/* Convert an xfs_fsmap to an fsmap. */
void
@@ -562,6 +563,65 @@ xfs_getfsmap_rtdev_rtbitmap(
info);
}
+/* Transform a absolute-startblock rmap (rtdev, logdev) into a fsmap */
+STATIC int
+xfs_getfsmap_rtdev_helper(
+ struct xfs_btree_cur *cur,
+ struct xfs_rmap_irec *rec,
+ void *priv)
+{
+ struct xfs_mount *mp = cur->bc_mp;
+ struct xfs_getfsmap_info *info = priv;
+ xfs_daddr_t rec_daddr;
+
+ rec_daddr = XFS_FSB_TO_BB(mp, rec->rm_startblock);
+
+ return xfs_getfsmap_helper(cur->bc_tp, info, rec, rec_daddr);
+}
+
+/* Actually query the rtrmap btree. */
+STATIC int
+xfs_getfsmap_rtdev_rmapbt_query(
+ struct xfs_trans *tp,
+ struct xfs_getfsmap_info *info)
+{
+ struct xfs_mount *mp = tp->t_mountp;
+ struct xfs_btree_cur *bt_cur;
+ int error;
+
+ /* Query the rtrmapbt */
+ xfs_ilock(mp->m_rrmapip, XFS_ILOCK_SHARED);
+ bt_cur = xfs_rtrmapbt_init_cursor(mp, tp, mp->m_rrmapip);
+ error = xfs_rmap_query_range(bt_cur, &info->low, &info->high,
+ xfs_getfsmap_rtdev_helper, info);
+ if (error)
+ goto err;
+
+ /* Report any gaps at the end of the rtrmapbt */
+ info->last = true;
+ error = xfs_getfsmap_rtdev_helper(bt_cur, &info->high, info);
+ if (error)
+ goto err;
+
+err:
+ xfs_btree_del_cursor(bt_cur, error < 0 ? XFS_BTREE_ERROR :
+ XFS_BTREE_NOERROR);
+ xfs_iunlock(mp->m_rrmapip, XFS_ILOCK_SHARED);
+ return error;
+}
+
+/* Execute a getfsmap query against the realtime device rmapbt. */
+STATIC int
+xfs_getfsmap_rtdev_rmapbt(
+ struct xfs_trans *tp,
+ struct xfs_fsmap *keys,
+ struct xfs_getfsmap_info *info)
+{
+ info->missing_owner = XFS_FMR_OWN_FREE;
+ return __xfs_getfsmap_rtdev(tp, keys, xfs_getfsmap_rtdev_rmapbt_query,
+ info);
+}
+
/* Execute a getfsmap query against the regular data device. */
STATIC int
__xfs_getfsmap_datadev(
@@ -855,7 +915,10 @@ xfs_getfsmap(
}
if (mp->m_rtdev_targp) {
handlers[2].dev = new_encode_dev(mp->m_rtdev_targp->bt_dev);
- handlers[2].fn = xfs_getfsmap_rtdev_rtbitmap;
+ if (use_rmap)
+ handlers[2].fn = xfs_getfsmap_rtdev_rmapbt;
+ else
+ handlers[2].fn = xfs_getfsmap_rtdev_rtbitmap;
}
xfs_sort(handlers, XFS_GETFSMAP_DEVS, sizeof(struct xfs_getfsmap_dev),
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH 17/19] xfs: scrub the realtime rmapbt
2017-08-31 20:33 [PATCH v9 00/19] xfs: add realtime reverse-mapping support Darrick J. Wong
` (15 preceding siblings ...)
2017-08-31 20:35 ` [PATCH 16/19] xfs: wire up getfsmap to the realtime reverse mapping btree Darrick J. Wong
@ 2017-08-31 20:35 ` Darrick J. Wong
2017-08-31 20:35 ` [PATCH 18/19] xfs: cross-reference realtime bitmap to realtime rmapbt scrubber Darrick J. Wong
2017-08-31 20:35 ` [PATCH 19/19] xfs: cross-reference the realtime rmapbt Darrick J. Wong
18 siblings, 0 replies; 20+ messages in thread
From: Darrick J. Wong @ 2017-08-31 20:35 UTC (permalink / raw)
To: darrick.wong; +Cc: linux-xfs
From: Darrick J. Wong <darrick.wong@oracle.com>
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>
---
fs/xfs/Makefile | 5 ++
fs/xfs/libxfs/xfs_fs.h | 3 +
fs/xfs/scrub/bmap.c | 1
fs/xfs/scrub/common.h | 2 +
fs/xfs/scrub/rtrmap.c | 123 ++++++++++++++++++++++++++++++++++++++++++++++++
fs/xfs/scrub/scrub.c | 9 ++++
fs/xfs/scrub/scrub.h | 1
7 files changed, 142 insertions(+), 2 deletions(-)
create mode 100644 fs/xfs/scrub/rtrmap.c
diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile
index 35a2ddf..4336e14 100644
--- a/fs/xfs/Makefile
+++ b/fs/xfs/Makefile
@@ -163,6 +163,9 @@ xfs-y += $(addprefix scrub/, \
symlink.o \
)
-xfs-$(CONFIG_XFS_RT) += scrub/rtbitmap.o
+xfs-$(CONFIG_XFS_RT) += $(addprefix scrub/, \
+ rtbitmap.o \
+ rtrmap.o \
+ )
xfs-$(CONFIG_XFS_QUOTA) += scrub/quota.o
endif
diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h
index fba0105..eb8102c 100644
--- a/fs/xfs/libxfs/xfs_fs.h
+++ b/fs/xfs/libxfs/xfs_fs.h
@@ -507,9 +507,10 @@ struct xfs_scrub_metadata {
#define XFS_SCRUB_TYPE_UQUOTA 21 /* user quotas */
#define XFS_SCRUB_TYPE_GQUOTA 22 /* group quotas */
#define XFS_SCRUB_TYPE_PQUOTA 23 /* project quotas */
+#define XFS_SCRUB_TYPE_RTRMAPBT 24 /* realtime reverse mapping btree */
/* Number of scrub subcommands. */
-#define XFS_SCRUB_TYPE_NR 24
+#define XFS_SCRUB_TYPE_NR 25
/* i: Repair this metadata. */
#define XFS_SCRUB_IFLAG_REPAIR (1 << 0)
diff --git a/fs/xfs/scrub/bmap.c b/fs/xfs/scrub/bmap.c
index 7858a5e..438a8b6 100644
--- a/fs/xfs/scrub/bmap.c
+++ b/fs/xfs/scrub/bmap.c
@@ -509,6 +509,7 @@ xfs_scrub_bmap(
case XFS_DINODE_FMT_UUID:
case XFS_DINODE_FMT_DEV:
case XFS_DINODE_FMT_LOCAL:
+ case XFS_DINODE_FMT_RMAP:
/* No mappings to check. */
goto out_unlock;
case XFS_DINODE_FMT_EXTENTS:
diff --git a/fs/xfs/scrub/common.h b/fs/xfs/scrub/common.h
index bf844e5..aceb557 100644
--- a/fs/xfs/scrub/common.h
+++ b/fs/xfs/scrub/common.h
@@ -145,6 +145,8 @@ int xfs_scrub_setup_parent(struct xfs_scrub_context *sc,
struct xfs_inode *ip);
int xfs_scrub_setup_rt(struct xfs_scrub_context *sc, struct xfs_inode *ip);
int xfs_scrub_setup_quota(struct xfs_scrub_context *sc, struct xfs_inode *ip);
+int xfs_scrub_setup_rtrmapbt(struct xfs_scrub_context *sc,
+ struct xfs_inode *ip);
void xfs_scrub_ag_free(struct xfs_scrub_context *sc, struct xfs_scrub_ag *sa);
int xfs_scrub_ag_init(struct xfs_scrub_context *sc, xfs_agnumber_t agno,
diff --git a/fs/xfs/scrub/rtrmap.c b/fs/xfs/scrub/rtrmap.c
new file mode 100644
index 0000000..1480ea6
--- /dev/null
+++ b/fs/xfs/scrub/rtrmap.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2017 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 "xfs.h"
+#include "xfs_fs.h"
+#include "xfs_shared.h"
+#include "xfs_format.h"
+#include "xfs_trans_resv.h"
+#include "xfs_mount.h"
+#include "xfs_defer.h"
+#include "xfs_btree.h"
+#include "xfs_bit.h"
+#include "xfs_log_format.h"
+#include "xfs_trans.h"
+#include "xfs_sb.h"
+#include "xfs_rmap.h"
+#include "xfs_rmap_btree.h"
+#include "xfs_rtrmap_btree.h"
+#include "xfs_inode.h"
+#include "scrub/xfs_scrub.h"
+#include "scrub/scrub.h"
+#include "scrub/common.h"
+#include "scrub/btree.h"
+#include "scrub/trace.h"
+
+/* Set us up with the realtime metadata and AG headers locked. */
+int
+xfs_scrub_setup_rtrmapbt(
+ struct xfs_scrub_context *sc,
+ struct xfs_inode *ip)
+{
+ struct xfs_mount *mp = sc->mp;
+ int lockmode;
+ int error = 0;
+
+ if (sc->sm->sm_agno || sc->sm->sm_ino || sc->sm->sm_gen)
+ return -EINVAL;
+
+ error = xfs_scrub_setup_fs(sc, ip);
+ if (error)
+ return error;
+
+ lockmode = XFS_ILOCK_EXCL;
+ xfs_ilock(mp->m_rrmapip, lockmode);
+ xfs_trans_ijoin(sc->tp, mp->m_rrmapip, lockmode);
+
+ lockmode = XFS_ILOCK_EXCL | XFS_ILOCK_RTBITMAP;
+ xfs_ilock(mp->m_rbmip, lockmode);
+ xfs_trans_ijoin(sc->tp, mp->m_rbmip, lockmode);
+
+ return 0;
+}
+
+/* Realtime reverse mapping. */
+
+/* Scrub a realtime rmapbt record. */
+STATIC int
+xfs_scrub_rtrmapbt_helper(
+ struct xfs_scrub_btree *bs,
+ union xfs_btree_rec *rec)
+{
+ struct xfs_mount *mp = bs->cur->bc_mp;
+ struct xfs_rmap_irec irec;
+ unsigned long long rec_end;
+ bool non_inode;
+ bool is_bmbt;
+ bool is_attr;
+ int error;
+
+ error = xfs_rmap_btrec_to_irec(bs->cur, rec, &irec);
+ if (!xfs_scrub_btree_op_ok(bs->sc, bs->cur, 0, &error))
+ goto out;
+
+ rec_end = (unsigned long long)irec.rm_startblock + irec.rm_blockcount;
+ xfs_scrub_btree_check_ok(bs->sc, bs->cur, 0,
+ irec.rm_startblock < mp->m_sb.sb_rblocks &&
+ rec_end <= mp->m_sb.sb_rblocks);
+
+ non_inode = XFS_RMAP_NON_INODE_OWNER(irec.rm_owner);
+ is_bmbt = irec.rm_flags & XFS_RMAP_BMBT_BLOCK;
+ is_attr = irec.rm_flags & XFS_RMAP_ATTR_FORK;
+
+ xfs_scrub_btree_check_ok(bs->sc, bs->cur, 0,
+ !is_bmbt && !non_inode && !is_attr);
+
+out:
+ return error;
+}
+
+/* Scrub the realtime rmap btree. */
+int
+xfs_scrub_rtrmapbt(
+ struct xfs_scrub_context *sc)
+{
+ struct xfs_owner_info oinfo;
+ struct xfs_mount *mp = sc->mp;
+ struct xfs_btree_cur *cur;
+ int error;
+
+ cur = xfs_rtrmapbt_init_cursor(mp, sc->tp, mp->m_rrmapip);
+ xfs_rmap_ino_bmbt_owner(&oinfo, mp->m_sb.sb_rrmapino, XFS_DATA_FORK);
+ error = xfs_scrub_btree(sc, cur, xfs_scrub_rtrmapbt_helper,
+ &oinfo, NULL);
+ xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
+
+ return error;
+}
diff --git a/fs/xfs/scrub/scrub.c b/fs/xfs/scrub/scrub.c
index 7f9a4f8..ffb1465 100644
--- a/fs/xfs/scrub/scrub.c
+++ b/fs/xfs/scrub/scrub.c
@@ -343,6 +343,15 @@ static const struct xfs_scrub_meta_ops meta_scrub_ops[] = {
{ NULL },
{ NULL },
#endif
+#ifdef CONFIG_XFS_RT
+ { /* realtime rmapbt */
+ .setup = xfs_scrub_setup_rtrmapbt,
+ .scrub = xfs_scrub_rtrmapbt,
+ .has = xfs_sb_version_hasrtrmapbt,
+ },
+#else
+ { NULL },
+#endif
};
#if IS_ENABLED(CONFIG_XFS_ONLINE_REPAIR)
diff --git a/fs/xfs/scrub/scrub.h b/fs/xfs/scrub/scrub.h
index 41ec126..0fc334e 100644
--- a/fs/xfs/scrub/scrub.h
+++ b/fs/xfs/scrub/scrub.h
@@ -105,5 +105,6 @@ int xfs_scrub_parent(struct xfs_scrub_context *sc);
int xfs_scrub_rtbitmap(struct xfs_scrub_context *sc);
int xfs_scrub_rtsummary(struct xfs_scrub_context *sc);
int xfs_scrub_quota(struct xfs_scrub_context *sc);
+int xfs_scrub_rtrmapbt(struct xfs_scrub_context *sc);
#endif /* __XFS_SCRUB_SCRUB_H__ */
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH 18/19] xfs: cross-reference realtime bitmap to realtime rmapbt scrubber
2017-08-31 20:33 [PATCH v9 00/19] xfs: add realtime reverse-mapping support Darrick J. Wong
` (16 preceding siblings ...)
2017-08-31 20:35 ` [PATCH 17/19] xfs: scrub the realtime rmapbt Darrick J. Wong
@ 2017-08-31 20:35 ` Darrick J. Wong
2017-08-31 20:35 ` [PATCH 19/19] xfs: cross-reference the realtime rmapbt Darrick J. Wong
18 siblings, 0 replies; 20+ messages in thread
From: Darrick J. Wong @ 2017-08-31 20:35 UTC (permalink / raw)
To: darrick.wong; +Cc: linux-xfs
From: Darrick J. Wong <darrick.wong@oracle.com>
When we're checking the realtime rmapbt, cross-reference the entries
with the realtime bitmap too.
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
fs/xfs/scrub/rtrmap.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/fs/xfs/scrub/rtrmap.c b/fs/xfs/scrub/rtrmap.c
index 1480ea6..6862b54 100644
--- a/fs/xfs/scrub/rtrmap.c
+++ b/fs/xfs/scrub/rtrmap.c
@@ -33,6 +33,8 @@
#include "xfs_rmap_btree.h"
#include "xfs_rtrmap_btree.h"
#include "xfs_inode.h"
+#include "xfs_alloc.h"
+#include "xfs_rtalloc.h"
#include "scrub/xfs_scrub.h"
#include "scrub/scrub.h"
#include "scrub/common.h"
@@ -78,6 +80,7 @@ xfs_scrub_rtrmapbt_helper(
struct xfs_mount *mp = bs->cur->bc_mp;
struct xfs_rmap_irec irec;
unsigned long long rec_end;
+ bool is_free;
bool non_inode;
bool is_bmbt;
bool is_attr;
@@ -99,6 +102,12 @@ xfs_scrub_rtrmapbt_helper(
xfs_scrub_btree_check_ok(bs->sc, bs->cur, 0,
!is_bmbt && !non_inode && !is_attr);
+ /* Check the rtbitmap thinks it's free. */
+ error = xfs_rtalloc_extent_is_free(mp, bs->cur->bc_tp,
+ irec.rm_startblock, irec.rm_blockcount, &is_free);
+ if (xfs_scrub_should_xref(bs->sc, &error, NULL))
+ xfs_scrub_btree_xref_check_ok(bs->sc, bs->cur, 0, !is_free);
+
out:
return error;
}
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH 19/19] xfs: cross-reference the realtime rmapbt
2017-08-31 20:33 [PATCH v9 00/19] xfs: add realtime reverse-mapping support Darrick J. Wong
` (17 preceding siblings ...)
2017-08-31 20:35 ` [PATCH 18/19] xfs: cross-reference realtime bitmap to realtime rmapbt scrubber Darrick J. Wong
@ 2017-08-31 20:35 ` Darrick J. Wong
18 siblings, 0 replies; 20+ messages in thread
From: Darrick J. Wong @ 2017-08-31 20:35 UTC (permalink / raw)
To: darrick.wong; +Cc: linux-xfs
From: Darrick J. Wong <darrick.wong@oracle.com>
When we're scrubbing the realtime metadata, cross-reference
the rtrmapt.
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
fs/xfs/scrub/bmap.c | 12 ++++++++++
fs/xfs/scrub/rtbitmap.c | 54 +++++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 64 insertions(+), 2 deletions(-)
diff --git a/fs/xfs/scrub/bmap.c b/fs/xfs/scrub/bmap.c
index 438a8b6..d93b53f 100644
--- a/fs/xfs/scrub/bmap.c
+++ b/fs/xfs/scrub/bmap.c
@@ -36,6 +36,7 @@
#include "xfs_bmap_btree.h"
#include "xfs_rmap.h"
#include "xfs_rmap_btree.h"
+#include "xfs_rtrmap_btree.h"
#include "xfs_alloc.h"
#include "xfs_ialloc.h"
#include "xfs_refcount.h"
@@ -314,6 +315,7 @@ xfs_scrub_bmap_extent(
bool is_freesp;
bool has_inodes;
bool is_free = false;
+ int lockmode = 0;
int error = 0;
if (cur)
@@ -405,6 +407,14 @@ xfs_scrub_bmap_extent(
!has_inodes);
}
+ if (info->is_rt && xfs_sb_version_hasrtrmapbt(&mp->m_sb)) {
+ /* Set up the rtrmapbt cross-reference. */
+ lockmode = XFS_ILOCK_SHARED | XFS_ILOCK_RTBITMAP;
+ xfs_ilock(mp->m_rrmapip, lockmode);
+ sa.rmap_cur = xfs_rtrmapbt_init_cursor(mp, info->sc->tp,
+ mp->m_rrmapip);
+ }
+
/* Cross-reference with rmapbt. */
if (sa.rmap_cur)
xfs_scrub_bmap_xref_rmap(info, &sa, irec, bno);
@@ -417,6 +427,8 @@ xfs_scrub_bmap_extent(
xfs_scrub_bmap_xref_refc(info, &sa, irec, bno);
xfs_scrub_ag_free(info->sc, &sa);
+ if (lockmode)
+ xfs_iunlock(mp->m_rrmapip, lockmode);
out:
info->lastoff = irec->br_startoff + irec->br_blockcount;
return error;
diff --git a/fs/xfs/scrub/rtbitmap.c b/fs/xfs/scrub/rtbitmap.c
index e15f8f3..9b7fded 100644
--- a/fs/xfs/scrub/rtbitmap.c
+++ b/fs/xfs/scrub/rtbitmap.c
@@ -29,12 +29,16 @@
#include "xfs_log_format.h"
#include "xfs_trans.h"
#include "xfs_sb.h"
+#include "xfs_inode.h"
#include "xfs_alloc.h"
#include "xfs_rtalloc.h"
#include "xfs_inode.h"
+#include "xfs_rmap.h"
+#include "xfs_rtrmap_btree.h"
#include "scrub/xfs_scrub.h"
#include "scrub/scrub.h"
#include "scrub/common.h"
+#include "scrub/btree.h"
#include "scrub/trace.h"
/* Set us up with the realtime metadata locked. */
@@ -54,6 +58,12 @@ xfs_scrub_setup_rt(
if (error)
return error;
+ if (xfs_sb_version_hasrmapbt(&mp->m_sb)) {
+ lockmode = XFS_ILOCK_EXCL;
+ xfs_ilock(mp->m_rrmapip, lockmode);
+ xfs_trans_ijoin(sc->tp, mp->m_rrmapip, lockmode);
+ }
+
lockmode = XFS_ILOCK_EXCL | XFS_ILOCK_RTBITMAP;
xfs_ilock(mp->m_rbmip, lockmode);
xfs_trans_ijoin(sc->tp, mp->m_rbmip, lockmode);
@@ -63,6 +73,11 @@ xfs_scrub_setup_rt(
/* Realtime bitmap. */
+struct xfs_scrub_rtbitmap_info {
+ struct xfs_btree_cur *cur;
+ struct xfs_scrub_context *sc;
+};
+
/* Scrub a free extent record from the realtime bitmap. */
STATIC int
xfs_scrub_rtbitmap_helper(
@@ -70,7 +85,32 @@ xfs_scrub_rtbitmap_helper(
struct xfs_rtalloc_rec *rec,
void *priv)
{
- return 0;
+ struct xfs_mount *mp = tp->t_mountp;
+ struct xfs_scrub_rtbitmap_info *sri = priv;
+ struct xfs_scrub_context *sc = sri->sc;
+ struct xfs_buf *bp;
+ xfs_rtblock_t block;
+ bool has_rmap;
+ int error;
+
+ if (!sri->cur)
+ return 0;
+
+ /* Find the buffer for error reporting. */
+ block = XFS_BITTOBLOCK(mp, rec->ar_startblock);
+ error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
+ if (!xfs_scrub_op_ok(sc, 0, 0, &error))
+ goto out;
+
+ /* Cross-reference the rtrmapbt. */
+ error = xfs_rmap_has_record(sri->cur, rec->ar_startblock,
+ rec->ar_blockcount, &has_rmap);
+ if (xfs_scrub_should_xref(sc, &error, &sri->cur))
+ xfs_scrub_btree_xref_check_ok(sc, sri->cur, 0, !has_rmap);
+
+ xfs_trans_brelse(sc->tp, bp);
+out:
+ return error;
}
/* Scrub the realtime bitmap. */
@@ -78,13 +118,23 @@ int
xfs_scrub_rtbitmap(
struct xfs_scrub_context *sc)
{
+ struct xfs_mount *mp = sc->mp;
+ struct xfs_scrub_rtbitmap_info sri;
int error;
- error = xfs_rtalloc_query_all(sc->tp, xfs_scrub_rtbitmap_helper, NULL);
+ sri.sc = sc;
+ if (xfs_sb_version_hasrmapbt(&mp->m_sb))
+ sri.cur = xfs_rtrmapbt_init_cursor(mp, sc->tp, mp->m_rrmapip);
+ else
+ sri.cur = NULL;
+
+ error = xfs_rtalloc_query_all(sc->tp, xfs_scrub_rtbitmap_helper, &sri);
if (!xfs_scrub_fblock_op_ok(sc, XFS_DATA_FORK, 0, &error))
goto out;
out:
+ if (sri.cur)
+ xfs_btree_del_cursor(sri.cur, XFS_BTREE_ERROR);
return error;
}
^ permalink raw reply related [flat|nested] 20+ messages in thread