aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cmd/zpool/zpool_main.c39
-rw-r--r--include/libzfs.h7
-rw-r--r--include/sys/fs/zfs.h10
-rw-r--r--include/sys/spa_impl.h1
-rw-r--r--lib/libzfs/libzfs_status.c21
-rw-r--r--module/zfs/spa.c2
-rw-r--r--module/zfs/spa_config.c2
7 files changed, 73 insertions, 9 deletions
diff --git a/cmd/zpool/zpool_main.c b/cmd/zpool/zpool_main.c
index f98bca14e..d496d0c72 100644
--- a/cmd/zpool/zpool_main.c
+++ b/cmd/zpool/zpool_main.c
@@ -1609,6 +1609,7 @@ show_import(nvlist_t *config)
char *msgid;
nvlist_t *nvroot;
zpool_status_t reason;
+ zpool_errata_t errata;
const char *health;
uint_t vsc;
int namewidth;
@@ -1627,7 +1628,7 @@ show_import(nvlist_t *config)
(uint64_t **)&vs, &vsc) == 0);
health = zpool_state_to_name(vs->vs_state, vs->vs_aux);
- reason = zpool_import_status(config, &msgid);
+ reason = zpool_import_status(config, &msgid, &errata);
(void) printf(gettext(" pool: %s\n"), name);
(void) printf(gettext(" id: %llu\n"), (u_longlong_t)guid);
@@ -1715,6 +1716,11 @@ show_import(nvlist_t *config)
"resilvered.\n"));
break;
+ case ZPOOL_STATUS_ERRATA:
+ (void) printf(gettext(" status: Errata #%d detected.\n"),
+ errata);
+ break;
+
default:
/*
* No other status can be seen when importing pools.
@@ -1736,6 +1742,17 @@ show_import(nvlist_t *config)
(void) printf(gettext(" action: The pool can be "
"imported using its name or numeric "
"identifier and\n\tthe '-f' flag.\n"));
+ } else if (reason == ZPOOL_STATUS_ERRATA) {
+ switch (errata) {
+ case ZPOOL_ERRATA_NONE:
+ break;
+
+ default:
+ /*
+ * All errata must contain an action message.
+ */
+ assert(0);
+ }
} else {
(void) printf(gettext(" action: The pool can be "
"imported using its name or numeric "
@@ -4126,12 +4143,13 @@ status_callback(zpool_handle_t *zhp, void *data)
nvlist_t *config, *nvroot;
char *msgid;
zpool_status_t reason;
+ zpool_errata_t errata;
const char *health;
uint_t c;
vdev_stat_t *vs;
config = zpool_get_config(zhp, NULL);
- reason = zpool_get_status(zhp, &msgid);
+ reason = zpool_get_status(zhp, &msgid, &errata);
cbp->cb_count++;
@@ -4349,6 +4367,23 @@ status_callback(zpool_handle_t *zhp, void *data)
"'zpool clear'.\n"));
break;
+ case ZPOOL_STATUS_ERRATA:
+ (void) printf(gettext("status: Errata #%d detected.\n"),
+ errata);
+
+ switch (errata) {
+ case ZPOOL_ERRATA_NONE:
+ break;
+
+ default:
+ /*
+ * All errata which allow the pool to be imported
+ * must contain an action message.
+ */
+ assert(0);
+ }
+ break;
+
default:
/*
* The remaining errors can't actually be generated, yet.
diff --git a/include/libzfs.h b/include/libzfs.h
index 742f39f94..55dd34c99 100644
--- a/include/libzfs.h
+++ b/include/libzfs.h
@@ -312,6 +312,7 @@ typedef enum {
ZPOOL_STATUS_IO_FAILURE_WAIT, /* failed I/O, failmode 'wait' */
ZPOOL_STATUS_IO_FAILURE_CONTINUE, /* failed I/O, failmode 'continue' */
ZPOOL_STATUS_BAD_LOG, /* cannot read log chain(s) */
+ ZPOOL_STATUS_ERRATA, /* informational errata available */
/*
* If the pool has unsupported features but can still be opened in
@@ -347,8 +348,10 @@ typedef enum {
ZPOOL_STATUS_OK
} zpool_status_t;
-extern zpool_status_t zpool_get_status(zpool_handle_t *, char **);
-extern zpool_status_t zpool_import_status(nvlist_t *, char **);
+extern zpool_status_t zpool_get_status(zpool_handle_t *, char **,
+ zpool_errata_t *);
+extern zpool_status_t zpool_import_status(nvlist_t *, char **,
+ zpool_errata_t *);
extern void zpool_dump_ddt(const ddt_stat_t *dds, const ddt_histogram_t *ddh);
/*
diff --git a/include/sys/fs/zfs.h b/include/sys/fs/zfs.h
index c54721155..50d099fc9 100644
--- a/include/sys/fs/zfs.h
+++ b/include/sys/fs/zfs.h
@@ -548,6 +548,7 @@ typedef struct zpool_rewind_policy {
#define ZPOOL_CONFIG_CAN_RDONLY "can_rdonly" /* not stored on disk */
#define ZPOOL_CONFIG_FEATURES_FOR_READ "features_for_read"
#define ZPOOL_CONFIG_FEATURE_STATS "feature_stats" /* not stored on disk */
+#define ZPOOL_CONFIG_ERRATA "errata" /* not stored on disk */
/*
* The persistent vdev state is stored as separate values rather than a single
* 'vdev_state' entry. This is because a device can be in multiple states, such
@@ -704,6 +705,15 @@ typedef enum dsl_scan_state {
DSS_NUM_STATES
} dsl_scan_state_t;
+/*
+ * Errata described by http://zfsonlinux.org/msg/ZFS-8000-ER. The ordering
+ * of this enum must be maintained to ensure the errata identifiers map to
+ * the correct documentation. New errata may only be appended to the list
+ * and must contain corresponding documentation at the above link.
+ */
+typedef enum zpool_errata {
+ ZPOOL_ERRATA_NONE,
+} zpool_errata_t;
/*
* Vdev statistics. Note: all fields should be 64-bit because this
diff --git a/include/sys/spa_impl.h b/include/sys/spa_impl.h
index 55515c1fc..90a32d3f0 100644
--- a/include/sys/spa_impl.h
+++ b/include/sys/spa_impl.h
@@ -236,6 +236,7 @@ struct spa {
uint64_t spa_deadman_calls; /* number of deadman calls */
hrtime_t spa_sync_starttime; /* starting time of spa_sync */
uint64_t spa_deadman_synctime; /* deadman expiration timer */
+ uint64_t spa_errata; /* errata issues detected */
spa_stats_t spa_stats; /* assorted spa statistics */
/*
diff --git a/lib/libzfs/libzfs_status.c b/lib/libzfs/libzfs_status.c
index 0ef5f36d6..534ff853a 100644
--- a/lib/libzfs/libzfs_status.c
+++ b/lib/libzfs/libzfs_status.c
@@ -67,6 +67,7 @@ static char *zfs_msgid_table[] = {
"ZFS-8000-HC",
"ZFS-8000-JQ",
"ZFS-8000-K4",
+ "ZFS-8000-ER",
};
#define NMSGID (sizeof (zfs_msgid_table) / sizeof (zfs_msgid_table[0]))
@@ -182,7 +183,7 @@ find_vdev_problem(nvlist_t *vdev, int (*func)(uint64_t, uint64_t, uint64_t))
* only picks the most damaging of all the current errors to report.
*/
static zpool_status_t
-check_status(nvlist_t *config, boolean_t isimport)
+check_status(nvlist_t *config, boolean_t isimport, zpool_errata_t *erratap)
{
nvlist_t *nvroot;
vdev_stat_t *vs;
@@ -193,6 +194,7 @@ check_status(nvlist_t *config, boolean_t isimport)
uint64_t stateval;
uint64_t suspended;
uint64_t hostid = 0;
+ uint64_t errata = 0;
unsigned long system_hostid = gethostid() & 0xffffffff;
verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
@@ -356,13 +358,22 @@ check_status(nvlist_t *config, boolean_t isimport)
}
}
+ /*
+ * Informational errata available.
+ */
+ (void) nvlist_lookup_uint64(config, ZPOOL_CONFIG_ERRATA, &errata);
+ if (errata) {
+ *erratap = errata;
+ return (ZPOOL_STATUS_ERRATA);
+ }
+
return (ZPOOL_STATUS_OK);
}
zpool_status_t
-zpool_get_status(zpool_handle_t *zhp, char **msgid)
+zpool_get_status(zpool_handle_t *zhp, char **msgid, zpool_errata_t *errata)
{
- zpool_status_t ret = check_status(zhp->zpool_config, B_FALSE);
+ zpool_status_t ret = check_status(zhp->zpool_config, B_FALSE, errata);
if (ret >= NMSGID)
*msgid = NULL;
@@ -373,9 +384,9 @@ zpool_get_status(zpool_handle_t *zhp, char **msgid)
}
zpool_status_t
-zpool_import_status(nvlist_t *config, char **msgid)
+zpool_import_status(nvlist_t *config, char **msgid, zpool_errata_t *errata)
{
- zpool_status_t ret = check_status(config, B_TRUE);
+ zpool_status_t ret = check_status(config, B_TRUE, errata);
if (ret >= NMSGID)
*msgid = NULL;
diff --git a/module/zfs/spa.c b/module/zfs/spa.c
index 7052eec4a..9e7a7b785 100644
--- a/module/zfs/spa.c
+++ b/module/zfs/spa.c
@@ -4083,6 +4083,8 @@ spa_tryimport(nvlist_t *tryconfig)
spa->spa_uberblock.ub_timestamp) == 0);
VERIFY(nvlist_add_nvlist(config, ZPOOL_CONFIG_LOAD_INFO,
spa->spa_load_info) == 0);
+ VERIFY(nvlist_add_uint64(config, ZPOOL_CONFIG_ERRATA,
+ spa->spa_errata) == 0);
/*
* If the bootfs property exists on this pool then we
diff --git a/module/zfs/spa_config.c b/module/zfs/spa_config.c
index 9efa05361..5b95a8e81 100644
--- a/module/zfs/spa_config.c
+++ b/module/zfs/spa_config.c
@@ -365,6 +365,8 @@ spa_config_generate(spa_t *spa, vdev_t *vd, uint64_t txg, int getstats)
txg) == 0);
VERIFY(nvlist_add_uint64(config, ZPOOL_CONFIG_POOL_GUID,
spa_guid(spa)) == 0);
+ VERIFY(nvlist_add_uint64(config, ZPOOL_CONFIG_ERRATA,
+ spa->spa_errata) == 0);
VERIFY(spa->spa_comment == NULL || nvlist_add_string(config,
ZPOOL_CONFIG_COMMENT, spa->spa_comment) == 0);