aboutsummaryrefslogtreecommitdiffstats
path: root/cmd
diff options
context:
space:
mode:
authorMatthew Ahrens <[email protected]>2023-05-08 11:20:23 -0700
committerGitHub <[email protected]>2023-05-08 11:20:23 -0700
commit3095ca91c261756c509d0afb4422027753e68c90 (patch)
treecd0c97824d0c8b7f40d9cfad54684832214a910c /cmd
parentdd19821149cb7e3785249eb9be75dd9864c88d56 (diff)
Verify block pointers before writing them out
If a block pointer is corrupted (but the block containing it checksums correctly, e.g. due to a bug that overwrites random memory), we can often detect it before the block is read, with the `zfs_blkptr_verify()` function, which is used in `arc_read()`, `zio_free()`, etc. However, such corruption is not typically recoverable. To recover from it we would need to detect the memory error before the block pointer is written to disk. This PR verifies BP's that are contained in indirect blocks and dnodes before they are written to disk, in `dbuf_write_ready()`. This way, we'll get a panic before the on-disk data is corrupted. This will help us to diagnose what's causing the corruption, as well as being much easier to recover from. To minimize performance impact, only checks that can be done without holding the spa_config_lock are performed. Additionally, when corruption is detected, the raw words of the block pointer are logged. (Note that `dprintf_bp()` is a no-op by default, but if enabled it is not safe to use with invalid block pointers.) Reviewed-by: Rich Ercolani <[email protected]> Reviewed-by: Brian Behlendorf <[email protected]> Reviewed-by: Paul Zuchowski <[email protected]> Reviewed-by: Alexander Motin <[email protected]> Signed-off-by: Matthew Ahrens <[email protected]> Closes #14817
Diffstat (limited to 'cmd')
-rw-r--r--cmd/zdb/zdb.c8
1 files changed, 4 insertions, 4 deletions
diff --git a/cmd/zdb/zdb.c b/cmd/zdb/zdb.c
index cea80b690..5ab13b470 100644
--- a/cmd/zdb/zdb.c
+++ b/cmd/zdb/zdb.c
@@ -8499,8 +8499,8 @@ zdb_read_block(char *thing, spa_t *spa)
!(flags & ZDB_FLAG_DECOMPRESS)) {
const blkptr_t *b = (const blkptr_t *)(void *)
((uintptr_t)buf + (uintptr_t)blkptr_offset);
- if (zfs_blkptr_verify(spa, b, B_FALSE, BLK_VERIFY_ONLY) ==
- B_FALSE) {
+ if (zfs_blkptr_verify(spa, b,
+ BLK_CONFIG_NEEDED, BLK_VERIFY_ONLY) == B_FALSE) {
abd_return_buf_copy(pabd, buf, lsize);
borrowed = B_FALSE;
buf = lbuf;
@@ -8508,8 +8508,8 @@ zdb_read_block(char *thing, spa_t *spa)
lbuf, lsize, psize, flags);
b = (const blkptr_t *)(void *)
((uintptr_t)buf + (uintptr_t)blkptr_offset);
- if (failed || zfs_blkptr_verify(spa, b, B_FALSE,
- BLK_VERIFY_LOG) == B_FALSE) {
+ if (failed || zfs_blkptr_verify(spa, b,
+ BLK_CONFIG_NEEDED, BLK_VERIFY_LOG) == B_FALSE) {
printf("invalid block pointer at this DVA\n");
goto out;
}