Skip to content

Commit

Permalink
DLPX-51469 panic in zfs_blkptr_verify(): "blkptr at ... DVA 0 has inv…
Browse files Browse the repository at this point in the history
…alid VDEV 2"

Reviewed at: http://reviews.delphix.com/r/33792/
  • Loading branch information
sdimitro committed May 4, 2017
1 parent cca1391 commit e5fe6b3
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 13 deletions.
6 changes: 6 additions & 0 deletions usr/src/cmd/zdb/zdb_il.c
Expand Up @@ -41,6 +41,7 @@
#include <sys/resource.h>
#include <sys/zil.h>
#include <sys/zil_impl.h>
#include <sys/spa_impl.h>
#include <sys/abd.h>

extern uint8_t dump_opt[256];
Expand Down Expand Up @@ -391,6 +392,11 @@ dump_intent_log(zilog_t *zilog)
for (i = 0; i < TX_MAX_TYPE; i++)
zil_rec_info[i].zri_count = 0;

/* see comment in zil_claim() or zil_check_log_chain() */
if (zilog->zl_spa->spa_uberblock.ub_checkpoint_txg != 0 &&
zh->zh_claim_txg == 0)
return;

if (verbose >= 2) {
(void) printf("\n");
(void) zil_parse(zilog, print_log_block, print_log_record, NULL,
Expand Down
8 changes: 6 additions & 2 deletions usr/src/uts/common/fs/zfs/dmu_traverse.c
Expand Up @@ -31,6 +31,7 @@
#include <sys/dsl_pool.h>
#include <sys/dnode.h>
#include <sys/spa.h>
#include <sys/spa_impl.h>
#include <sys/zio.h>
#include <sys/dmu_impl.h>
#include <sys/sa.h>
Expand Down Expand Up @@ -124,9 +125,12 @@ traverse_zil(traverse_data_t *td, zil_header_t *zh)

/*
* We only want to visit blocks that have been claimed but not yet
* replayed; plus, in read-only mode, blocks that are already stable.
* replayed; plus, in read-only mode, blocks that are already stable,
* except from the case where we are opening the checkpointed state
* of the pool. [see comment in zil_claim()]
*/
if (claim_txg == 0 && spa_writeable(td->td_spa))
if (claim_txg == 0 && (spa_writeable(td->td_spa) ||
td->td_spa->spa_uberblock.ub_checkpoint_txg != 0))
return;

zilog = zil_alloc(spa_get_dsl(td->td_spa)->dp_meta_objset, zh);
Expand Down
8 changes: 5 additions & 3 deletions usr/src/uts/common/fs/zfs/dsl_scan.c
Expand Up @@ -552,11 +552,13 @@ dsl_scan_zil(dsl_pool_t *dp, zil_header_t *zh)
zil_scan_arg_t zsa = { dp, zh };
zilog_t *zilog;

ASSERT(spa_writeable(dp->dp_spa));

/*
* We only want to visit blocks that have been claimed but not yet
* replayed (or, in read-only mode, blocks that *would* be claimed).
* We only want to visit blocks that have been claimed
* but not yet replayed.
*/
if (claim_txg == 0 && spa_writeable(dp->dp_spa))
if (claim_txg == 0)
return;

zilog = zil_alloc(dp->dp_meta_objset, zh);
Expand Down
39 changes: 31 additions & 8 deletions usr/src/uts/common/fs/zfs/zil.c
Expand Up @@ -369,8 +369,18 @@ zil_parse(zilog_t *zilog, zil_parse_blk_func_t *parse_blk_func,
static int
zil_clear_log_block(zilog_t *zilog, blkptr_t *bp, void *tx, uint64_t first_txg)
{
if (BP_IS_HOLE(bp) || bp->blk_birth >= first_txg ||
zil_bp_tree_add(zilog, bp) != 0)
ASSERT(!BP_IS_HOLE(bp));

/*
* As we call this function from the context of a rewind to a
* checkpoint, each ZIL block whose txg is later than the txg
* that we rewind to is invalid. Thus, we return -1 so
* zil_parse() doesn't attempt to read it.
*/
if (bp->blk_birth >= first_txg)
return (-1);

if (zil_bp_tree_add(zilog, bp) != 0)
return (0);

zio_free(zilog->zl_spa, first_txg, bp);
Expand Down Expand Up @@ -785,16 +795,17 @@ zil_check_log_chain(dsl_pool_t *dp, dsl_dataset_t *ds, void *tx)
zilog = dmu_objset_zil(os);
bp = (blkptr_t *)&zilog->zl_header->zh_log;

/*
* Check the first block and determine if it's on a log device
* which may have been removed or faulted prior to loading this
* pool. If so, there's no point in checking the rest of the log
* as its content should have already been synced to the pool.
*/
if (!BP_IS_HOLE(bp)) {
vdev_t *vd;
boolean_t valid = B_TRUE;

/*
* Check the first block and determine if it's on a log device
* which may have been removed or faulted prior to loading this
* pool. If so, there's no point in checking the rest of the
* log as its content should have already been synced to the
* pool.
*/
spa_config_enter(os->os_spa, SCL_STATE, FTAG, RW_READER);
vd = vdev_lookup_top(os->os_spa, DVA_GET_VDEV(&bp->blk_dva[0]));
if (vd->vdev_islog && vdev_is_dead(vd))
Expand All @@ -803,6 +814,18 @@ zil_check_log_chain(dsl_pool_t *dp, dsl_dataset_t *ds, void *tx)

if (!valid)
return (0);

/*
* Check whether the current uberblock is checkpointed (e.g.
* we are rewinding) and whether the current header has been
* claimed or not. If it hasn't then skip verifying it. We
* do this because its ZIL blocks may be part of the pool's
* state before the rewind, which is no longer valid.
*/
zil_header_t *zh = zil_header_in_syncing_context(zilog);
if (zilog->zl_spa->spa_uberblock.ub_checkpoint_txg != 0 &&
zh->zh_claim_txg == 0)
return (0);
}

/*
Expand Down

0 comments on commit e5fe6b3

Please sign in to comment.