Skip to content

Commit 1c1646a

Browse files
author
Darrick J. Wong
committed
xfs: check for reverse mapping records that could be merged
Enhance the rmap scrubber to flag adjacent records that could be merged. Signed-off-by: Darrick J. Wong <djwong@kernel.org> Reviewed-by: Dave Chinner <dchinner@redhat.com>
1 parent 29ab991 commit 1c1646a

1 file changed

Lines changed: 52 additions & 0 deletions

File tree

fs/xfs/scrub/rmap.c

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,12 @@ struct xchk_rmap {
3939
* allocations that cannot be shared.
4040
*/
4141
struct xfs_rmap_irec overlap_rec;
42+
43+
/*
44+
* The previous rmapbt record, so that we can check for two records
45+
* that could be one.
46+
*/
47+
struct xfs_rmap_irec prev_rec;
4248
};
4349

4450
/* Cross-reference a rmap against the refcount btree. */
@@ -198,6 +204,51 @@ xchk_rmapbt_check_overlapping(
198204
memcpy(&cr->overlap_rec, irec, sizeof(struct xfs_rmap_irec));
199205
}
200206

207+
/* Decide if two reverse-mapping records can be merged. */
208+
static inline bool
209+
xchk_rmap_mergeable(
210+
struct xchk_rmap *cr,
211+
const struct xfs_rmap_irec *r2)
212+
{
213+
const struct xfs_rmap_irec *r1 = &cr->prev_rec;
214+
215+
/* Ignore if prev_rec is not yet initialized. */
216+
if (cr->prev_rec.rm_blockcount == 0)
217+
return false;
218+
219+
if (r1->rm_owner != r2->rm_owner)
220+
return false;
221+
if (r1->rm_startblock + r1->rm_blockcount != r2->rm_startblock)
222+
return false;
223+
if ((unsigned long long)r1->rm_blockcount + r2->rm_blockcount >
224+
XFS_RMAP_LEN_MAX)
225+
return false;
226+
if (XFS_RMAP_NON_INODE_OWNER(r2->rm_owner))
227+
return true;
228+
/* must be an inode owner below here */
229+
if (r1->rm_flags != r2->rm_flags)
230+
return false;
231+
if (r1->rm_flags & XFS_RMAP_BMBT_BLOCK)
232+
return true;
233+
return r1->rm_offset + r1->rm_blockcount == r2->rm_offset;
234+
}
235+
236+
/* Flag failures for records that could be merged. */
237+
STATIC void
238+
xchk_rmapbt_check_mergeable(
239+
struct xchk_btree *bs,
240+
struct xchk_rmap *cr,
241+
const struct xfs_rmap_irec *irec)
242+
{
243+
if (bs->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
244+
return;
245+
246+
if (xchk_rmap_mergeable(cr, irec))
247+
xchk_btree_set_corrupt(bs->sc, bs->cur, 0);
248+
249+
memcpy(&cr->prev_rec, irec, sizeof(struct xfs_rmap_irec));
250+
}
251+
201252
/* Scrub an rmapbt record. */
202253
STATIC int
203254
xchk_rmapbt_rec(
@@ -214,6 +265,7 @@ xchk_rmapbt_rec(
214265
}
215266

216267
xchk_rmapbt_check_unwritten_in_keyflags(bs);
268+
xchk_rmapbt_check_mergeable(bs, cr, &irec);
217269
xchk_rmapbt_check_overlapping(bs, cr, &irec);
218270
xchk_rmapbt_xref(bs->sc, &irec);
219271
return 0;

0 commit comments

Comments
 (0)