aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cmd/zpool/zpool_main.c22
-rw-r--r--include/sys/dsl_scan.h2
-rw-r--r--include/sys/fs/zfs.h2
-rw-r--r--module/zfs/dsl_scan.c39
4 files changed, 65 insertions, 0 deletions
diff --git a/cmd/zpool/zpool_main.c b/cmd/zpool/zpool_main.c
index d496d0c72..41e13af9a 100644
--- a/cmd/zpool/zpool_main.c
+++ b/cmd/zpool/zpool_main.c
@@ -1747,6 +1747,23 @@ show_import(nvlist_t *config)
case ZPOOL_ERRATA_NONE:
break;
+ case ZPOOL_ERRATA_ZOL_2094_SCRUB:
+ (void) printf(gettext(" action: The pool can "
+ "be imported using its name or numeric "
+ "identifier,\n\thowever there is a compat"
+ "ibility issue which should be corrected"
+ "\n\tby running 'zpool scrub'\n"));
+ break;
+
+ case ZPOOL_ERRATA_ZOL_2094_ASYNC_DESTROY:
+ (void) printf(gettext(" action: The pool can"
+ "not be imported with this version of ZFS "
+ "due to\n\tan active asynchronous destroy. "
+ "Revert to an earlier version\n\tand "
+ "allow the destroy to complete before "
+ "updating.\n"));
+ break;
+
default:
/*
* All errata must contain an action message.
@@ -4375,6 +4392,11 @@ status_callback(zpool_handle_t *zhp, void *data)
case ZPOOL_ERRATA_NONE:
break;
+ case ZPOOL_ERRATA_ZOL_2094_SCRUB:
+ (void) printf(gettext("action: To correct the issue "
+ "run 'zpool scrub'.\n"));
+ break;
+
default:
/*
* All errata which allow the pool to be imported
diff --git a/include/sys/dsl_scan.h b/include/sys/dsl_scan.h
index bf8c5ac82..bcb85d67d 100644
--- a/include/sys/dsl_scan.h
+++ b/include/sys/dsl_scan.h
@@ -72,6 +72,8 @@ typedef enum dsl_scan_flags {
DSF_VISIT_DS_AGAIN = 1<<0,
} dsl_scan_flags_t;
+#define DSL_SCAN_FLAGS_MASK (DSF_VISIT_DS_AGAIN)
+
/*
* Every pool will have one dsl_scan_t and this structure will contain
* in-memory information about the scan and a pointer to the on-disk
diff --git a/include/sys/fs/zfs.h b/include/sys/fs/zfs.h
index 50d099fc9..df5692d14 100644
--- a/include/sys/fs/zfs.h
+++ b/include/sys/fs/zfs.h
@@ -713,6 +713,8 @@ typedef enum dsl_scan_state {
*/
typedef enum zpool_errata {
ZPOOL_ERRATA_NONE,
+ ZPOOL_ERRATA_ZOL_2094_SCRUB,
+ ZPOOL_ERRATA_ZOL_2094_ASYNC_DESTROY,
} zpool_errata_t;
/*
diff --git a/module/zfs/dsl_scan.c b/module/zfs/dsl_scan.c
index ea0450781..7807f8485 100644
--- a/module/zfs/dsl_scan.c
+++ b/module/zfs/dsl_scan.c
@@ -123,6 +123,42 @@ dsl_scan_init(dsl_pool_t *dp, uint64_t txg)
err = zap_lookup(dp->dp_meta_objset, DMU_POOL_DIRECTORY_OBJECT,
DMU_POOL_SCAN, sizeof (uint64_t), SCAN_PHYS_NUMINTS,
&scn->scn_phys);
+ /*
+ * Detect if the pool contains the signature of #2094. If it
+ * does properly update the scn->scn_phys structure and notify
+ * the administrator by setting an errata for the pool.
+ */
+ if (err == EOVERFLOW) {
+ uint64_t zaptmp[SCAN_PHYS_NUMINTS + 1];
+ VERIFY3S(SCAN_PHYS_NUMINTS, ==, 24);
+ VERIFY3S(offsetof(dsl_scan_phys_t, scn_flags), ==,
+ (23 * sizeof (uint64_t)));
+
+ err = zap_lookup(dp->dp_meta_objset,
+ DMU_POOL_DIRECTORY_OBJECT, DMU_POOL_SCAN,
+ sizeof (uint64_t), SCAN_PHYS_NUMINTS + 1, &zaptmp);
+ if (err == 0) {
+ uint64_t overflow = zaptmp[SCAN_PHYS_NUMINTS];
+
+ if (overflow & ~DSL_SCAN_FLAGS_MASK ||
+ scn->scn_async_destroying) {
+ spa->spa_errata =
+ ZPOOL_ERRATA_ZOL_2094_ASYNC_DESTROY;
+ return (EOVERFLOW);
+ }
+
+ bcopy(zaptmp, &scn->scn_phys,
+ SCAN_PHYS_NUMINTS * sizeof (uint64_t));
+ scn->scn_phys.scn_flags = overflow;
+
+ /* Required scrub already in progress. */
+ if (scn->scn_phys.scn_state == DSS_FINISHED ||
+ scn->scn_phys.scn_state == DSS_CANCELED)
+ spa->spa_errata =
+ ZPOOL_ERRATA_ZOL_2094_SCRUB;
+ }
+ }
+
if (err == ENOENT)
return (0);
else if (err)
@@ -319,6 +355,9 @@ dsl_scan_done(dsl_scan_t *scn, boolean_t complete, dmu_tx_t *tx)
}
scn->scn_phys.scn_end_time = gethrestime_sec();
+
+ if (spa->spa_errata == ZPOOL_ERRATA_ZOL_2094_SCRUB)
+ spa->spa_errata = 0;
}
/* ARGSUSED */