3956 ::vdev -r should work with pipelines 3957 ztest should update the cachefile before killing itself 3958 multiple scans can lead to partial resilvering 3959 ddt entries are not always resilvered 3960 dsl_scan can skip over dedup-ed blocks if physical birth != logical birth 3961 freed gang blocks are not resilvered and can cause pool to suspend 3962 ztest should print out zfs debug buffer before exiting Reviewed by: Matthew Ahrens <mahrens@delphix.com> Reviewed by: Adam Leventhal <ahl@delphix.com> Approved by: Richard Lowe <richlowe@richlowe.net> References: https://www.illumos.org/issues/3956 https://www.illumos.org/issues/3957 https://www.illumos.org/issues/3958 https://www.illumos.org/issues/3959 https://www.illumos.org/issues/3960 https://www.illumos.org/issues/3961 https://www.illumos.org/issues/3962 illumos/illumos-gate@b4952e17e8 Ported-by: Richard Yao <ryao@gentoo.org> Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov> Porting notes: 1. zfs_dbgmsg_print() is only used in userland. Since we do not have mdb on Linux, it does not make sense to make it available in the kernel. This means that a build failure will occur if any future kernel patch depends on it. However, that is unlikely given that this functionality was added to support zdb. 2. zfs_dbgmsg_print() is only invoked for -VVV or greater log levels. This preserves the existing behavior of minimal noise when running with -V, and -VV. 3. In vdev_config_generate() the call to nvlist_alloc() was not changed to fnvlist_alloc() because we must pass KM_PUSHPAGE in the txg_sync context.
This commit is contained in:
parent
621dd7bb2c
commit
5d1f7fb647
|
@ -20,7 +20,7 @@
|
||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2012 by Delphix. All rights reserved.
|
* Copyright (c) 2013 by Delphix. All rights reserved.
|
||||||
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
|
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
|
||||||
* Copyright (c) 2013 Steven Hartland. All rights reserved.
|
* Copyright (c) 2013 Steven Hartland. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
@ -789,6 +789,18 @@ ztest_kill(ztest_shared_t *zs)
|
||||||
{
|
{
|
||||||
zs->zs_alloc = metaslab_class_get_alloc(spa_normal_class(ztest_spa));
|
zs->zs_alloc = metaslab_class_get_alloc(spa_normal_class(ztest_spa));
|
||||||
zs->zs_space = metaslab_class_get_space(spa_normal_class(ztest_spa));
|
zs->zs_space = metaslab_class_get_space(spa_normal_class(ztest_spa));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Before we kill off ztest, make sure that the config is updated.
|
||||||
|
* See comment above spa_config_sync().
|
||||||
|
*/
|
||||||
|
mutex_enter(&spa_namespace_lock);
|
||||||
|
spa_config_sync(ztest_spa, B_FALSE, B_FALSE);
|
||||||
|
mutex_exit(&spa_namespace_lock);
|
||||||
|
|
||||||
|
if (ztest_opts.zo_verbose >= 3)
|
||||||
|
zfs_dbgmsg_print(FTAG);
|
||||||
|
|
||||||
(void) kill(getpid(), SIGKILL);
|
(void) kill(getpid(), SIGKILL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2774,7 +2786,7 @@ ztest_vdev_attach_detach(ztest_ds_t *zd, uint64_t id)
|
||||||
uint64_t leaf, top;
|
uint64_t leaf, top;
|
||||||
uint64_t ashift = ztest_get_ashift();
|
uint64_t ashift = ztest_get_ashift();
|
||||||
uint64_t oldguid, pguid;
|
uint64_t oldguid, pguid;
|
||||||
size_t oldsize, newsize;
|
uint64_t oldsize, newsize;
|
||||||
char *oldpath, *newpath;
|
char *oldpath, *newpath;
|
||||||
int replacing;
|
int replacing;
|
||||||
int oldvd_has_siblings = B_FALSE;
|
int oldvd_has_siblings = B_FALSE;
|
||||||
|
@ -2935,8 +2947,8 @@ ztest_vdev_attach_detach(ztest_ds_t *zd, uint64_t id)
|
||||||
if (error != expected_error && expected_error != EBUSY) {
|
if (error != expected_error && expected_error != EBUSY) {
|
||||||
fatal(0, "attach (%s %llu, %s %llu, %d) "
|
fatal(0, "attach (%s %llu, %s %llu, %d) "
|
||||||
"returned %d, expected %d",
|
"returned %d, expected %d",
|
||||||
oldpath, (longlong_t)oldsize, newpath,
|
oldpath, oldsize, newpath,
|
||||||
(longlong_t)newsize, replacing, error, expected_error);
|
newsize, replacing, error, expected_error);
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
mutex_exit(&ztest_vdev_lock);
|
mutex_exit(&ztest_vdev_lock);
|
||||||
|
@ -4957,7 +4969,7 @@ ztest_fault_inject(ztest_ds_t *zd, uint64_t id)
|
||||||
*/
|
*/
|
||||||
if (vd0 != NULL && maxfaults != 1 &&
|
if (vd0 != NULL && maxfaults != 1 &&
|
||||||
(!vdev_resilver_needed(vd0->vdev_top, NULL, NULL) ||
|
(!vdev_resilver_needed(vd0->vdev_top, NULL, NULL) ||
|
||||||
vd0->vdev_resilvering)) {
|
vd0->vdev_resilver_txg != 0)) {
|
||||||
/*
|
/*
|
||||||
* Make vd0 explicitly claim to be unreadable,
|
* Make vd0 explicitly claim to be unreadable,
|
||||||
* or unwriteable, or reach behind its back
|
* or unwriteable, or reach behind its back
|
||||||
|
@ -5817,6 +5829,9 @@ ztest_run(ztest_shared_t *zs)
|
||||||
zs->zs_alloc = metaslab_class_get_alloc(spa_normal_class(spa));
|
zs->zs_alloc = metaslab_class_get_alloc(spa_normal_class(spa));
|
||||||
zs->zs_space = metaslab_class_get_space(spa_normal_class(spa));
|
zs->zs_space = metaslab_class_get_space(spa_normal_class(spa));
|
||||||
|
|
||||||
|
if (ztest_opts.zo_verbose >= 3)
|
||||||
|
zfs_dbgmsg_print(FTAG);
|
||||||
|
|
||||||
umem_free(tid, ztest_opts.zo_threads * sizeof (kt_did_t));
|
umem_free(tid, ztest_opts.zo_threads * sizeof (kt_did_t));
|
||||||
|
|
||||||
/* Kill the resume thread */
|
/* Kill the resume thread */
|
||||||
|
|
|
@ -72,11 +72,42 @@ typedef enum dsl_scan_flags {
|
||||||
DSF_VISIT_DS_AGAIN = 1<<0,
|
DSF_VISIT_DS_AGAIN = 1<<0,
|
||||||
} dsl_scan_flags_t;
|
} dsl_scan_flags_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
* representation (i.e. dsl_scan_phys_t). Most of the state of the scan
|
||||||
|
* is contained on-disk to allow the scan to resume in the event of a reboot
|
||||||
|
* or panic. This structure maintains information about the behavior of a
|
||||||
|
* running scan, some caching information, and how it should traverse the pool.
|
||||||
|
*
|
||||||
|
* The following members of this structure direct the behavior of the scan:
|
||||||
|
*
|
||||||
|
* scn_pausing - a scan that cannot be completed in a single txg or
|
||||||
|
* has exceeded its allotted time will need to pause.
|
||||||
|
* When this flag is set the scanner will stop traversing
|
||||||
|
* the pool and write out the current state to disk.
|
||||||
|
*
|
||||||
|
* scn_restart_txg - directs the scanner to either restart or start a
|
||||||
|
* a scan at the specified txg value.
|
||||||
|
*
|
||||||
|
* scn_done_txg - when a scan completes its traversal it will set
|
||||||
|
* the completion txg to the next txg. This is necessary
|
||||||
|
* to ensure that any blocks that were freed during
|
||||||
|
* the scan but have not yet been processed (i.e deferred
|
||||||
|
* frees) are accounted for.
|
||||||
|
*
|
||||||
|
* This structure also maintains information about deferred frees which are
|
||||||
|
* a special kind of traversal. Deferred free can exist in either a bptree or
|
||||||
|
* a bpobj structure. The scn_is_bptree flag will indicate the type of
|
||||||
|
* deferred free that is in progress. If the deferred free is part of an
|
||||||
|
* asynchronous destroy then the scn_async_destroying flag will be set.
|
||||||
|
*/
|
||||||
typedef struct dsl_scan {
|
typedef struct dsl_scan {
|
||||||
struct dsl_pool *scn_dp;
|
struct dsl_pool *scn_dp;
|
||||||
|
|
||||||
boolean_t scn_pausing;
|
boolean_t scn_pausing;
|
||||||
uint64_t scn_restart_txg;
|
uint64_t scn_restart_txg;
|
||||||
|
uint64_t scn_done_txg;
|
||||||
uint64_t scn_sync_start_time;
|
uint64_t scn_sync_start_time;
|
||||||
zio_t *scn_zio_root;
|
zio_t *scn_zio_root;
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2012 by Delphix. All rights reserved.
|
* Copyright (c) 2013 by Delphix. All rights reserved.
|
||||||
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
|
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
|
||||||
* Copyright (c) 2012, Joyent, Inc. All rights reserved.
|
* Copyright (c) 2012, Joyent, Inc. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
@ -530,7 +530,7 @@ typedef struct zpool_rewind_policy {
|
||||||
#define ZPOOL_CONFIG_SPLIT_GUID "split_guid"
|
#define ZPOOL_CONFIG_SPLIT_GUID "split_guid"
|
||||||
#define ZPOOL_CONFIG_SPLIT_LIST "guid_list"
|
#define ZPOOL_CONFIG_SPLIT_LIST "guid_list"
|
||||||
#define ZPOOL_CONFIG_REMOVING "removing"
|
#define ZPOOL_CONFIG_REMOVING "removing"
|
||||||
#define ZPOOL_CONFIG_RESILVERING "resilvering"
|
#define ZPOOL_CONFIG_RESILVER_TXG "resilver_txg"
|
||||||
#define ZPOOL_CONFIG_COMMENT "comment"
|
#define ZPOOL_CONFIG_COMMENT "comment"
|
||||||
#define ZPOOL_CONFIG_SUSPENDED "suspended" /* not stored on disk */
|
#define ZPOOL_CONFIG_SUSPENDED "suspended" /* not stored on disk */
|
||||||
#define ZPOOL_CONFIG_TIMESTAMP "timestamp" /* not stored on disk */
|
#define ZPOOL_CONFIG_TIMESTAMP "timestamp" /* not stored on disk */
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2012 by Delphix. All rights reserved.
|
* Copyright (c) 2013 by Delphix. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _SYS_VDEV_IMPL_H
|
#ifndef _SYS_VDEV_IMPL_H
|
||||||
|
@ -182,7 +182,7 @@ struct vdev {
|
||||||
uint64_t vdev_faulted; /* persistent faulted state */
|
uint64_t vdev_faulted; /* persistent faulted state */
|
||||||
uint64_t vdev_degraded; /* persistent degraded state */
|
uint64_t vdev_degraded; /* persistent degraded state */
|
||||||
uint64_t vdev_removed; /* persistent removed state */
|
uint64_t vdev_removed; /* persistent removed state */
|
||||||
uint64_t vdev_resilvering; /* persistent resilvering state */
|
uint64_t vdev_resilver_txg; /* persistent resilvering state */
|
||||||
uint64_t vdev_nparity; /* number of parity devices for raidz */
|
uint64_t vdev_nparity; /* number of parity devices for raidz */
|
||||||
char *vdev_path; /* vdev path (if any) */
|
char *vdev_path; /* vdev path (if any) */
|
||||||
char *vdev_devid; /* vdev devid (if any) */
|
char *vdev_devid; /* vdev devid (if any) */
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2012 by Delphix. All rights reserved.
|
* Copyright (c) 2013 by Delphix. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _SYS_ZFS_DEBUG_H
|
#ifndef _SYS_ZFS_DEBUG_H
|
||||||
|
@ -95,6 +95,7 @@ extern void zfs_dbgmsg_fini(void);
|
||||||
#define zfs_dbgmsg(...) dprintf(__VA_ARGS__)
|
#define zfs_dbgmsg(...) dprintf(__VA_ARGS__)
|
||||||
#else
|
#else
|
||||||
extern void zfs_dbgmsg(const char *fmt, ...);
|
extern void zfs_dbgmsg(const char *fmt, ...);
|
||||||
|
extern void zfs_dbgmsg_print(const char *tag);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef _KERNEL
|
#ifndef _KERNEL
|
||||||
|
|
|
@ -190,6 +190,7 @@ dsl_scan_setup_sync(void *arg, dmu_tx_t *tx)
|
||||||
scn->scn_phys.scn_errors = 0;
|
scn->scn_phys.scn_errors = 0;
|
||||||
scn->scn_phys.scn_to_examine = spa->spa_root_vdev->vdev_stat.vs_alloc;
|
scn->scn_phys.scn_to_examine = spa->spa_root_vdev->vdev_stat.vs_alloc;
|
||||||
scn->scn_restart_txg = 0;
|
scn->scn_restart_txg = 0;
|
||||||
|
scn->scn_done_txg = 0;
|
||||||
spa_scan_stat_init(spa);
|
spa_scan_stat_init(spa);
|
||||||
|
|
||||||
if (DSL_SCAN_IS_SCRUB_RESILVER(scn)) {
|
if (DSL_SCAN_IS_SCRUB_RESILVER(scn)) {
|
||||||
|
@ -776,7 +777,7 @@ dsl_scan_visitbp(blkptr_t *bp, const zbookmark_t *zb,
|
||||||
* Don't scan it now unless we need to because something
|
* Don't scan it now unless we need to because something
|
||||||
* under it was modified.
|
* under it was modified.
|
||||||
*/
|
*/
|
||||||
if (bp->blk_birth <= scn->scn_phys.scn_cur_max_txg) {
|
if (BP_PHYSICAL_BIRTH(bp) <= scn->scn_phys.scn_cur_max_txg) {
|
||||||
scan_funcs[scn->scn_phys.scn_func](dp, bp, zb);
|
scan_funcs[scn->scn_phys.scn_func](dp, bp, zb);
|
||||||
}
|
}
|
||||||
if (buf)
|
if (buf)
|
||||||
|
@ -1227,7 +1228,7 @@ dsl_scan_ddt_entry(dsl_scan_t *scn, enum zio_checksum checksum,
|
||||||
|
|
||||||
for (p = 0; p < DDT_PHYS_TYPES; p++, ddp++) {
|
for (p = 0; p < DDT_PHYS_TYPES; p++, ddp++) {
|
||||||
if (ddp->ddp_phys_birth == 0 ||
|
if (ddp->ddp_phys_birth == 0 ||
|
||||||
ddp->ddp_phys_birth > scn->scn_phys.scn_cur_max_txg)
|
ddp->ddp_phys_birth > scn->scn_phys.scn_max_txg)
|
||||||
continue;
|
continue;
|
||||||
ddt_bp_create(checksum, ddk, ddp, &bp);
|
ddt_bp_create(checksum, ddk, ddp, &bp);
|
||||||
|
|
||||||
|
@ -1475,6 +1476,16 @@ dsl_scan_sync(dsl_pool_t *dp, dmu_tx_t *tx)
|
||||||
if (scn->scn_phys.scn_state != DSS_SCANNING)
|
if (scn->scn_phys.scn_state != DSS_SCANNING)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (scn->scn_done_txg == tx->tx_txg) {
|
||||||
|
ASSERT(!scn->scn_pausing);
|
||||||
|
/* finished with scan. */
|
||||||
|
zfs_dbgmsg("txg %llu scan complete", tx->tx_txg);
|
||||||
|
dsl_scan_done(scn, B_TRUE, tx);
|
||||||
|
ASSERT3U(spa->spa_scrub_inflight, ==, 0);
|
||||||
|
dsl_scan_sync_state(scn, tx);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (scn->scn_phys.scn_ddt_bookmark.ddb_class <=
|
if (scn->scn_phys.scn_ddt_bookmark.ddb_class <=
|
||||||
scn->scn_phys.scn_ddt_class_max) {
|
scn->scn_phys.scn_ddt_class_max) {
|
||||||
zfs_dbgmsg("doing scan sync txg %llu; "
|
zfs_dbgmsg("doing scan sync txg %llu; "
|
||||||
|
@ -1510,9 +1521,9 @@ dsl_scan_sync(dsl_pool_t *dp, dmu_tx_t *tx)
|
||||||
(longlong_t)NSEC2MSEC(gethrtime() - scn->scn_sync_start_time));
|
(longlong_t)NSEC2MSEC(gethrtime() - scn->scn_sync_start_time));
|
||||||
|
|
||||||
if (!scn->scn_pausing) {
|
if (!scn->scn_pausing) {
|
||||||
/* finished with scan. */
|
scn->scn_done_txg = tx->tx_txg + 1;
|
||||||
zfs_dbgmsg("finished scan txg %llu", (longlong_t)tx->tx_txg);
|
zfs_dbgmsg("txg %llu traversal complete, waiting till txg %llu",
|
||||||
dsl_scan_done(scn, B_TRUE, tx);
|
tx->tx_txg, scn->scn_done_txg);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DSL_SCAN_IS_SCRUB_RESILVER(scn)) {
|
if (DSL_SCAN_IS_SCRUB_RESILVER(scn)) {
|
||||||
|
|
|
@ -4509,7 +4509,7 @@ spa_vdev_attach(spa_t *spa, uint64_t guid, nvlist_t *nvroot, int replacing)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* mark the device being resilvered */
|
/* mark the device being resilvered */
|
||||||
newvd->vdev_resilvering = B_TRUE;
|
newvd->vdev_resilver_txg = txg;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the parent is not a mirror, or if we're replacing, insert the new
|
* If the parent is not a mirror, or if we're replacing, insert the new
|
||||||
|
@ -5370,13 +5370,6 @@ spa_vdev_resilver_done_hunt(vdev_t *vd)
|
||||||
return (oldvd);
|
return (oldvd);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vd->vdev_resilvering && vdev_dtl_empty(vd, DTL_MISSING) &&
|
|
||||||
vdev_dtl_empty(vd, DTL_OUTAGE)) {
|
|
||||||
ASSERT(vd->vdev_ops->vdev_op_leaf);
|
|
||||||
vd->vdev_resilvering = B_FALSE;
|
|
||||||
vdev_config_dirty(vd->vdev_top);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check for a completed replacement. We always consider the first
|
* Check for a completed replacement. We always consider the first
|
||||||
* vdev in the list to be the oldest vdev, and the last one to be
|
* vdev in the list to be the oldest vdev, and the last one to be
|
||||||
|
@ -5466,6 +5459,8 @@ spa_vdev_resilver_done(spa_t *spa)
|
||||||
ASSERT(pvd->vdev_ops == &vdev_replacing_ops);
|
ASSERT(pvd->vdev_ops == &vdev_replacing_ops);
|
||||||
sguid = ppvd->vdev_child[1]->vdev_guid;
|
sguid = ppvd->vdev_child[1]->vdev_guid;
|
||||||
}
|
}
|
||||||
|
ASSERT(vd->vdev_resilver_txg == 0 || !vdev_dtl_required(vd));
|
||||||
|
|
||||||
spa_config_exit(spa, SCL_ALL, FTAG);
|
spa_config_exit(spa, SCL_ALL, FTAG);
|
||||||
if (spa_vdev_detach(spa, guid, pguid, B_TRUE) != 0)
|
if (spa_vdev_detach(spa, guid, pguid, B_TRUE) != 0)
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
|
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
|
||||||
* Copyright (c) 2012 by Delphix. All rights reserved.
|
* Copyright (c) 2013 by Delphix. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/spa.h>
|
#include <sys/spa.h>
|
||||||
|
@ -196,7 +196,12 @@ spa_config_write(spa_config_dirent_t *dp, nvlist_t *nvl)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Synchronize pool configuration to disk. This must be called with the
|
* Synchronize pool configuration to disk. This must be called with the
|
||||||
* namespace lock held.
|
* namespace lock held. Synchronizing the pool cache is typically done after
|
||||||
|
* the configuration has been synced to the MOS. This exposes a window where
|
||||||
|
* the MOS config will have been updated but the cache file has not. If
|
||||||
|
* the system were to crash at that instant then the cached config may not
|
||||||
|
* contain the correct information to open the pool and an explicity import
|
||||||
|
* would be required.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
spa_config_sync(spa_t *target, boolean_t removing, boolean_t postsysevent)
|
spa_config_sync(spa_t *target, boolean_t removing, boolean_t postsysevent)
|
||||||
|
|
|
@ -526,8 +526,8 @@ vdev_alloc(spa_t *spa, vdev_t **vdp, nvlist_t *nv, vdev_t *parent, uint_t id,
|
||||||
(void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_OFFLINE,
|
(void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_OFFLINE,
|
||||||
&vd->vdev_offline);
|
&vd->vdev_offline);
|
||||||
|
|
||||||
(void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_RESILVERING,
|
(void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_RESILVER_TXG,
|
||||||
&vd->vdev_resilvering);
|
&vd->vdev_resilver_txg);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* When importing a pool, we want to ignore the persistent fault
|
* When importing a pool, we want to ignore the persistent fault
|
||||||
|
@ -1682,6 +1682,75 @@ vdev_dtl_empty(vdev_t *vd, vdev_dtl_type_t t)
|
||||||
return (empty);
|
return (empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns the lowest txg in the DTL range.
|
||||||
|
*/
|
||||||
|
static uint64_t
|
||||||
|
vdev_dtl_min(vdev_t *vd)
|
||||||
|
{
|
||||||
|
space_seg_t *ss;
|
||||||
|
|
||||||
|
ASSERT(MUTEX_HELD(&vd->vdev_dtl_lock));
|
||||||
|
ASSERT3U(vd->vdev_dtl[DTL_MISSING].sm_space, !=, 0);
|
||||||
|
ASSERT0(vd->vdev_children);
|
||||||
|
|
||||||
|
ss = avl_first(&vd->vdev_dtl[DTL_MISSING].sm_root);
|
||||||
|
return (ss->ss_start - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns the highest txg in the DTL.
|
||||||
|
*/
|
||||||
|
static uint64_t
|
||||||
|
vdev_dtl_max(vdev_t *vd)
|
||||||
|
{
|
||||||
|
space_seg_t *ss;
|
||||||
|
|
||||||
|
ASSERT(MUTEX_HELD(&vd->vdev_dtl_lock));
|
||||||
|
ASSERT3U(vd->vdev_dtl[DTL_MISSING].sm_space, !=, 0);
|
||||||
|
ASSERT0(vd->vdev_children);
|
||||||
|
|
||||||
|
ss = avl_last(&vd->vdev_dtl[DTL_MISSING].sm_root);
|
||||||
|
return (ss->ss_end);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Determine if a resilvering vdev should remove any DTL entries from
|
||||||
|
* its range. If the vdev was resilvering for the entire duration of the
|
||||||
|
* scan then it should excise that range from its DTLs. Otherwise, this
|
||||||
|
* vdev is considered partially resilvered and should leave its DTL
|
||||||
|
* entries intact. The comment in vdev_dtl_reassess() describes how we
|
||||||
|
* excise the DTLs.
|
||||||
|
*/
|
||||||
|
static boolean_t
|
||||||
|
vdev_dtl_should_excise(vdev_t *vd)
|
||||||
|
{
|
||||||
|
spa_t *spa = vd->vdev_spa;
|
||||||
|
dsl_scan_t *scn = spa->spa_dsl_pool->dp_scan;
|
||||||
|
|
||||||
|
ASSERT0(scn->scn_phys.scn_errors);
|
||||||
|
ASSERT0(vd->vdev_children);
|
||||||
|
|
||||||
|
if (vd->vdev_resilver_txg == 0 ||
|
||||||
|
vd->vdev_dtl[DTL_MISSING].sm_space == 0)
|
||||||
|
return (B_TRUE);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When a resilver is initiated the scan will assign the scn_max_txg
|
||||||
|
* value to the highest txg value that exists in all DTLs. If this
|
||||||
|
* device's max DTL is not part of this scan (i.e. it is not in
|
||||||
|
* the range (scn_min_txg, scn_max_txg] then it is not eligible
|
||||||
|
* for excision.
|
||||||
|
*/
|
||||||
|
if (vdev_dtl_max(vd) <= scn->scn_phys.scn_max_txg) {
|
||||||
|
ASSERT3U(scn->scn_phys.scn_min_txg, <=, vdev_dtl_min(vd));
|
||||||
|
ASSERT3U(scn->scn_phys.scn_min_txg, <, vd->vdev_resilver_txg);
|
||||||
|
ASSERT3U(vd->vdev_resilver_txg, <=, scn->scn_phys.scn_max_txg);
|
||||||
|
return (B_TRUE);
|
||||||
|
}
|
||||||
|
return (B_FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Reassess DTLs after a config change or scrub completion.
|
* Reassess DTLs after a config change or scrub completion.
|
||||||
*/
|
*/
|
||||||
|
@ -1705,9 +1774,17 @@ vdev_dtl_reassess(vdev_t *vd, uint64_t txg, uint64_t scrub_txg, int scrub_done)
|
||||||
dsl_scan_t *scn = spa->spa_dsl_pool->dp_scan;
|
dsl_scan_t *scn = spa->spa_dsl_pool->dp_scan;
|
||||||
|
|
||||||
mutex_enter(&vd->vdev_dtl_lock);
|
mutex_enter(&vd->vdev_dtl_lock);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we've completed a scan cleanly then determine
|
||||||
|
* if this vdev should remove any DTLs. We only want to
|
||||||
|
* excise regions on vdevs that were available during
|
||||||
|
* the entire duration of this scan.
|
||||||
|
*/
|
||||||
if (scrub_txg != 0 &&
|
if (scrub_txg != 0 &&
|
||||||
(spa->spa_scrub_started ||
|
(spa->spa_scrub_started ||
|
||||||
(scn && scn->scn_phys.scn_errors == 0))) {
|
(scn != NULL && scn->scn_phys.scn_errors == 0)) &&
|
||||||
|
vdev_dtl_should_excise(vd)) {
|
||||||
/*
|
/*
|
||||||
* We completed a scrub up to scrub_txg. If we
|
* We completed a scrub up to scrub_txg. If we
|
||||||
* did it without rebooting, then the scrub dtl
|
* did it without rebooting, then the scrub dtl
|
||||||
|
@ -1746,6 +1823,16 @@ vdev_dtl_reassess(vdev_t *vd, uint64_t txg, uint64_t scrub_txg, int scrub_done)
|
||||||
else
|
else
|
||||||
space_map_walk(&vd->vdev_dtl[DTL_MISSING],
|
space_map_walk(&vd->vdev_dtl[DTL_MISSING],
|
||||||
space_map_add, &vd->vdev_dtl[DTL_OUTAGE]);
|
space_map_add, &vd->vdev_dtl[DTL_OUTAGE]);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the vdev was resilvering and no longer has any
|
||||||
|
* DTLs then reset its resilvering flag.
|
||||||
|
*/
|
||||||
|
if (vd->vdev_resilver_txg != 0 &&
|
||||||
|
vd->vdev_dtl[DTL_MISSING].sm_space == 0 &&
|
||||||
|
vd->vdev_dtl[DTL_OUTAGE].sm_space == 0)
|
||||||
|
vd->vdev_resilver_txg = 0;
|
||||||
|
|
||||||
mutex_exit(&vd->vdev_dtl_lock);
|
mutex_exit(&vd->vdev_dtl_lock);
|
||||||
|
|
||||||
if (txg != 0)
|
if (txg != 0)
|
||||||
|
@ -1922,12 +2009,9 @@ vdev_resilver_needed(vdev_t *vd, uint64_t *minp, uint64_t *maxp)
|
||||||
mutex_enter(&vd->vdev_dtl_lock);
|
mutex_enter(&vd->vdev_dtl_lock);
|
||||||
if (vd->vdev_dtl[DTL_MISSING].sm_space != 0 &&
|
if (vd->vdev_dtl[DTL_MISSING].sm_space != 0 &&
|
||||||
vdev_writeable(vd)) {
|
vdev_writeable(vd)) {
|
||||||
space_seg_t *ss;
|
|
||||||
|
|
||||||
ss = avl_first(&vd->vdev_dtl[DTL_MISSING].sm_root);
|
thismin = vdev_dtl_min(vd);
|
||||||
thismin = ss->ss_start - 1;
|
thismax = vdev_dtl_max(vd);
|
||||||
ss = avl_last(&vd->vdev_dtl[DTL_MISSING].sm_root);
|
|
||||||
thismax = ss->ss_end;
|
|
||||||
needed = B_TRUE;
|
needed = B_TRUE;
|
||||||
}
|
}
|
||||||
mutex_exit(&vd->vdev_dtl_lock);
|
mutex_exit(&vd->vdev_dtl_lock);
|
||||||
|
|
|
@ -218,28 +218,23 @@ vdev_config_generate(spa_t *spa, vdev_t *vd, boolean_t getstats,
|
||||||
|
|
||||||
VERIFY(nvlist_alloc(&nv, NV_UNIQUE_NAME, KM_PUSHPAGE) == 0);
|
VERIFY(nvlist_alloc(&nv, NV_UNIQUE_NAME, KM_PUSHPAGE) == 0);
|
||||||
|
|
||||||
VERIFY(nvlist_add_string(nv, ZPOOL_CONFIG_TYPE,
|
fnvlist_add_string(nv, ZPOOL_CONFIG_TYPE, vd->vdev_ops->vdev_op_type);
|
||||||
vd->vdev_ops->vdev_op_type) == 0);
|
|
||||||
if (!(flags & (VDEV_CONFIG_SPARE | VDEV_CONFIG_L2CACHE)))
|
if (!(flags & (VDEV_CONFIG_SPARE | VDEV_CONFIG_L2CACHE)))
|
||||||
VERIFY(nvlist_add_uint64(nv, ZPOOL_CONFIG_ID, vd->vdev_id)
|
fnvlist_add_uint64(nv, ZPOOL_CONFIG_ID, vd->vdev_id);
|
||||||
== 0);
|
fnvlist_add_uint64(nv, ZPOOL_CONFIG_GUID, vd->vdev_guid);
|
||||||
VERIFY(nvlist_add_uint64(nv, ZPOOL_CONFIG_GUID, vd->vdev_guid) == 0);
|
|
||||||
|
|
||||||
if (vd->vdev_path != NULL)
|
if (vd->vdev_path != NULL)
|
||||||
VERIFY(nvlist_add_string(nv, ZPOOL_CONFIG_PATH,
|
fnvlist_add_string(nv, ZPOOL_CONFIG_PATH, vd->vdev_path);
|
||||||
vd->vdev_path) == 0);
|
|
||||||
|
|
||||||
if (vd->vdev_devid != NULL)
|
if (vd->vdev_devid != NULL)
|
||||||
VERIFY(nvlist_add_string(nv, ZPOOL_CONFIG_DEVID,
|
fnvlist_add_string(nv, ZPOOL_CONFIG_DEVID, vd->vdev_devid);
|
||||||
vd->vdev_devid) == 0);
|
|
||||||
|
|
||||||
if (vd->vdev_physpath != NULL)
|
if (vd->vdev_physpath != NULL)
|
||||||
VERIFY(nvlist_add_string(nv, ZPOOL_CONFIG_PHYS_PATH,
|
fnvlist_add_string(nv, ZPOOL_CONFIG_PHYS_PATH,
|
||||||
vd->vdev_physpath) == 0);
|
vd->vdev_physpath);
|
||||||
|
|
||||||
if (vd->vdev_fru != NULL)
|
if (vd->vdev_fru != NULL)
|
||||||
VERIFY(nvlist_add_string(nv, ZPOOL_CONFIG_FRU,
|
fnvlist_add_string(nv, ZPOOL_CONFIG_FRU, vd->vdev_fru);
|
||||||
vd->vdev_fru) == 0);
|
|
||||||
|
|
||||||
if (vd->vdev_nparity != 0) {
|
if (vd->vdev_nparity != 0) {
|
||||||
ASSERT(strcmp(vd->vdev_ops->vdev_op_type,
|
ASSERT(strcmp(vd->vdev_ops->vdev_op_type,
|
||||||
|
@ -260,59 +255,54 @@ vdev_config_generate(spa_t *spa, vdev_t *vd, boolean_t getstats,
|
||||||
* that only support a single parity device -- older software
|
* that only support a single parity device -- older software
|
||||||
* will just ignore it.
|
* will just ignore it.
|
||||||
*/
|
*/
|
||||||
VERIFY(nvlist_add_uint64(nv, ZPOOL_CONFIG_NPARITY,
|
fnvlist_add_uint64(nv, ZPOOL_CONFIG_NPARITY, vd->vdev_nparity);
|
||||||
vd->vdev_nparity) == 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vd->vdev_wholedisk != -1ULL)
|
if (vd->vdev_wholedisk != -1ULL)
|
||||||
VERIFY(nvlist_add_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK,
|
fnvlist_add_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK,
|
||||||
vd->vdev_wholedisk) == 0);
|
vd->vdev_wholedisk);
|
||||||
|
|
||||||
if (vd->vdev_not_present)
|
if (vd->vdev_not_present)
|
||||||
VERIFY(nvlist_add_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT, 1) == 0);
|
fnvlist_add_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT, 1);
|
||||||
|
|
||||||
if (vd->vdev_isspare)
|
if (vd->vdev_isspare)
|
||||||
VERIFY(nvlist_add_uint64(nv, ZPOOL_CONFIG_IS_SPARE, 1) == 0);
|
fnvlist_add_uint64(nv, ZPOOL_CONFIG_IS_SPARE, 1);
|
||||||
|
|
||||||
if (!(flags & (VDEV_CONFIG_SPARE | VDEV_CONFIG_L2CACHE)) &&
|
if (!(flags & (VDEV_CONFIG_SPARE | VDEV_CONFIG_L2CACHE)) &&
|
||||||
vd == vd->vdev_top) {
|
vd == vd->vdev_top) {
|
||||||
VERIFY(nvlist_add_uint64(nv, ZPOOL_CONFIG_METASLAB_ARRAY,
|
fnvlist_add_uint64(nv, ZPOOL_CONFIG_METASLAB_ARRAY,
|
||||||
vd->vdev_ms_array) == 0);
|
vd->vdev_ms_array);
|
||||||
VERIFY(nvlist_add_uint64(nv, ZPOOL_CONFIG_METASLAB_SHIFT,
|
fnvlist_add_uint64(nv, ZPOOL_CONFIG_METASLAB_SHIFT,
|
||||||
vd->vdev_ms_shift) == 0);
|
vd->vdev_ms_shift);
|
||||||
VERIFY(nvlist_add_uint64(nv, ZPOOL_CONFIG_ASHIFT,
|
fnvlist_add_uint64(nv, ZPOOL_CONFIG_ASHIFT, vd->vdev_ashift);
|
||||||
vd->vdev_ashift) == 0);
|
fnvlist_add_uint64(nv, ZPOOL_CONFIG_ASIZE,
|
||||||
VERIFY(nvlist_add_uint64(nv, ZPOOL_CONFIG_ASIZE,
|
vd->vdev_asize);
|
||||||
vd->vdev_asize) == 0);
|
fnvlist_add_uint64(nv, ZPOOL_CONFIG_IS_LOG, vd->vdev_islog);
|
||||||
VERIFY(nvlist_add_uint64(nv, ZPOOL_CONFIG_IS_LOG,
|
|
||||||
vd->vdev_islog) == 0);
|
|
||||||
if (vd->vdev_removing)
|
if (vd->vdev_removing)
|
||||||
VERIFY(nvlist_add_uint64(nv, ZPOOL_CONFIG_REMOVING,
|
fnvlist_add_uint64(nv, ZPOOL_CONFIG_REMOVING,
|
||||||
vd->vdev_removing) == 0);
|
vd->vdev_removing);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vd->vdev_dtl_smo.smo_object != 0)
|
if (vd->vdev_dtl_smo.smo_object != 0)
|
||||||
VERIFY(nvlist_add_uint64(nv, ZPOOL_CONFIG_DTL,
|
fnvlist_add_uint64(nv, ZPOOL_CONFIG_DTL,
|
||||||
vd->vdev_dtl_smo.smo_object) == 0);
|
vd->vdev_dtl_smo.smo_object);
|
||||||
|
|
||||||
if (vd->vdev_crtxg)
|
if (vd->vdev_crtxg)
|
||||||
VERIFY(nvlist_add_uint64(nv, ZPOOL_CONFIG_CREATE_TXG,
|
fnvlist_add_uint64(nv, ZPOOL_CONFIG_CREATE_TXG, vd->vdev_crtxg);
|
||||||
vd->vdev_crtxg) == 0);
|
|
||||||
|
|
||||||
if (getstats) {
|
if (getstats) {
|
||||||
vdev_stat_t vs;
|
vdev_stat_t vs;
|
||||||
pool_scan_stat_t ps;
|
pool_scan_stat_t ps;
|
||||||
|
|
||||||
vdev_get_stats(vd, &vs);
|
vdev_get_stats(vd, &vs);
|
||||||
VERIFY(nvlist_add_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
|
fnvlist_add_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
|
||||||
(uint64_t *)&vs, sizeof (vs) / sizeof (uint64_t)) == 0);
|
(uint64_t *)&vs, sizeof (vs) / sizeof (uint64_t));
|
||||||
|
|
||||||
/* provide either current or previous scan information */
|
/* provide either current or previous scan information */
|
||||||
if (spa_scan_get_stats(spa, &ps) == 0) {
|
if (spa_scan_get_stats(spa, &ps) == 0) {
|
||||||
VERIFY(nvlist_add_uint64_array(nv,
|
fnvlist_add_uint64_array(nv,
|
||||||
ZPOOL_CONFIG_SCAN_STATS, (uint64_t *)&ps,
|
ZPOOL_CONFIG_SCAN_STATS, (uint64_t *)&ps,
|
||||||
sizeof (pool_scan_stat_t) / sizeof (uint64_t))
|
sizeof (pool_scan_stat_t) / sizeof (uint64_t));
|
||||||
== 0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -342,8 +332,8 @@ vdev_config_generate(spa_t *spa, vdev_t *vd, boolean_t getstats,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (idx) {
|
if (idx) {
|
||||||
VERIFY(nvlist_add_nvlist_array(nv,
|
fnvlist_add_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
|
||||||
ZPOOL_CONFIG_CHILDREN, child, idx) == 0);
|
child, idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (c = 0; c < idx; c++)
|
for (c = 0; c < idx; c++)
|
||||||
|
@ -355,26 +345,20 @@ vdev_config_generate(spa_t *spa, vdev_t *vd, boolean_t getstats,
|
||||||
const char *aux = NULL;
|
const char *aux = NULL;
|
||||||
|
|
||||||
if (vd->vdev_offline && !vd->vdev_tmpoffline)
|
if (vd->vdev_offline && !vd->vdev_tmpoffline)
|
||||||
VERIFY(nvlist_add_uint64(nv, ZPOOL_CONFIG_OFFLINE,
|
fnvlist_add_uint64(nv, ZPOOL_CONFIG_OFFLINE, B_TRUE);
|
||||||
B_TRUE) == 0);
|
if (vd->vdev_resilver_txg != 0)
|
||||||
if (vd->vdev_resilvering)
|
fnvlist_add_uint64(nv, ZPOOL_CONFIG_RESILVER_TXG,
|
||||||
VERIFY(nvlist_add_uint64(nv, ZPOOL_CONFIG_RESILVERING,
|
vd->vdev_resilver_txg);
|
||||||
B_TRUE) == 0);
|
|
||||||
if (vd->vdev_faulted)
|
if (vd->vdev_faulted)
|
||||||
VERIFY(nvlist_add_uint64(nv, ZPOOL_CONFIG_FAULTED,
|
fnvlist_add_uint64(nv, ZPOOL_CONFIG_FAULTED, B_TRUE);
|
||||||
B_TRUE) == 0);
|
|
||||||
if (vd->vdev_degraded)
|
if (vd->vdev_degraded)
|
||||||
VERIFY(nvlist_add_uint64(nv, ZPOOL_CONFIG_DEGRADED,
|
fnvlist_add_uint64(nv, ZPOOL_CONFIG_DEGRADED, B_TRUE);
|
||||||
B_TRUE) == 0);
|
|
||||||
if (vd->vdev_removed)
|
if (vd->vdev_removed)
|
||||||
VERIFY(nvlist_add_uint64(nv, ZPOOL_CONFIG_REMOVED,
|
fnvlist_add_uint64(nv, ZPOOL_CONFIG_REMOVED, B_TRUE);
|
||||||
B_TRUE) == 0);
|
|
||||||
if (vd->vdev_unspare)
|
if (vd->vdev_unspare)
|
||||||
VERIFY(nvlist_add_uint64(nv, ZPOOL_CONFIG_UNSPARE,
|
fnvlist_add_uint64(nv, ZPOOL_CONFIG_UNSPARE, B_TRUE);
|
||||||
B_TRUE) == 0);
|
|
||||||
if (vd->vdev_ishole)
|
if (vd->vdev_ishole)
|
||||||
VERIFY(nvlist_add_uint64(nv, ZPOOL_CONFIG_IS_HOLE,
|
fnvlist_add_uint64(nv, ZPOOL_CONFIG_IS_HOLE, B_TRUE);
|
||||||
B_TRUE) == 0);
|
|
||||||
|
|
||||||
switch (vd->vdev_stat.vs_aux) {
|
switch (vd->vdev_stat.vs_aux) {
|
||||||
case VDEV_AUX_ERR_EXCEEDED:
|
case VDEV_AUX_ERR_EXCEEDED:
|
||||||
|
@ -387,12 +371,11 @@ vdev_config_generate(spa_t *spa, vdev_t *vd, boolean_t getstats,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aux != NULL)
|
if (aux != NULL)
|
||||||
VERIFY(nvlist_add_string(nv, ZPOOL_CONFIG_AUX_STATE,
|
fnvlist_add_string(nv, ZPOOL_CONFIG_AUX_STATE, aux);
|
||||||
aux) == 0);
|
|
||||||
|
|
||||||
if (vd->vdev_splitting && vd->vdev_orig_guid != 0LL) {
|
if (vd->vdev_splitting && vd->vdev_orig_guid != 0LL) {
|
||||||
VERIFY(nvlist_add_uint64(nv, ZPOOL_CONFIG_ORIG_GUID,
|
fnvlist_add_uint64(nv, ZPOOL_CONFIG_ORIG_GUID,
|
||||||
vd->vdev_orig_guid) == 0);
|
vd->vdev_orig_guid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2012 by Delphix. All rights reserved.
|
* Copyright (c) 2013 by Delphix. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/zfs_context.h>
|
#include <sys/zfs_context.h>
|
||||||
|
@ -141,6 +141,19 @@ zfs_dbgmsg(const char *fmt, ...)
|
||||||
}
|
}
|
||||||
mutex_exit(&zfs_dbgmsgs_lock);
|
mutex_exit(&zfs_dbgmsgs_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
zfs_dbgmsg_print(const char *tag)
|
||||||
|
{
|
||||||
|
zfs_dbgmsg_t *zdm;
|
||||||
|
|
||||||
|
(void) printf("ZFS_DBGMSG(%s):\n", tag);
|
||||||
|
mutex_enter(&zfs_dbgmsgs_lock);
|
||||||
|
for (zdm = list_head(&zfs_dbgmsgs); zdm;
|
||||||
|
zdm = list_next(&zfs_dbgmsgs, zdm))
|
||||||
|
(void) printf("%s\n", zdm->zdm_msg);
|
||||||
|
mutex_exit(&zfs_dbgmsgs_lock);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(_KERNEL)
|
#if defined(_KERNEL)
|
||||||
|
|
Loading…
Reference in New Issue