aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cmd/zdb/zdb.c6
-rw-r--r--include/sys/spa_impl.h1
-rw-r--r--module/zfs/metaslab.c6
-rw-r--r--module/zfs/spa.c7
-rw-r--r--module/zfs/vdev.c6
5 files changed, 24 insertions, 2 deletions
diff --git a/cmd/zdb/zdb.c b/cmd/zdb/zdb.c
index e2680fd36..8bbb77479 100644
--- a/cmd/zdb/zdb.c
+++ b/cmd/zdb/zdb.c
@@ -118,6 +118,7 @@ extern int zfs_recover;
extern unsigned long zfs_arc_meta_min, zfs_arc_meta_limit;
extern int zfs_vdev_async_read_max_active;
extern boolean_t spa_load_verify_dryrun;
+extern boolean_t spa_mode_readable_spacemaps;
extern int zfs_reconstruct_indirect_combinations_max;
extern int zfs_btree_verify_intensity;
@@ -8524,6 +8525,11 @@ main(int argc, char **argv)
*/
spa_load_verify_dryrun = B_TRUE;
+ /*
+ * ZDB should have ability to read spacemaps.
+ */
+ spa_mode_readable_spacemaps = B_TRUE;
+
kernel_init(SPA_MODE_READ);
if (dump_all)
diff --git a/include/sys/spa_impl.h b/include/sys/spa_impl.h
index 21729e617..9714bbce9 100644
--- a/include/sys/spa_impl.h
+++ b/include/sys/spa_impl.h
@@ -370,6 +370,7 @@ struct spa {
boolean_t spa_is_root; /* pool is root */
int spa_minref; /* num refs when first opened */
spa_mode_t spa_mode; /* SPA_MODE_{READ|WRITE} */
+ boolean_t spa_read_spacemaps; /* spacemaps available if ro */
spa_log_state_t spa_log_state; /* log state */
uint64_t spa_autoexpand; /* lun expansion on/off */
ddt_t *spa_ddt[ZIO_CHECKSUM_FUNCTIONS]; /* in-core DDTs */
diff --git a/module/zfs/metaslab.c b/module/zfs/metaslab.c
index df0d83327..d1fee70f0 100644
--- a/module/zfs/metaslab.c
+++ b/module/zfs/metaslab.c
@@ -2661,7 +2661,8 @@ metaslab_init(metaslab_group_t *mg, uint64_t id, uint64_t object,
/*
* We only open space map objects that already exist. All others
- * will be opened when we finally allocate an object for it.
+ * will be opened when we finally allocate an object for it. For
+ * readonly pools there is no need to open the space map object.
*
* Note:
* When called from vdev_expand(), we can't call into the DMU as
@@ -2670,7 +2671,8 @@ metaslab_init(metaslab_group_t *mg, uint64_t id, uint64_t object,
* that case, the object parameter is zero though, so we won't
* call into the DMU.
*/
- if (object != 0) {
+ if (object != 0 && !(spa->spa_mode == SPA_MODE_READ &&
+ !spa->spa_read_spacemaps)) {
error = space_map_open(&ms->ms_sm, mos, object, ms->ms_start,
ms->ms_size, vd->vdev_ashift);
diff --git a/module/zfs/spa.c b/module/zfs/spa.c
index 1c0856d7f..1083b5a90 100644
--- a/module/zfs/spa.c
+++ b/module/zfs/spa.c
@@ -181,6 +181,12 @@ boolean_t spa_create_process = B_TRUE; /* no process ==> no sysdc */
boolean_t spa_load_verify_dryrun = B_FALSE;
/*
+ * Allow read spacemaps in case of readonly import (spa_mode == SPA_MODE_READ).
+ * This is used by zdb for spacemaps verification.
+ */
+boolean_t spa_mode_readable_spacemaps = B_FALSE;
+
+/*
* This (illegal) pool name is used when temporarily importing a spa_t in order
* to get the vdev stats associated with the imported devices.
*/
@@ -1242,6 +1248,7 @@ spa_activate(spa_t *spa, spa_mode_t mode)
spa->spa_state = POOL_STATE_ACTIVE;
spa->spa_mode = mode;
+ spa->spa_read_spacemaps = spa_mode_readable_spacemaps;
spa->spa_normal_class = metaslab_class_create(spa, zfs_metaslab_ops);
spa->spa_log_class = metaslab_class_create(spa, zfs_metaslab_ops);
diff --git a/module/zfs/vdev.c b/module/zfs/vdev.c
index 0ba76f6b8..4a67ba85f 100644
--- a/module/zfs/vdev.c
+++ b/module/zfs/vdev.c
@@ -3142,6 +3142,12 @@ vdev_dtl_load(vdev_t *vd)
if (vd->vdev_ops->vdev_op_leaf && vd->vdev_dtl_object != 0) {
ASSERT(vdev_is_concrete(vd));
+ /*
+ * If the dtl cannot be sync'd there is no need to open it.
+ */
+ if (spa->spa_mode == SPA_MODE_READ && !spa->spa_read_spacemaps)
+ return (0);
+
error = space_map_open(&vd->vdev_dtl_sm, mos,
vd->vdev_dtl_object, 0, -1ULL, 0);
if (error)