char *msgid;
nvlist_t *nvroot;
zpool_status_t reason;
+ zpool_errata_t errata;
const char *health;
uint_t vsc;
int namewidth;
(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);
"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.
(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 "
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++;
"'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.
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
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);
/*
#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
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
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 */
/*
"ZFS-8000-HC",
"ZFS-8000-JQ",
"ZFS-8000-K4",
+ "ZFS-8000-ER",
};
#define NMSGID (sizeof (zfs_msgid_table) / sizeof (zfs_msgid_table[0]))
* 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;
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,
}
}
+ /*
+ * 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;
}
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;
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
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);