diff options
author | avg <avg@FreeBSD.org> | 2014-02-17 18:25:41 +0000 |
---|---|---|
committer | avg <avg@FreeBSD.org> | 2014-02-17 18:25:41 +0000 |
commit | 489e9199469312bfa8a4485ea401738f13296942 (patch) | |
tree | 023e997449769dd55a53ddb51d21497877551fda /sys/cddl/contrib/opensolaris/uts/common/fs/zfs/bptree.c | |
parent | b0a412937022eafe8c2d5bbc56abe56fd7b1b098 (diff) | |
download | FreeBSD-src-489e9199469312bfa8a4485ea401738f13296942.zip FreeBSD-src-489e9199469312bfa8a4485ea401738f13296942.tar.gz |
MFC r260185: MFV r260155: 4391 panic system rather than corrupting pool if we hit bug 4390
Diffstat (limited to 'sys/cddl/contrib/opensolaris/uts/common/fs/zfs/bptree.c')
-rw-r--r-- | sys/cddl/contrib/opensolaris/uts/common/fs/zfs/bptree.c | 27 |
1 files changed, 19 insertions, 8 deletions
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/bptree.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/bptree.c index a0c90cc..41b166c 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/bptree.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/bptree.c @@ -180,6 +180,7 @@ bptree_iterate(objset_t *os, uint64_t obj, boolean_t free, bptree_itor_t func, err = 0; for (i = ba.ba_phys->bt_begin; i < ba.ba_phys->bt_end; i++) { bptree_entry_phys_t bte; + int flags = TRAVERSE_PREFETCH_METADATA | TRAVERSE_POST; ASSERT(!free || i == ba.ba_phys->bt_begin); @@ -188,13 +189,13 @@ bptree_iterate(objset_t *os, uint64_t obj, boolean_t free, bptree_itor_t func, if (err != 0) break; + if (zfs_recover) + flags |= TRAVERSE_HARD; err = traverse_dataset_destroyed(os->os_spa, &bte.be_bp, - bte.be_birth_txg, &bte.be_zb, - TRAVERSE_PREFETCH_METADATA | TRAVERSE_POST, + bte.be_birth_txg, &bte.be_zb, flags, bptree_visit_cb, &ba); if (free) { - ASSERT(err == 0 || err == ERESTART); - if (err != 0) { + if (err == ERESTART) { /* save bookmark for future resume */ ASSERT3U(bte.be_zb.zb_objset, ==, ZB_DESTROYED_OBJSET); @@ -202,11 +203,21 @@ bptree_iterate(objset_t *os, uint64_t obj, boolean_t free, bptree_itor_t func, dmu_write(os, obj, i * sizeof (bte), sizeof (bte), &bte, tx); break; - } else { - ba.ba_phys->bt_begin++; - (void) dmu_free_range(os, obj, - i * sizeof (bte), sizeof (bte), tx); } + if (err != 0) { + /* + * We can not properly handle an i/o + * error, because the traversal code + * does not know how to resume from an + * arbitrary bookmark. + */ + zfs_panic_recover("error %u from " + "traverse_dataset_destroyed()", err); + } + + ba.ba_phys->bt_begin++; + (void) dmu_free_range(os, obj, + i * sizeof (bte), sizeof (bte), tx); } } |