summaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
authorDarrick J. Wong <djwong@kernel.org>2021-09-01 11:16:08 -0700
committerDarrick J. Wong <djwong@kernel.org>2021-10-22 16:41:01 -0700
commitcabe272e498bbd7ea5b0823f52d494bc9f98c8de (patch)
tree1125b5182b13a3f7a1ecc0c1475f7ecd22fbd2c0 /fs
parentfe60bde58dabcf385e48735ae780df0b9246bb32 (diff)
xfs: prepare rmap functions to deal with rtrmapbt
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 <djwong@kernel.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/xfs/libxfs/xfs_rmap.c88
1 files changed, 63 insertions, 25 deletions
diff --git a/fs/xfs/libxfs/xfs_rmap.c b/fs/xfs/libxfs/xfs_rmap.c
index a24bed28ff17..6c817c9d8b9e 100644
--- a/fs/xfs/libxfs/xfs_rmap.c
+++ b/fs/xfs/libxfs/xfs_rmap.c
@@ -25,6 +25,15 @@
#include "xfs_ag.h"
#include "xfs_health.h"
+/* Return the maximum length of an rmap record. */
+static xfs_filblks_t
+xfs_rmap_len_max(
+ struct xfs_btree_cur *cur)
+{
+ return cur->bc_btnum == XFS_BTNUM_RTRMAP ?
+ 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.
@@ -99,11 +108,19 @@ xfs_rmap_update(
trace_xfs_rmap_update(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_btnum == XFS_BTNUM_RTRMAP) {
+ 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, error, _RET_IP_);
@@ -198,11 +215,20 @@ xfs_rmap_btrec_to_irec(
{
int error;
- 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);
- error = xfs_rmap_irec_offset_unpack(be64_to_cpu(rec->rmap.rm_offset),
- irec);
+ if (cur->bc_btnum == XFS_BTNUM_RTRMAP) {
+ 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);
+ error = 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);
+ error = xfs_rmap_irec_offset_unpack(
+ be64_to_cpu(rec->rmap.rm_offset), irec);
+ }
+
if (xfs_metadata_is_sick(error))
xfs_btree_mark_sick(cur);
return error;
@@ -218,13 +244,9 @@ xfs_rmap_get_rec(
int *stat)
{
struct xfs_mount *mp = cur->bc_mp;
- xfs_agnumber_t agno = cur->bc_ag.pag->pag_agno;
union xfs_btree_rec *rec;
int error;
- if (cur->bc_btnum != XFS_BTNUM_RMAP)
- goto out_bad_rec;
-
error = xfs_btree_get_rec(cur, &rec, stat);
if (error || !*stat)
return error;
@@ -234,12 +256,25 @@ xfs_rmap_get_rec(
if (irec->rm_blockcount == 0)
goto out_bad_rec;
- if (irec->rm_startblock <= XFS_AGFL_BLOCK(mp)) {
+ if (cur->bc_btnum == XFS_BTNUM_RTRMAP) {
+ if (!xfs_verify_rtbno(mp, irec->rm_startblock))
+ goto out_bad_rec;
+ if (irec->rm_startblock >
+ irec->rm_startblock + irec->rm_blockcount)
+ goto out_bad_rec;
+ if (!xfs_verify_rtbno(mp,
+ irec->rm_startblock + irec->rm_blockcount - 1))
+ goto out_bad_rec;
+ if (XFS_RMAP_NON_INODE_OWNER(irec->rm_owner))
+ goto out_bad_rec;
+ } else if (irec->rm_startblock <= XFS_AGFL_BLOCK(mp)) {
if (irec->rm_owner != XFS_RMAP_OWN_FS)
goto out_bad_rec;
if (irec->rm_blockcount != XFS_AGFL_BLOCK(mp) + 1)
goto out_bad_rec;
} else {
+ xfs_agnumber_t agno = cur->bc_ag.pag->pag_agno;
+
/* check for valid extent range, including overflow */
if (!xfs_verify_agbno(mp, agno, irec->rm_startblock))
goto out_bad_rec;
@@ -258,9 +293,13 @@ xfs_rmap_get_rec(
return 0;
out_bad_rec:
- xfs_warn(mp,
- "Reverse Mapping BTree record corruption in AG %d detected!",
- agno);
+ if (cur->bc_btnum == XFS_BTNUM_RTRMAP)
+ xfs_warn(mp,
+ "RT Reverse Mapping BTree record corruption detected!");
+ else
+ xfs_warn(mp,
+ "Reverse Mapping BTree record corruption in AG %d detected!",
+ cur->bc_ag.pag->pag_agno);
xfs_warn(mp,
"Owner 0x%llx, flags 0x%x, start block 0x%llx block count 0x%llx",
irec->rm_owner, irec->rm_flags, irec->rm_startblock,
@@ -922,8 +961,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.
@@ -1184,8 +1223,8 @@ 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(cur, state, _RET_IP_);
@@ -1650,8 +1689,8 @@ 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(cur, state, _RET_IP_);
@@ -2448,7 +2487,6 @@ xfs_rmap_finish_one(
goto out_drop;
}
-
/*
* If we haven't gotten a cursor or the cursor AG doesn't match
* the startblock, get one now.