6957090 ddt_zap_prefetch() induces deadlock, panic
6958874 bpobj_close() tries to dereference a NULL bpo_dbuf
--- 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);
}