summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Yao <[email protected]>2014-02-20 20:28:33 -0800
committerBrian Behlendorf <[email protected]>2014-02-21 12:10:40 -0800
commit4f2dcb3eee0e6c922f1f54955c3e15fd20b3b4f6 (patch)
treef8c2c1a1452705f8e886c9b023186ac5d936687f
parentffe9d38275f63dbd0e6a23f3dd310249684ad518 (diff)
Add erratum for issue #2094
ZoL commit 1421c89 unintentionally changed the disk format in a forward- compatible, but not backward compatible way. This was accomplished by adding an entry to zbookmark_t, which is included in a couple of on-disk structures. That lead to the creation of pools with incorrect dsl_scan_phys_t objects that could only be imported by versions of ZoL containing that commit. Such pools cannot be imported by other versions of ZFS or past versions of ZoL. The additional field has been removed by the previous commit. However, affected pools must be imported and scrubbed using a version of ZoL with this commit applied. This will return the pools to a state in which they may be imported by other implementations. The 'zpool import' or 'zpool status' command can be used to determine if a pool is impacted. A message similar to one of the following means your pool must be scrubbed to restore compatibility. $ zpool import pool: zol-0.6.2-173 id: 1165955789558693437 state: ONLINE status: Errata #1 detected. action: The pool can be imported using its name or numeric identifier, however there is a compatibility issue which should be corrected by running 'zpool scrub' see: http://zfsonlinux.org/msg/ZFS-8000-ER config: ... $ zpool status pool: zol-0.6.2-173 state: ONLINE scan: pool compatibility issue detected. see: https://github.com/zfsonlinux/zfs/issues/2094 action: To correct the issue run 'zpool scrub'. config: ... If there was an async destroy in progress 'zpool import' will prevent the pool from being imported. Further advice on how to proceed will be provided by the error message as follows. $ zpool import pool: zol-0.6.2-173 id: 1165955789558693437 state: ONLINE status: Errata #2 detected. action: The pool can not be imported with this version of ZFS due to an active asynchronous destroy. Revert to an earlier version and allow the destroy to complete before updating. see: http://zfsonlinux.org/msg/ZFS-8000-ER config: ... Pools affected by the damaged dsl_scan_phys_t can be detected prior to an upgrade by running the following command as root: zdb -dddd poolname 1 | grep -P '^\t\tscan = ' | sed -e 's;scan = ;;' | wc -w Note that `poolname` must be replaced with the name of the pool you wish to check. A value of 25 indicates the dsl_scan_phys_t has been damaged. A value of 24 indicates that the dsl_scan_phys_t is normal. A value of 0 indicates that there has never been a scrub run on the pool. The regression caused by the change to zbookmark_t never made it into a tagged release, Gentoo backports, Ubuntu, Debian, Fedora, or EPEL stable respositorys. Only those using the HEAD version directly from Github after the 0.6.2 but before the 0.6.3 tag are affected. This patch does have one limitation that should be mentioned. It will not detect errata #2 on a pool unless errata #1 is also present. It expected this will not be a significant problem because pools impacted by errata #2 have a high probably of being impacted by errata #1. End users can ensure they do no hit this unlikely case by waiting for all asynchronous destroy operations to complete before updating ZoL. The presence of any background destroys on any imported pools can be checked by running `zpool get freeing` as root. This will display a non-zero value for any pool with an active asynchronous destroy. Lastly, it is expected that no user data has been lost as a result of this erratum. Original-patch-by: Tim Chase <[email protected]> Reworked-by: Brian Behlendorf <[email protected]> Signed-off-by: Tim Chase <[email protected]> Signed-off-by: Richard Yao <[email protected]> Signed-off-by: Brian Behlendorf <[email protected]> Issue #2094
-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 */