Skip to content

Commit

Permalink
Merge branch 'issue-2094'
Browse files Browse the repository at this point in the history
This patch stack was designed to accomplish the following:

* Cleanly address the pool incompatibility which was accidentally
  introduced post-0.6.2 but pre-0.6.3.  This required adding
  infrastructure which can be used from now on to notify system
  administrators of errata which affect their pool.

* Add additional automated regression testing to ensure this type
  of compatibility issue is caught prior to the change being merged.

Signed-off-by: Brian Behlendorf <[email protected]>
Closes #2094
  • Loading branch information
behlendorf committed Feb 21, 2014
2 parents 98fad86 + 4f2dcb3 commit 3965d2e
Show file tree
Hide file tree
Showing 15 changed files with 641 additions and 14 deletions.
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "scripts/zfs-images"]
path = scripts/zfs-images
url = https://github.com/zfsonlinux/zfs-images
65 changes: 61 additions & 4 deletions cmd/zpool/zpool_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -1608,7 +1608,8 @@ show_import(nvlist_t *config)
uint64_t guid;
char *msgid;
nvlist_t *nvroot;
int reason;
zpool_status_t reason;
zpool_errata_t errata;
const char *health;
uint_t vsc;
int namewidth;
Expand All @@ -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);
Expand Down Expand Up @@ -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.
Expand All @@ -1736,6 +1742,34 @@ 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;

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.
*/
assert(0);
}
} else {
(void) printf(gettext(" action: The pool can be "
"imported using its name or numeric "
Expand Down Expand Up @@ -4125,13 +4159,14 @@ status_callback(zpool_handle_t *zhp, void *data)
status_cbdata_t *cbp = data;
nvlist_t *config, *nvroot;
char *msgid;
int reason;
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++;

Expand Down Expand Up @@ -4349,6 +4384,28 @@ 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;

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
* must contain an action message.
*/
assert(0);
}
break;

default:
/*
* The remaining errors can't actually be generated, yet.
Expand Down
7 changes: 5 additions & 2 deletions include/libzfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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);

/*
Expand Down
2 changes: 2 additions & 0 deletions include/sys/dsl_scan.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
12 changes: 12 additions & 0 deletions include/sys/fs/zfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -704,6 +705,17 @@ 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_ZOL_2094_SCRUB,
ZPOOL_ERRATA_ZOL_2094_ASYNC_DESTROY,
} zpool_errata_t;

/*
* Vdev statistics. Note: all fields should be 64-bit because this
Expand Down
1 change: 1 addition & 0 deletions include/sys/spa_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */

/*
Expand Down
2 changes: 0 additions & 2 deletions include/sys/zio.h
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,6 @@ struct zbookmark {
uint64_t zb_object;
int64_t zb_level;
uint64_t zb_blkid;
char * zb_func;
};

#define SET_BOOKMARK(zb, objset, object, level, blkid) \
Expand All @@ -269,7 +268,6 @@ struct zbookmark {
(zb)->zb_object = object; \
(zb)->zb_level = level; \
(zb)->zb_blkid = blkid; \
(zb)->zb_func = FTAG; \
}

#define ZB_DESTROYED_OBJSET (-1ULL)
Expand Down
21 changes: 16 additions & 5 deletions lib/libzfs/libzfs_status.c
Original file line number Diff line number Diff line change
Expand Up @@ -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]))
Expand Down Expand Up @@ -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;
Expand All @@ -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,
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down
39 changes: 39 additions & 0 deletions module/zfs/dsl_scan.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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 */
Expand Down
2 changes: 2 additions & 0 deletions module/zfs/spa.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions module/zfs/spa_config.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
1 change: 0 additions & 1 deletion module/zfs/spa_stats.c
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,6 @@ spa_read_history_add(spa_t *spa, const zbookmark_t *zb, uint32_t aflags)
return;

srh = kmem_zalloc(sizeof (spa_read_history_t), KM_PUSHPAGE);
strlcpy(srh->origin, zb->zb_func, sizeof (srh->origin));
strlcpy(srh->comm, getcomm(), sizeof (srh->comm));
srh->start = gethrtime();
srh->objset = zb->zb_objset;
Expand Down
2 changes: 2 additions & 0 deletions scripts/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ dist_pkgdata_SCRIPTS = \
$(top_builddir)/scripts/common.sh \
$(top_srcdir)/scripts/zconfig.sh \
$(top_srcdir)/scripts/zfault.sh \
$(top_srcdir)/scripts/zimport.sh \
$(top_srcdir)/scripts/zfs.sh \
$(top_srcdir)/scripts/zpool-create.sh \
$(top_srcdir)/scripts/zpios.sh \
Expand All @@ -17,6 +18,7 @@ dist_pkgdata_SCRIPTS = \
ZFS=$(top_builddir)/scripts/zfs.sh
ZCONFIG=$(top_builddir)/scripts/zconfig.sh
ZFAULT=$(top_builddir)/scripts/zfault.sh
ZIMPORT=$(top_builddir)/scripts/zimport.sh
ZTEST=$(top_builddir)/cmd/ztest/ztest
ZPIOS_SANITY=$(top_builddir)/scripts/zpios-sanity.sh

Expand Down
1 change: 1 addition & 0 deletions scripts/zfs-images
Submodule zfs-images added at 333160
Loading

0 comments on commit 3965d2e

Please sign in to comment.