Skip to content

Commit ad07b09

Browse files
asomerstonyhutter
authored andcommitted
Verify every block pointer is either embedded, hole, or has a valid DVA
Now instead of crashing when attempting to read the corrupt block pointer, ZFS will return ECKSUM, in a stack that looks like this: ``` none:set-error zfs.ko`arc_read+0x1d82 zfs.ko`dbuf_read+0xa8c zfs.ko`dmu_buf_hold_array_by_dnode+0x292 zfs.ko`dmu_read_uio_dnode+0x47 zfs.ko`zfs_read+0x2d5 zfs.ko`zfs_freebsd_read+0x7b kernel`VOP_READ_APV+0xd0 kernel`vn_read+0x20e kernel`vn_io_fault_doio+0x45 kernel`vn_io_fault1+0x15e kernel`vn_io_fault+0x150 kernel`dofileread+0x80 kernel`sys_read+0xb7 kernel`amd64_syscall+0x424 kernel`0xffffffff810633cb ``` This patch should hopefully also prevent such corrupt block pointers from being written to disk in the first place. And in zdb, don't crash when printing a block pointer with no valid DVAs. If a block pointer isn't embedded yet doesn't have any valid DVAs, that's a data corruption bug. zdb should be able to handle the situation gracefully. Finally, remove an extra check for gang blocks in SNPRINTF_BLKPTR. This check, which compares the asizes of two different DVAs within the same BP, was added by illumos-gate commit b24ab67[^1], and I can't understand why. It doesn't appear to do anything useful, so remove it. [^1]: illumos/illumos-gate@b24ab67 Fixes openzfs#17077 Sponsored by: ConnectWise Reviewed-by: Alexander Motin <[email protected]> Reviewed-by: Brian Behlendorf <[email protected]> Reviewed by: Alek Pinchuk <[email protected]> Signed-off-by: Alan Somers <[email protected]> Closes openzfs#17078
1 parent 49da67e commit ad07b09

File tree

2 files changed

+10
-5
lines changed

2 files changed

+10
-5
lines changed

include/sys/spa.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -670,7 +670,6 @@ typedef struct blkptr {
670670
(u_longlong_t)DVA_GET_ASIZE(dva), \
671671
ws); \
672672
} \
673-
ASSERT3S(copies, >, 0); \
674673
if (BP_IS_ENCRYPTED(bp)) { \
675674
len += func(buf + len, size - len, \
676675
"salt=%llx iv=%llx:%llx%c", \
@@ -679,10 +678,6 @@ typedef struct blkptr {
679678
(u_longlong_t)BP_GET_IV2(bp), \
680679
ws); \
681680
} \
682-
if (BP_IS_GANG(bp) && \
683-
DVA_GET_ASIZE(&bp->blk_dva[2]) <= \
684-
DVA_GET_ASIZE(&bp->blk_dva[1]) / 2) \
685-
copies--; \
686681
len += func(buf + len, size - len, \
687682
"[L%llu %s] %s %s %s %s %s %s %s%c" \
688683
"size=%llxL/%llxP birth=%lluL/%lluP fill=%llu%c" \

module/zfs/zio.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1212,6 +1212,16 @@ zfs_blkptr_verify(spa_t *spa, const blkptr_t *bp,
12121212
bp, (longlong_t)BPE_GET_PSIZE(bp));
12131213
}
12141214
return (errors ? ECKSUM : 0);
1215+
} else if (BP_IS_HOLE(bp)) {
1216+
/*
1217+
* Holes are allowed (expected, even) to have no DVAs, no
1218+
* checksum, and no psize.
1219+
*/
1220+
return (errors ? ECKSUM : 0);
1221+
} else if (unlikely(!DVA_IS_VALID(&bp->blk_dva[0]))) {
1222+
/* Non-hole, non-embedded BPs _must_ have at least one DVA */
1223+
errors += zfs_blkptr_verify_log(spa, bp, blk_verify,
1224+
"blkptr at %px has no valid DVAs", bp);
12151225
}
12161226
if (unlikely(BP_GET_CHECKSUM(bp) >= ZIO_CHECKSUM_FUNCTIONS)) {
12171227
errors += zfs_blkptr_verify_log(spa, bp, blk_verify,

0 commit comments

Comments
 (0)