Skip to content

Commit

Permalink
xfs: add repair helpers for the reverse mapping btree
Browse files Browse the repository at this point in the history
Add a couple of functions to the reverse mapping btree that will be used
to repair the rmapbt.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
  • Loading branch information
Darrick J. Wong committed May 16, 2018
1 parent 7f8f131 commit 4d4f86b
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 0 deletions.
81 changes: 81 additions & 0 deletions fs/xfs/libxfs/xfs_rmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -2032,6 +2032,34 @@ xfs_rmap_map_shared(
return error;
}

/* Insert a raw rmap into the rmapbt. */
int
xfs_rmap_map_raw(
struct xfs_btree_cur *cur,
struct xfs_rmap_irec *rmap)
{
struct xfs_owner_info oinfo;

oinfo.oi_owner = rmap->rm_owner;
oinfo.oi_offset = rmap->rm_offset;
oinfo.oi_flags = 0;
if (rmap->rm_flags & XFS_RMAP_ATTR_FORK)
oinfo.oi_flags |= XFS_OWNER_INFO_ATTR_FORK;
if (rmap->rm_flags & XFS_RMAP_BMBT_BLOCK)
oinfo.oi_flags |= XFS_OWNER_INFO_BMBT_BLOCK;

if (rmap->rm_flags || XFS_RMAP_NON_INODE_OWNER(rmap->rm_owner))
return xfs_rmap_map(cur, rmap->rm_startblock,
rmap->rm_blockcount,
rmap->rm_flags & XFS_RMAP_UNWRITTEN,
&oinfo);

return xfs_rmap_map_shared(cur, rmap->rm_startblock,
rmap->rm_blockcount,
rmap->rm_flags & XFS_RMAP_UNWRITTEN,
&oinfo);
}

struct xfs_rmap_query_range_info {
xfs_rmap_query_range_fn fn;
void *priv;
Expand Down Expand Up @@ -2455,3 +2483,56 @@ xfs_rmap_record_exists(
irec.rm_startblock + irec.rm_blockcount >= bno + len);
return 0;
}

struct xfs_rmap_key_state {
uint64_t owner;
uint64_t offset;
unsigned int flags;
bool has_rmap;
};

/* For each rmap given, figure out if it doesn't match the key we want. */
STATIC int
xfs_rmap_has_other_keys_helper(
struct xfs_btree_cur *cur,
struct xfs_rmap_irec *rec,
void *priv)
{
struct xfs_rmap_key_state *rks = priv;

if (rks->owner == rec->rm_owner && rks->offset == rec->rm_offset &&
((rks->flags & rec->rm_flags) & XFS_RMAP_KEY_FLAGS) == rks->flags)
return 0;
rks->has_rmap = true;
return XFS_BTREE_QUERY_RANGE_ABORT;
}

/*
* Given an extent and some owner info, can we find records overlapping
* the extent whose owner info does not match the given owner?
*/
int
xfs_rmap_has_other_keys(
struct xfs_btree_cur *cur,
xfs_agblock_t bno,
xfs_extlen_t len,
struct xfs_owner_info *oinfo,
bool *has_rmap)
{
struct xfs_rmap_irec low = {0};
struct xfs_rmap_irec high;
struct xfs_rmap_key_state rks;
int error;

xfs_owner_info_unpack(oinfo, &rks.owner, &rks.offset, &rks.flags);
rks.has_rmap = false;

low.rm_startblock = bno;
memset(&high, 0xFF, sizeof(high));
high.rm_startblock = bno + len - 1;

error = xfs_rmap_query_range(cur, &low, &high,
xfs_rmap_has_other_keys_helper, &rks);
*has_rmap = rks.has_rmap;
return error;
}
4 changes: 4 additions & 0 deletions fs/xfs/libxfs/xfs_rmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -238,5 +238,9 @@ int xfs_rmap_has_record(struct xfs_btree_cur *cur, xfs_agblock_t bno,
int xfs_rmap_record_exists(struct xfs_btree_cur *cur, xfs_agblock_t bno,
xfs_extlen_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,
bool *has_rmap);
int xfs_rmap_map_raw(struct xfs_btree_cur *cur, struct xfs_rmap_irec *rmap);

#endif /* __XFS_RMAP_H__ */

0 comments on commit 4d4f86b

Please sign in to comment.