Mercurial > illumos > illumos-gate
changeset 12587:16aef3d16470
6957090 ddt_zap_prefetch() induces deadlock, panic
6958874 bpobj_close() tries to dereference a NULL bpo_dbuf
author | George Wilson <George.Wilson@Sun.COM> |
---|---|
date | Tue, 08 Jun 2010 13:36:53 -0700 |
parents | b118bbd65be9 |
children | 1cb8fb936e1f |
files | usr/src/uts/common/fs/zfs/bpobj.c usr/src/uts/common/fs/zfs/dbuf.c usr/src/uts/common/fs/zfs/ddt.c usr/src/uts/common/fs/zfs/dsl_dataset.c |
diffstat | 4 files changed, 20 insertions(+), 15 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/uts/common/fs/zfs/bpobj.c Tue Jun 08 12:32:02 2010 -0700 +++ b/usr/src/uts/common/fs/zfs/bpobj.c Tue Jun 08 13:36:53 2010 -0700 @@ -113,16 +113,15 @@ ASSERT3U(doi.doi_type, ==, DMU_OT_BPOBJ); ASSERT3U(doi.doi_bonus_type, ==, DMU_OT_BPOBJ_HDR); + err = dmu_bonus_hold(os, object, bpo, &bpo->bpo_dbuf); + if (err) + return (err); + bpo->bpo_os = os; bpo->bpo_object = object; bpo->bpo_epb = doi.doi_data_block_size >> SPA_BLKPTRSHIFT; bpo->bpo_havecomp = (doi.doi_bonus_size > BPOBJ_SIZE_V0); bpo->bpo_havesubobj = (doi.doi_bonus_size > BPOBJ_SIZE_V1); - - err = dmu_bonus_hold(bpo->bpo_os, - bpo->bpo_object, bpo, &bpo->bpo_dbuf); - if (err) - return (err); bpo->bpo_phys = bpo->bpo_dbuf->db_data; return (0); } @@ -140,6 +139,7 @@ bpo->bpo_dbuf = NULL; bpo->bpo_phys = NULL; bpo->bpo_cached_dbuf = NULL; + bpo->bpo_object = 0; mutex_destroy(&bpo->bpo_lock); }
--- a/usr/src/uts/common/fs/zfs/dbuf.c Tue Jun 08 12:32:02 2010 -0700 +++ b/usr/src/uts/common/fs/zfs/dbuf.c Tue Jun 08 13:36:53 2010 -0700 @@ -865,10 +865,15 @@ else if (db->db_blkptr) birth_txg = db->db_blkptr->blk_birth; - /* If we don't exist or are in a snapshot, we can't be freed */ + /* + * If we don't exist or are in a snapshot, we can't be freed. + * Don't pass the bp to dsl_dataset_block_freeable() since we + * are holding the db_mtx lock and might deadlock if we are + * prefetching a dedup-ed block. + */ if (birth_txg) return (ds == NULL || - dsl_dataset_block_freeable(ds, db->db_blkptr, birth_txg)); + dsl_dataset_block_freeable(ds, NULL, birth_txg)); else return (FALSE); } @@ -1145,6 +1150,7 @@ * db_blkptr, but since this is just a guess, * it's OK if we get an odd answer. */ + ddt_prefetch(os->os_spa, bp); dnode_willuse_space(dn, -willfree, tx); }
--- a/usr/src/uts/common/fs/zfs/ddt.c Tue Jun 08 12:32:02 2010 -0700 +++ b/usr/src/uts/common/fs/zfs/ddt.c Tue Jun 08 13:36:53 2010 -0700 @@ -36,6 +36,11 @@ #include <sys/zio_compress.h> #include <sys/dsl_scan.h> +/* + * Enable/disable prefetching of dedup-ed blocks which are going to be freed. + */ +int zfs_dedup_prefetch = 1; + static const ddt_ops_t *ddt_ops[DDT_TYPES] = { &ddt_zap_ops, }; @@ -730,7 +735,7 @@ ddt_t *ddt; ddt_entry_t dde; - if (!BP_GET_DEDUP(bp)) + if (!zfs_dedup_prefetch || bp == NULL || !BP_GET_DEDUP(bp)) return; /*
--- a/usr/src/uts/common/fs/zfs/dsl_dataset.c Tue Jun 08 12:32:02 2010 -0700 +++ b/usr/src/uts/common/fs/zfs/dsl_dataset.c Tue Jun 08 13:36:53 2010 -0700 @@ -42,11 +42,6 @@ #include <sys/dsl_scan.h> #include <sys/dsl_deadlist.h> -/* - * Enable/disable prefetching of dedup-ed blocks which are going to be freed. - */ -int zfs_dedup_prefetch = 1; - static char *dsl_reaper = "the grim reaper"; static dsl_checkfunc_t dsl_dataset_destroy_begin_check; @@ -254,8 +249,7 @@ if (blk_birth <= dsl_dataset_prev_snap_txg(ds)) return (B_FALSE); - if (zfs_dedup_prefetch && bp && BP_GET_DEDUP(bp)) - ddt_prefetch(dsl_dataset_get_spa(ds), bp); + ddt_prefetch(dsl_dataset_get_spa(ds), bp); return (B_TRUE); }