Skip to content

Commit 6ff646b

Browse files
committed
xfs: fix rmap key and record comparison functions
Keys for extent interval records in the reverse mapping btree are supposed to be computed as follows: (physical block, owner, fork, is_btree, is_unwritten, offset) This provides users the ability to look up a reverse mapping from a bmbt record -- start with the physical block; then if there are multiple records for the same block, move on to the owner; then the inode fork type; and so on to the file offset. However, the key comparison functions incorrectly remove the fork/btree/unwritten information that's encoded in the on-disk offset. This means that lookup comparisons are only done with: (physical block, owner, offset) This means that queries can return incorrect results. On consistent filesystems this hasn't been an issue because blocks are never shared between forks or with bmbt blocks; and are never unwritten. However, this bug means that online repair cannot always detect corruption in the key information in internal rmapbt nodes. Found by fuzzing keys[1].attrfork = ones on xfs/371. Fixes: 4b8ed67 ("xfs: add rmap btree operations") Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> Reviewed-by: Christoph Hellwig <hch@lst.de>
1 parent 5dda389 commit 6ff646b

1 file changed

Lines changed: 8 additions & 8 deletions

File tree

fs/xfs/libxfs/xfs_rmap_btree.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -243,8 +243,8 @@ xfs_rmapbt_key_diff(
243243
else if (y > x)
244244
return -1;
245245

246-
x = XFS_RMAP_OFF(be64_to_cpu(kp->rm_offset));
247-
y = rec->rm_offset;
246+
x = be64_to_cpu(kp->rm_offset);
247+
y = xfs_rmap_irec_offset_pack(rec);
248248
if (x > y)
249249
return 1;
250250
else if (y > x)
@@ -275,8 +275,8 @@ xfs_rmapbt_diff_two_keys(
275275
else if (y > x)
276276
return -1;
277277

278-
x = XFS_RMAP_OFF(be64_to_cpu(kp1->rm_offset));
279-
y = XFS_RMAP_OFF(be64_to_cpu(kp2->rm_offset));
278+
x = be64_to_cpu(kp1->rm_offset);
279+
y = be64_to_cpu(kp2->rm_offset);
280280
if (x > y)
281281
return 1;
282282
else if (y > x)
@@ -390,8 +390,8 @@ xfs_rmapbt_keys_inorder(
390390
return 1;
391391
else if (a > b)
392392
return 0;
393-
a = XFS_RMAP_OFF(be64_to_cpu(k1->rmap.rm_offset));
394-
b = XFS_RMAP_OFF(be64_to_cpu(k2->rmap.rm_offset));
393+
a = be64_to_cpu(k1->rmap.rm_offset);
394+
b = be64_to_cpu(k2->rmap.rm_offset);
395395
if (a <= b)
396396
return 1;
397397
return 0;
@@ -420,8 +420,8 @@ xfs_rmapbt_recs_inorder(
420420
return 1;
421421
else if (a > b)
422422
return 0;
423-
a = XFS_RMAP_OFF(be64_to_cpu(r1->rmap.rm_offset));
424-
b = XFS_RMAP_OFF(be64_to_cpu(r2->rmap.rm_offset));
423+
a = be64_to_cpu(r1->rmap.rm_offset);
424+
b = be64_to_cpu(r2->rmap.rm_offset);
425425
if (a <= b)
426426
return 1;
427427
return 0;

0 commit comments

Comments
 (0)