summaryrefslogtreecommitdiff
path: root/usr/src/cmd
diff options
context:
space:
mode:
authorLin Ling <Lin.Ling@Sun.COM>2010-05-03 14:54:08 -0700
committerLin Ling <Lin.Ling@Sun.COM>2010-05-03 14:54:08 -0700
commit3f9d6ad73e45c6823b409f93b0c8d4f62861d2d5 (patch)
tree195b2b1fa9e897a41897e12fed9b0c6e58d8107e /usr/src/cmd
parent3113f7cee6785cfe8d9e78c535cf9e2a79283275 (diff)
downloadillumos-joyent-3f9d6ad73e45c6823b409f93b0c8d4f62861d2d5.tar.gz
6675946 'zpool status' should show the progress of resilvering for individual disk.
6683750 scrub -s have to wait until resilver completed? 6841252 Resilvering not restartable - causing an excess reboot delay 6855073 spa scrub stats (eg %done) are reset on reboot 6891824 7410 NAS head "continually resilvering" following HDD replacement 6899970 scrub/resilver percent complete reporting in zpool status can be overly optimistic 6940889 add interval (count) args to zpool list 6944623 dbuf_read_done() locking performance improvement 6946760 mutex problem in bplist_enqueue() 6391915 RFE: provide interval arg to zpool status to monitor resilvering 6946512 want zfs_send() to pass back debug info 6943992 'zpool scrub' should not restart the existing scrub silently 6878281 zpool should store the time of last scrub/resilver and other zpool status info in pool properties. 6935158 Assertion failed: used <= spa_get_dspace(dd->dd_pool->dp_spa) 6944388 dsl_dataset_snapshot_reserve_space() causes dp_write_limit=max --HG-- rename : usr/src/uts/common/fs/zfs/dsl_scrub.c => usr/src/uts/common/fs/zfs/dsl_scan.c
Diffstat (limited to 'usr/src/cmd')
-rw-r--r--usr/src/cmd/availdevs/availdevs.c5
-rw-r--r--usr/src/cmd/fm/schemes/zfs/scheme.c5
-rw-r--r--usr/src/cmd/mdb/common/modules/zfs/zfs.c105
-rw-r--r--usr/src/cmd/ndmpd/ndmp/ndmpd_zfs.c2
-rw-r--r--usr/src/cmd/truss/codes.c5
-rw-r--r--usr/src/cmd/zdb/zdb.c105
-rw-r--r--usr/src/cmd/zfs/zfs_main.c21
-rw-r--r--usr/src/cmd/zpool/Makefile3
-rw-r--r--usr/src/cmd/zpool/zpool_main.c397
-rw-r--r--usr/src/cmd/zpool/zpool_util.h5
-rw-r--r--usr/src/cmd/zpool/zpool_vdev.c23
-rw-r--r--usr/src/cmd/ztest/ztest.c11
12 files changed, 453 insertions, 234 deletions
diff --git a/usr/src/cmd/availdevs/availdevs.c b/usr/src/cmd/availdevs/availdevs.c
index 1332a4f2bb..7ecec0a05c 100644
--- a/usr/src/cmd/availdevs/availdevs.c
+++ b/usr/src/cmd/availdevs/availdevs.c
@@ -20,8 +20,7 @@
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#include "availdevs.h"
@@ -134,7 +133,7 @@ add_pool_to_xml(nvlist_t *config, void *data)
nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE, &state) ||
nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, &devices) ||
nvlist_lookup_uint64_array(
- devices, ZPOOL_CONFIG_STATS, (uint64_t **)&vs, &n)) {
+ devices, ZPOOL_CONFIG_VDEV_STATS, (uint64_t **)&vs, &n)) {
return (-1);
}
diff --git a/usr/src/cmd/fm/schemes/zfs/scheme.c b/usr/src/cmd/fm/schemes/zfs/scheme.c
index ffa8ebf7f5..c0922f4d89 100644
--- a/usr/src/cmd/fm/schemes/zfs/scheme.c
+++ b/usr/src/cmd/fm/schemes/zfs/scheme.c
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#include <fm/fmd_fmri.h>
@@ -214,7 +213,7 @@ fmd_fmri_unusable(nvlist_t *nvl)
vdev_stat_t *vs;
uint_t c;
- (void) nvlist_lookup_uint64_array(vd, ZPOOL_CONFIG_STATS,
+ (void) nvlist_lookup_uint64_array(vd, ZPOOL_CONFIG_VDEV_STATS,
(uint64_t **)&vs, &c);
ret = (vs->vs_state < VDEV_STATE_DEGRADED);
diff --git a/usr/src/cmd/mdb/common/modules/zfs/zfs.c b/usr/src/cmd/mdb/common/modules/zfs/zfs.c
index e722007d72..e7bb40809b 100644
--- a/usr/src/cmd/mdb/common/modules/zfs/zfs.c
+++ b/usr/src/cmd/mdb/common/modules/zfs/zfs.c
@@ -129,6 +129,16 @@ getrefcount(uintptr_t addr, mdb_ctf_id_t *id,
return (GETMEMBID(addr + off, &rc_id, rc_count, *rc));
}
+static boolean_t
+strisprint(const char *cp)
+{
+ for (; *cp; cp++) {
+ if (!isprint(*cp))
+ return (B_FALSE);
+ }
+ return (B_TRUE);
+}
+
static int verbose;
static int
@@ -624,8 +634,10 @@ zap_leaf(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
zlc->l_entry.le_hash);
break;
case ZAP_CHUNK_ARRAY:
- mdb_printf(" %u: array \"%s\"\n",
- i, zlc->l_array.la_array);
+ mdb_printf(" %u: array", i);
+ if (strisprint((char *)zlc->l_array.la_array))
+ mdb_printf(" \"%s\"", zlc->l_array.la_array);
+ mdb_printf("\n");
if (verbose) {
int j;
mdb_printf(" ");
@@ -811,6 +823,77 @@ abuf_find(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
return (DCMD_OK);
}
+/* ARGSUSED */
+static int
+dbgmsg_cb(uintptr_t addr, const void *unknown, void *arg)
+{
+ static mdb_ctf_id_t id;
+ static boolean_t gotid;
+ static ulong_t off;
+
+ int *verbosep = arg;
+ time_t timestamp;
+ char buf[1024];
+
+ if (!gotid) {
+ if (mdb_ctf_lookup_by_name("struct zfs_dbgmsg", &id) == -1) {
+ mdb_warn("couldn't find struct zfs_dbgmsg");
+ return (WALK_ERR);
+ }
+ gotid = TRUE;
+ if (mdb_ctf_offsetof(id, "zdm_msg", &off) == -1) {
+ mdb_warn("couldn't find zdm_msg");
+ return (WALK_ERR);
+ }
+ off /= 8;
+ }
+
+
+ if (GETMEMBID(addr, &id, zdm_timestamp, timestamp)) {
+ return (WALK_ERR);
+ }
+
+ if (mdb_readstr(buf, sizeof (buf), addr + off) == -1) {
+ mdb_warn("failed to read zdm_msg at %p\n", addr + off);
+ return (DCMD_ERR);
+ }
+
+ if (*verbosep)
+ mdb_printf("%Y ", timestamp);
+
+ mdb_printf("%s\n", buf);
+
+ if (*verbosep)
+ (void) mdb_call_dcmd("whatis", addr, DCMD_ADDRSPEC, 0, NULL);
+
+ return (WALK_NEXT);
+}
+
+/* ARGSUSED */
+static int
+dbgmsg(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
+{
+ GElf_Sym sym;
+ int verbose = FALSE;
+
+ if (mdb_getopts(argc, argv,
+ 'v', MDB_OPT_SETBITS, TRUE, &verbose,
+ NULL) != argc)
+ return (DCMD_USAGE);
+
+ if (mdb_lookup_by_name("zfs_dbgmsgs", &sym)) {
+ mdb_warn("can't find zfs_dbgmsgs");
+ return (DCMD_ERR);
+ }
+
+ if (mdb_pwalk("list", dbgmsg_cb, &verbose, sym.st_value) != 0) {
+ mdb_warn("can't walk zfs_dbgmsgs");
+ return (DCMD_ERR);
+ }
+
+ return (DCMD_OK);
+}
+
/*ARGSUSED*/
static int
arc_print(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
@@ -2195,7 +2278,7 @@ reference_cb(uintptr_t addr, const void *ignored, void *arg)
uintptr_t ref_holder;
uintptr_t ref_removed;
uint64_t ref_number;
- boolean_t holder_is_str;
+ boolean_t holder_is_str = B_FALSE;
char holder_str[128];
boolean_t removed = (boolean_t)arg;
@@ -2212,18 +2295,8 @@ reference_cb(uintptr_t addr, const void *ignored, void *arg)
GETMEMBID(addr, &ref_id, ref_number, ref_number))
return (WALK_ERR);
- if (mdb_readstr(holder_str, sizeof (holder_str), ref_holder) != -1) {
- char *cp;
- holder_is_str = B_TRUE;
- for (cp = holder_str; *cp; cp++) {
- if (!isprint(*cp)) {
- holder_is_str = B_FALSE;
- break;
- }
- }
- } else {
- holder_is_str = B_FALSE;
- }
+ if (mdb_readstr(holder_str, sizeof (holder_str), ref_holder) != -1)
+ holder_is_str = strisprint(holder_str);
if (removed)
mdb_printf("removed ");
@@ -2940,6 +3013,8 @@ static const mdb_dcmd_t dcmds[] = {
sa_attr_table},
{ "sa_attr", ": attr_id",
"print SA attribute address when given sa_handle_t", sa_attr_print},
+ { "zfs_dbgmsg", ":[-v]",
+ "print zfs debug log", dbgmsg},
{ NULL }
};
diff --git a/usr/src/cmd/ndmpd/ndmp/ndmpd_zfs.c b/usr/src/cmd/ndmpd/ndmp/ndmpd_zfs.c
index 6a57828a24..4c12778ad1 100644
--- a/usr/src/cmd/ndmpd/ndmp/ndmpd_zfs.c
+++ b/usr/src/cmd/ndmpd/ndmp/ndmpd_zfs.c
@@ -610,7 +610,7 @@ ndmpd_zfs_backup_send_read(ndmpd_zfs_args_t *ndmpd_zfs_args)
}
err = zfs_send(zhp, fromsnap, ndmpd_zfs_args->nz_snapname, flags,
- ndmpd_zfs_args->nz_pipe_fd[PIPE_ZFS], NULL, NULL);
+ ndmpd_zfs_args->nz_pipe_fd[PIPE_ZFS], NULL, NULL, NULL);
if (err && !session->ns_data.dd_abort)
NDMPD_ZFS_LOG_ZERR(ndmpd_zfs_args, "zfs_send: %d", err);
diff --git a/usr/src/cmd/truss/codes.c b/usr/src/cmd/truss/codes.c
index 03f7b40ab0..7178537a06 100644
--- a/usr/src/cmd/truss/codes.c
+++ b/usr/src/cmd/truss/codes.c
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
@@ -1146,7 +1145,7 @@ const struct ioc {
"zfs_cmd_t" },
{ (uint_t)ZFS_IOC_POOL_TRYIMPORT, "ZFS_IOC_POOL_TRYIMPORT",
"zfs_cmd_t" },
- { (uint_t)ZFS_IOC_POOL_SCRUB, "ZFS_IOC_POOL_SCRUB",
+ { (uint_t)ZFS_IOC_POOL_SCAN, "ZFS_IOC_POOL_SCAN",
"zfs_cmd_t" },
{ (uint_t)ZFS_IOC_POOL_FREEZE, "ZFS_IOC_POOL_FREEZE",
"zfs_cmd_t" },
diff --git a/usr/src/cmd/zdb/zdb.c b/usr/src/cmd/zdb/zdb.c
index 61e79d0e84..2d36cf5488 100644
--- a/usr/src/cmd/zdb/zdb.c
+++ b/usr/src/cmd/zdb/zdb.c
@@ -150,6 +150,7 @@ usage(void)
"has altroot/not in a cachefile\n");
(void) fprintf(stderr, " -p <path> -- use one or more with "
"-e to specify path to vdev dir\n");
+ (void) fprintf(stderr, " -P print numbers parsable\n");
(void) fprintf(stderr, " -t <txg> -- highest txg to use when "
"searching for uberblocks\n");
(void) fprintf(stderr, "Specify an option more than once (e.g. -bb) "
@@ -196,6 +197,15 @@ dump_packed_nvlist(objset_t *os, uint64_t object, void *data, size_t size)
nvlist_free(nv);
}
+static void
+zdb_nicenum(uint64_t num, char *buf)
+{
+ if (dump_opt['P'])
+ (void) sprintf(buf, "%llu", (longlong_t)num);
+ else
+ nicenum(num, buf);
+}
+
const char dump_zap_stars[] = "****************************************";
const int dump_zap_width = sizeof (dump_zap_stars) - 1;
@@ -490,7 +500,7 @@ dump_spacemap(objset_t *os, space_map_obj_t *smo, space_map_t *sm)
*/
alloc = 0;
for (offset = 0; offset < smo->smo_objsize; offset += sizeof (entry)) {
- VERIFY(0 == dmu_read(os, smo->smo_object, offset,
+ VERIFY3U(0, ==, dmu_read(os, smo->smo_object, offset,
sizeof (entry), &entry, DMU_READ_PREFETCH));
if (SM_DEBUG_DECODE(entry)) {
(void) printf("\t [%6llu] %s: txg %llu, pass %llu\n",
@@ -525,12 +535,12 @@ dump_spacemap(objset_t *os, space_map_obj_t *smo, space_map_t *sm)
static void
dump_metaslab_stats(metaslab_t *msp)
{
- char maxbuf[5];
+ char maxbuf[32];
space_map_t *sm = &msp->ms_map;
avl_tree_t *t = sm->sm_pp_root;
int free_pct = sm->sm_space * 100 / sm->sm_size;
- nicenum(space_map_maxsize(sm), maxbuf);
+ zdb_nicenum(space_map_maxsize(sm), maxbuf);
(void) printf("\t %25s %10lu %7s %6s %4s %4d%%\n",
"segments", avl_numnodes(t), "maxsize", maxbuf,
@@ -544,9 +554,9 @@ dump_metaslab(metaslab_t *msp)
spa_t *spa = vd->vdev_spa;
space_map_t *sm = &msp->ms_map;
space_map_obj_t *smo = &msp->ms_smo;
- char freebuf[5];
+ char freebuf[32];
- nicenum(sm->sm_size - smo->smo_alloc, freebuf);
+ zdb_nicenum(sm->sm_size - smo->smo_alloc, freebuf);
(void) printf(
"\tmetaslab %6llu offset %12llx spacemap %6llu free %5s\n",
@@ -855,7 +865,7 @@ dump_history(spa_t *spa)
(void) snprintf(internalstr,
sizeof (internalstr),
"[internal %s txg:%lld] %s",
- hist_event_table[ievent], txg,
+ zfs_history_event_names[ievent], txg,
intstr);
cmd = internalstr;
}
@@ -966,6 +976,7 @@ visit_indirect(spa_t *spa, const dnode_phys_t *dnp,
ZIO_PRIORITY_ASYNC_READ, ZIO_FLAG_CANFAIL, &flags, zb);
if (err)
return (err);
+ ASSERT(buf->b_data);
/* recursively visit blocks below this */
cbp = buf->b_data;
@@ -1015,7 +1026,7 @@ dump_dsl_dir(objset_t *os, uint64_t object, void *data, size_t size)
{
dsl_dir_phys_t *dd = data;
time_t crtime;
- char nice[6];
+ char nice[32];
if (dd == NULL)
return;
@@ -1032,15 +1043,15 @@ dump_dsl_dir(objset_t *os, uint64_t object, void *data, size_t size)
(u_longlong_t)dd->dd_origin_obj);
(void) printf("\t\tchild_dir_zapobj = %llu\n",
(u_longlong_t)dd->dd_child_dir_zapobj);
- nicenum(dd->dd_used_bytes, nice);
+ zdb_nicenum(dd->dd_used_bytes, nice);
(void) printf("\t\tused_bytes = %s\n", nice);
- nicenum(dd->dd_compressed_bytes, nice);
+ zdb_nicenum(dd->dd_compressed_bytes, nice);
(void) printf("\t\tcompressed_bytes = %s\n", nice);
- nicenum(dd->dd_uncompressed_bytes, nice);
+ zdb_nicenum(dd->dd_uncompressed_bytes, nice);
(void) printf("\t\tuncompressed_bytes = %s\n", nice);
- nicenum(dd->dd_quota, nice);
+ zdb_nicenum(dd->dd_quota, nice);
(void) printf("\t\tquota = %s\n", nice);
- nicenum(dd->dd_reserved, nice);
+ zdb_nicenum(dd->dd_reserved, nice);
(void) printf("\t\treserved = %s\n", nice);
(void) printf("\t\tprops_zapobj = %llu\n",
(u_longlong_t)dd->dd_props_zapobj);
@@ -1050,7 +1061,7 @@ dump_dsl_dir(objset_t *os, uint64_t object, void *data, size_t size)
(u_longlong_t)dd->dd_flags);
#define DO(which) \
- nicenum(dd->dd_used_breakdown[DD_USED_ ## which], nice); \
+ zdb_nicenum(dd->dd_used_breakdown[DD_USED_ ## which], nice); \
(void) printf("\t\tused_breakdown[" #which "] = %s\n", nice)
DO(HEAD);
DO(SNAP);
@@ -1066,7 +1077,7 @@ dump_dsl_dataset(objset_t *os, uint64_t object, void *data, size_t size)
{
dsl_dataset_phys_t *ds = data;
time_t crtime;
- char used[6], compressed[6], uncompressed[6], unique[6];
+ char used[32], compressed[32], uncompressed[32], unique[32];
char blkbuf[BP_SPRINTF_LEN];
if (ds == NULL)
@@ -1074,10 +1085,10 @@ dump_dsl_dataset(objset_t *os, uint64_t object, void *data, size_t size)
ASSERT(size == sizeof (*ds));
crtime = ds->ds_creation_time;
- nicenum(ds->ds_used_bytes, used);
- nicenum(ds->ds_compressed_bytes, compressed);
- nicenum(ds->ds_uncompressed_bytes, uncompressed);
- nicenum(ds->ds_unique_bytes, unique);
+ zdb_nicenum(ds->ds_used_bytes, used);
+ zdb_nicenum(ds->ds_compressed_bytes, compressed);
+ zdb_nicenum(ds->ds_uncompressed_bytes, uncompressed);
+ zdb_nicenum(ds->ds_unique_bytes, unique);
sprintf_blkptr(blkbuf, &ds->ds_bp);
(void) printf("\t\tdir_obj = %llu\n",
@@ -1122,9 +1133,9 @@ dump_bplist(objset_t *mos, uint64_t object, char *name)
bplist_t bpl = { 0 };
blkptr_t blk, *bp = &blk;
uint64_t itor = 0;
- char bytes[6];
- char comp[6];
- char uncomp[6];
+ char bytes[32];
+ char comp[32];
+ char uncomp[32];
if (dump_opt['d'] < 3)
return;
@@ -1137,10 +1148,10 @@ dump_bplist(objset_t *mos, uint64_t object, char *name)
return;
}
- nicenum(bpl.bpl_phys->bpl_bytes, bytes);
+ zdb_nicenum(bpl.bpl_phys->bpl_bytes, bytes);
if (bpl.bpl_dbuf->db_size == sizeof (bplist_phys_t)) {
- nicenum(bpl.bpl_phys->bpl_comp, comp);
- nicenum(bpl.bpl_phys->bpl_uncomp, uncomp);
+ zdb_nicenum(bpl.bpl_phys->bpl_comp, comp);
+ zdb_nicenum(bpl.bpl_phys->bpl_uncomp, uncomp);
(void) printf("\n %s: %llu entries, %s (%s/%s comp)\n",
name, (u_longlong_t)bpl.bpl_phys->bpl_entries,
bytes, comp, uncomp);
@@ -1391,6 +1402,8 @@ static object_viewer_t *object_viewer[DMU_OT_NUMTYPES + 1] = {
dump_zap, /* SA Master Node */
dump_sa_attrs, /* SA attribute registration */
dump_sa_layouts, /* SA attribute layouts */
+ dump_zap, /* DSL scrub translations */
+ dump_none, /* fake dedup BP */
dump_unknown, /* Unknown type, must be last */
};
@@ -1402,7 +1415,8 @@ dump_object(objset_t *os, uint64_t object, int verbosity, int *print_header)
dnode_t *dn;
void *bonus = NULL;
size_t bsize = 0;
- char iblk[6], dblk[6], lsize[6], asize[6], bonus_size[6], fill[7];
+ char iblk[32], dblk[32], lsize[32], asize[32], fill[32];
+ char bonus_size[32];
char aux[50];
int error;
@@ -1426,11 +1440,11 @@ dump_object(objset_t *os, uint64_t object, int verbosity, int *print_header)
}
dmu_object_info_from_dnode(dn, &doi);
- nicenum(doi.doi_metadata_block_size, iblk);
- nicenum(doi.doi_data_block_size, dblk);
- nicenum(doi.doi_max_offset, lsize);
- nicenum(doi.doi_physical_blocks_512 << 9, asize);
- nicenum(doi.doi_bonus_size, bonus_size);
+ zdb_nicenum(doi.doi_metadata_block_size, iblk);
+ zdb_nicenum(doi.doi_data_block_size, dblk);
+ zdb_nicenum(doi.doi_max_offset, lsize);
+ zdb_nicenum(doi.doi_physical_blocks_512 << 9, asize);
+ zdb_nicenum(doi.doi_bonus_size, bonus_size);
(void) sprintf(fill, "%6.2f", 100.0 * doi.doi_fill_count *
doi.doi_data_block_size / (object == 0 ? DNODES_PER_BLOCK : 1) /
doi.doi_max_offset);
@@ -1492,7 +1506,7 @@ dump_object(objset_t *os, uint64_t object, int verbosity, int *print_header)
}
for (;;) {
- char segsize[6];
+ char segsize[32];
error = dnode_next_offset(dn,
0, &start, minlvl, blkfill, 0);
if (error)
@@ -1500,7 +1514,7 @@ dump_object(objset_t *os, uint64_t object, int verbosity, int *print_header)
end = start;
error = dnode_next_offset(dn,
DNODE_FIND_HOLE, &end, minlvl, blkfill, 0);
- nicenum(end - start, segsize);
+ zdb_nicenum(end - start, segsize);
(void) printf("\t\tsegment [%016llx, %016llx)"
" size %5s\n", (u_longlong_t)start,
(u_longlong_t)end, segsize);
@@ -1523,7 +1537,7 @@ dump_dir(objset_t *os)
dmu_objset_stats_t dds;
uint64_t object, object_count;
uint64_t refdbytes, usedobjs, scratch;
- char numbuf[8];
+ char numbuf[32];
char blkbuf[BP_SPRINTF_LEN + 20];
char osname[MAXNAMELEN];
char *type = "UNKNOWN";
@@ -1547,7 +1561,7 @@ dump_dir(objset_t *os)
ASSERT3U(usedobjs, ==, os->os_rootbp->blk_fill);
- nicenum(refdbytes, numbuf);
+ zdb_nicenum(refdbytes, numbuf);
if (verbosity >= 4) {
(void) sprintf(blkbuf, ", rootbp ");
@@ -1905,8 +1919,9 @@ zdb_count_block(spa_t *spa, zilog_t *zilog, zdb_cb_t *zcb, const blkptr_t *bp,
bp, NULL, NULL, ZIO_FLAG_CANFAIL)), ==, 0);
}
+/* ARGSUSED */
static int
-zdb_blkptr_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp,
+zdb_blkptr_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp, arc_buf_t *pbuf,
const zbookmark_t *zb, const dnode_phys_t *dnp, void *arg)
{
zdb_cb_t *zcb = arg;
@@ -2222,7 +2237,8 @@ dump_block_stats(spa_t *spa)
"\t avg\t comp\t%%Total\tType\n");
for (t = 0; t <= ZDB_OT_TOTAL; t++) {
- char csize[6], lsize[6], psize[6], asize[6], avg[6];
+ char csize[32], lsize[32], psize[32], asize[32];
+ char avg[32];
char *typename;
if (t < DMU_OT_NUMTYPES)
@@ -2258,11 +2274,11 @@ dump_block_stats(spa_t *spa)
zcb.zcb_type[ZB_TOTAL][t].zb_asize)
continue;
- nicenum(zb->zb_count, csize);
- nicenum(zb->zb_lsize, lsize);
- nicenum(zb->zb_psize, psize);
- nicenum(zb->zb_asize, asize);
- nicenum(zb->zb_asize / zb->zb_count, avg);
+ zdb_nicenum(zb->zb_count, csize);
+ zdb_nicenum(zb->zb_lsize, lsize);
+ zdb_nicenum(zb->zb_psize, psize);
+ zdb_nicenum(zb->zb_asize, asize);
+ zdb_nicenum(zb->zb_asize / zb->zb_count, avg);
(void) printf("%6s\t%5s\t%5s\t%5s\t%5s"
"\t%5.2f\t%6.2f\t",
@@ -2302,7 +2318,7 @@ typedef struct zdb_ddt_entry {
/* ARGSUSED */
static int
zdb_ddt_add_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp,
- const zbookmark_t *zb, const dnode_phys_t *dnp, void *arg)
+ arc_buf_t *pbuf, const zbookmark_t *zb, const dnode_phys_t *dnp, void *arg)
{
avl_tree_t *t = arg;
avl_index_t where;
@@ -2897,7 +2913,7 @@ main(int argc, char **argv)
dprintf_setup(&argc, argv);
- while ((c = getopt(argc, argv, "bcdhilmsuCDRSAFLXevp:t:U:")) != -1) {
+ while ((c = getopt(argc, argv, "bcdhilmsuCDRSAFLXevp:t:U:P")) != -1) {
switch (c) {
case 'b':
case 'c':
@@ -2920,6 +2936,7 @@ main(int argc, char **argv)
case 'L':
case 'X':
case 'e':
+ case 'P':
dump_opt[c]++;
break;
case 'v':
@@ -2970,7 +2987,7 @@ main(int argc, char **argv)
verbose = MAX(verbose, 1);
for (c = 0; c < 256; c++) {
- if (dump_all && !strchr("elAFLRSX", c))
+ if (dump_all && !strchr("elAFLRSXP", c))
dump_opt[c] = 1;
if (dump_opt[c])
dump_opt[c] += verbose;
diff --git a/usr/src/cmd/zfs/zfs_main.c b/usr/src/cmd/zfs/zfs_main.c
index 66f99ccfbf..6176a102d3 100644
--- a/usr/src/cmd/zfs/zfs_main.c
+++ b/usr/src/cmd/zfs/zfs_main.c
@@ -20,8 +20,7 @@
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#include <assert.h>
@@ -2573,6 +2572,8 @@ zfs_do_send(int argc, char **argv)
zfs_handle_t *zhp;
sendflags_t flags = { 0 };
int c, err;
+ nvlist_t *dbgnv;
+ boolean_t extraverbose = B_FALSE;
/* check options */
while ((c = getopt(argc, argv, ":i:I:RDpv")) != -1) {
@@ -2595,6 +2596,8 @@ zfs_do_send(int argc, char **argv)
flags.props = B_TRUE;
break;
case 'v':
+ if (flags.verbose)
+ extraverbose = B_TRUE;
flags.verbose = B_TRUE;
break;
case 'D':
@@ -2679,7 +2682,19 @@ zfs_do_send(int argc, char **argv)
if (flags.replicate && fromname == NULL)
flags.doall = B_TRUE;
- err = zfs_send(zhp, fromname, toname, flags, STDOUT_FILENO, NULL, 0);
+ err = zfs_send(zhp, fromname, toname, flags, STDOUT_FILENO, NULL, 0,
+ extraverbose ? &dbgnv : NULL);
+
+ if (extraverbose) {
+ /*
+ * dump_nvlist prints to stdout, but that's been
+ * redirected to a file. Make it print to stderr
+ * instead.
+ */
+ (void) dup2(STDERR_FILENO, STDOUT_FILENO);
+ dump_nvlist(dbgnv, 0);
+ nvlist_free(dbgnv);
+ }
zfs_close(zhp);
return (err != 0);
diff --git a/usr/src/cmd/zpool/Makefile b/usr/src/cmd/zpool/Makefile
index 728fdbe03b..0bf7b02767 100644
--- a/usr/src/cmd/zpool/Makefile
+++ b/usr/src/cmd/zpool/Makefile
@@ -19,8 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
+# Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
#
PROG= zpool
diff --git a/usr/src/cmd/zpool/zpool_main.c b/usr/src/cmd/zpool/zpool_main.c
index a31ee80255..c663cea5a1 100644
--- a/usr/src/cmd/zpool/zpool_main.c
+++ b/usr/src/cmd/zpool/zpool_main.c
@@ -20,8 +20,7 @@
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#include <assert.h>
@@ -42,7 +41,6 @@
#include <pwd.h>
#include <zone.h>
#include <sys/fs/zfs.h>
-
#include <sys/stat.h>
#include <libzfs.h>
@@ -215,7 +213,7 @@ get_usage(zpool_help_t idx) {
"[count]]\n"));
case HELP_LIST:
return (gettext("\tlist [-H] [-o property[,...]] "
- "[pool] ...\n"));
+ "[-T d|u] [pool] ... [interval [count]]\n"));
case HELP_OFFLINE:
return (gettext("\toffline [-t] <pool> <device> ...\n"));
case HELP_ONLINE:
@@ -228,7 +226,8 @@ get_usage(zpool_help_t idx) {
case HELP_SCRUB:
return (gettext("\tscrub [-s] <pool> ...\n"));
case HELP_STATUS:
- return (gettext("\tstatus [-vx] [pool] ...\n"));
+ return (gettext("\tstatus [-vx] [-T d|u] [pool] ... [interval "
+ "[count]]\n"));
case HELP_UPGRADE:
return (gettext("\tupgrade\n"
"\tupgrade -v\n"
@@ -519,11 +518,10 @@ zpool_do_add(int argc, char **argv)
}
/*
- * zpool remove <pool> <vdev> ...
+ * zpool remove <pool> <vdev> ...
*
- * Removes the given vdev from the pool. Currently, this only supports removing
- * spares and cache devices from the pool. Eventually, we'll want to support
- * removing leaf vdevs (as an alias for 'detach') as well as toplevel vdevs.
+ * Removes the given vdev from the pool. Currently, this supports removing
+ * spares, cache, and log devices from the pool.
*/
int
zpool_do_remove(int argc, char **argv)
@@ -1044,20 +1042,21 @@ print_status_config(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
{
nvlist_t **child;
uint_t c, children;
+ pool_scan_stat_t *ps = NULL;
vdev_stat_t *vs;
- char rbuf[6], wbuf[6], cbuf[6], repaired[7];
+ char rbuf[6], wbuf[6], cbuf[6];
char *vname;
uint64_t notpresent;
spare_cbdata_t cb;
char *state;
- verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_STATS,
- (uint64_t **)&vs, &c) == 0);
-
if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
&child, &children) != 0)
children = 0;
+ verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
+ (uint64_t **)&vs, &c) == 0);
+
state = zpool_state_to_name(vs->vs_state, vs->vs_aux);
if (isspare) {
/*
@@ -1147,14 +1146,16 @@ print_status_config(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
(void) printf(gettext("corrupted data"));
break;
}
- } else if (vs->vs_scrub_repaired != 0 && children == 0) {
- /*
- * Report bytes resilvered/repaired on leaf devices.
- */
- zfs_nicenum(vs->vs_scrub_repaired, repaired, sizeof (repaired));
- (void) printf(gettext(" %s %s"), repaired,
- (vs->vs_scrub_type == POOL_SCRUB_RESILVER) ?
- "resilvered" : "repaired");
+ }
+
+ (void) nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_SCAN_STATS,
+ (uint64_t **)&ps, &c);
+
+ if (ps && ps->pss_state == DSS_SCANNING &&
+ vs->vs_scan_processed != 0 && children == 0) {
+ (void) printf(gettext(" (%s)"),
+ (ps->pss_func == POOL_SCAN_RESILVER) ?
+ "resilvering" : "repairing");
}
(void) printf("\n");
@@ -1194,7 +1195,7 @@ print_import_config(const char *name, nvlist_t *nv, int namewidth, int depth)
strcmp(type, VDEV_TYPE_HOLE) == 0)
return;
- verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_STATS,
+ verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
(uint64_t **)&vs, &c) == 0);
(void) printf("\t%*s%-*s", depth, "", namewidth - depth, name);
@@ -1333,7 +1334,7 @@ show_import(nvlist_t *config)
verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
&nvroot) == 0);
- verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS,
+ verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_VDEV_STATS,
(uint64_t **)&vs, &vsc) == 0);
health = zpool_state_to_name(vs->vs_state, vs->vs_aux);
@@ -1400,6 +1401,11 @@ show_import(nvlist_t *config)
"read.\n"));
break;
+ case ZPOOL_STATUS_RESILVERING:
+ (void) printf(gettext("status: One or more devices were being "
+ "resilvered.\n"));
+ break;
+
default:
/*
* No other status can be seen when importing pools.
@@ -1990,13 +1996,13 @@ print_vdev_stats(zpool_handle_t *zhp, const char *name, nvlist_t *oldnv,
char *vname;
if (oldnv != NULL) {
- verify(nvlist_lookup_uint64_array(oldnv, ZPOOL_CONFIG_STATS,
- (uint64_t **)&oldvs, &c) == 0);
+ verify(nvlist_lookup_uint64_array(oldnv,
+ ZPOOL_CONFIG_VDEV_STATS, (uint64_t **)&oldvs, &c) == 0);
} else {
oldvs = &zerovs;
}
- verify(nvlist_lookup_uint64_array(newnv, ZPOOL_CONFIG_STATS,
+ verify(nvlist_lookup_uint64_array(newnv, ZPOOL_CONFIG_VDEV_STATS,
(uint64_t **)&newvs, &c) == 0);
if (strlen(name) + depth > cb->cb_namewidth)
@@ -2046,6 +2052,12 @@ print_vdev_stats(zpool_handle_t *zhp, const char *name, nvlist_t *oldnv,
return;
for (c = 0; c < children; c++) {
+ uint64_t ishole = B_FALSE;
+
+ if (nvlist_lookup_uint64(newchild[c],
+ ZPOOL_CONFIG_IS_HOLE, &ishole) == 0 && ishole)
+ continue;
+
vname = zpool_vdev_name(g_zfs, zhp, newchild[c], B_FALSE);
print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL,
newchild[c], cb, depth + 2);
@@ -2157,55 +2169,14 @@ get_namewidth(zpool_handle_t *zhp, void *data)
}
/*
- * zpool iostat [-T d|u] [-v] [pool] ... [interval [count]]
- *
- * -T Display a timestamp in date(1) or Unix format
- * -v Display statistics for individual vdevs
- *
- * This command can be tricky because we want to be able to deal with pool
- * creation/destruction as well as vdev configuration changes. The bulk of this
- * processing is handled by the pool_list_* routines in zpool_iter.c. We rely
- * on pool_list_update() to detect the addition of new pools. Configuration
- * changes are all handled within libzfs.
+ * Parse the input string, get the 'interval' and 'count' value if there is one.
*/
-int
-zpool_do_iostat(int argc, char **argv)
+static void
+get_interval_count(int *argcp, char **argv, unsigned long *iv,
+ unsigned long *cnt)
{
- int c;
- int ret;
- int npools;
unsigned long interval = 0, count = 0;
- zpool_list_t *list;
- boolean_t verbose = B_FALSE;
- iostat_cbdata_t cb;
-
- /* check options */
- while ((c = getopt(argc, argv, "T:v")) != -1) {
- switch (c) {
- case 'T':
- if (optarg) {
- if (*optarg == 'u')
- timestamp_fmt = UDATE;
- else if (*optarg == 'd')
- timestamp_fmt = DDATE;
- else
- usage(B_FALSE);
- } else {
- usage(B_FALSE);
- }
- break;
- case 'v':
- verbose = B_TRUE;
- break;
- case '?':
- (void) fprintf(stderr, gettext("invalid option '%c'\n"),
- optopt);
- usage(B_FALSE);
- }
- }
-
- argc -= optind;
- argv += optind;
+ int argc = *argcp, errno;
/*
* Determine if the last argument is an integer or a pool name
@@ -2222,7 +2193,6 @@ zpool_do_iostat(int argc, char **argv)
"cannot be zero\n"));
usage(B_FALSE);
}
-
/*
* Ignore the last parameter
*/
@@ -2239,7 +2209,7 @@ zpool_do_iostat(int argc, char **argv)
/*
* If the last argument is also an integer, then we have both a count
- * and an integer.
+ * and an interval.
*/
if (argc > 0 && isdigit(argv[argc - 1][0])) {
char *end;
@@ -2264,6 +2234,66 @@ zpool_do_iostat(int argc, char **argv)
}
}
+ *iv = interval;
+ *cnt = count;
+ *argcp = argc;
+}
+
+static void
+get_timestamp_arg(char c)
+{
+ if (c == 'u')
+ timestamp_fmt = UDATE;
+ else if (c == 'd')
+ timestamp_fmt = DDATE;
+ else
+ usage(B_FALSE);
+}
+
+/*
+ * zpool iostat [-v] [-T d|u] [pool] ... [interval [count]]
+ *
+ * -v Display statistics for individual vdevs
+ * -T Display a timestamp in date(1) or Unix format
+ *
+ * This command can be tricky because we want to be able to deal with pool
+ * creation/destruction as well as vdev configuration changes. The bulk of this
+ * processing is handled by the pool_list_* routines in zpool_iter.c. We rely
+ * on pool_list_update() to detect the addition of new pools. Configuration
+ * changes are all handled within libzfs.
+ */
+int
+zpool_do_iostat(int argc, char **argv)
+{
+ int c;
+ int ret;
+ int npools;
+ unsigned long interval = 0, count = 0;
+ zpool_list_t *list;
+ boolean_t verbose = B_FALSE;
+ iostat_cbdata_t cb;
+
+ /* check options */
+ while ((c = getopt(argc, argv, "T:v")) != -1) {
+ switch (c) {
+ case 'T':
+ get_timestamp_arg(*optarg);
+ break;
+ case 'v':
+ verbose = B_TRUE;
+ break;
+ case '?':
+ (void) fprintf(stderr, gettext("invalid option '%c'\n"),
+ optopt);
+ usage(B_FALSE);
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ get_interval_count(&argc, argv, &interval, &count);
+
/*
* Construct the list of all interesting pools.
*/
@@ -2464,12 +2494,13 @@ list_callback(zpool_handle_t *zhp, void *data)
}
/*
- * zpool list [-H] [-o prop[,prop]*] [pool] ...
+ * zpool list [-H] [-o prop[,prop]*] [-T d|u] [pool] ... [interval [count]]
*
* -H Scripted mode. Don't display headers, and separate properties
* by a single tab.
* -o List of properties to display. Defaults to
* "name,size,allocated,free,capacity,health,altroot"
+ * -T Display a timestamp in date(1) or Unix format
*
* List all pools in the system, whether or not they're healthy. Output space
* statistics for each one, as well as health status summary.
@@ -2483,9 +2514,10 @@ zpool_do_list(int argc, char **argv)
static char default_props[] =
"name,size,allocated,free,capacity,dedupratio,health,altroot";
char *props = default_props;
+ unsigned long interval = 0, count = 0;
/* check options */
- while ((c = getopt(argc, argv, ":Ho:")) != -1) {
+ while ((c = getopt(argc, argv, ":Ho:T:")) != -1) {
switch (c) {
case 'H':
cb.cb_scripted = B_TRUE;
@@ -2493,6 +2525,9 @@ zpool_do_list(int argc, char **argv)
case 'o':
props = optarg;
break;
+ case 'T':
+ get_timestamp_arg(*optarg);
+ break;
case ':':
(void) fprintf(stderr, gettext("missing argument for "
"'%c' option\n"), optopt);
@@ -2508,21 +2543,37 @@ zpool_do_list(int argc, char **argv)
argc -= optind;
argv += optind;
+ get_interval_count(&argc, argv, &interval, &count);
+
if (zprop_get_list(g_zfs, props, &cb.cb_proplist, ZFS_TYPE_POOL) != 0)
usage(B_FALSE);
cb.cb_first = B_TRUE;
- ret = for_each_pool(argc, argv, B_TRUE, &cb.cb_proplist,
- list_callback, &cb);
+ for (;;) {
- zprop_free_list(cb.cb_proplist);
+ if (timestamp_fmt != NODATE)
+ print_timestamp(timestamp_fmt);
- if (argc == 0 && cb.cb_first && !cb.cb_scripted) {
- (void) printf(gettext("no pools available\n"));
- return (0);
+ ret = for_each_pool(argc, argv, B_TRUE, &cb.cb_proplist,
+ list_callback, &cb);
+
+ if (argc == 0 && cb.cb_first && !cb.cb_scripted) {
+ (void) printf(gettext("no pools available\n"));
+ zprop_free_list(cb.cb_proplist);
+ return (0);
+ }
+
+ if (interval == 0)
+ break;
+
+ if (count != 0 && --count == 0)
+ break;
+
+ (void) sleep(interval);
}
+ zprop_free_list(cb.cb_proplist);
return (ret);
}
@@ -3106,7 +3157,7 @@ scrub_callback(zpool_handle_t *zhp, void *data)
return (1);
}
- err = zpool_scrub(zhp, cb->cb_type);
+ err = zpool_scan(zhp, cb->cb_type);
return (err != 0);
}
@@ -3122,13 +3173,13 @@ zpool_do_scrub(int argc, char **argv)
int c;
scrub_cbdata_t cb;
- cb.cb_type = POOL_SCRUB_EVERYTHING;
+ cb.cb_type = POOL_SCAN_SCRUB;
/* check options */
while ((c = getopt(argc, argv, "s")) != -1) {
switch (c) {
case 's':
- cb.cb_type = POOL_SCRUB_NONE;
+ cb.cb_type = POOL_SCAN_NONE;
break;
case '?':
(void) fprintf(stderr, gettext("invalid option '%c'\n"),
@@ -3163,62 +3214,103 @@ typedef struct status_cbdata {
* Print out detailed scrub status.
*/
void
-print_scrub_status(nvlist_t *nvroot)
+print_scan_status(pool_scan_stat_t *ps)
{
- vdev_stat_t *vs;
- uint_t vsc;
- time_t start, end, now;
+ time_t start, end;
+ uint64_t elapsed, mins_left;
+ uint64_t pass_exam, examined, total;
+ uint_t rate;
double fraction_done;
- uint64_t examined, total, minutes_left, minutes_taken;
- char *scrub_type;
+ char processed_buf[7], examined_buf[7], total_buf[7], rate_buf[7];
- verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS,
- (uint64_t **)&vs, &vsc) == 0);
+ (void) printf(gettext(" scan: "));
- /*
- * If there's never been a scrub, there's not much to say.
- */
- if (vs->vs_scrub_end == 0 && vs->vs_scrub_type == POOL_SCRUB_NONE) {
+ /* If there's never been a scan, there's not much to say. */
+ if (ps == NULL || ps->pss_func == POOL_SCAN_NONE ||
+ ps->pss_func >= POOL_SCAN_FUNCS) {
(void) printf(gettext("none requested\n"));
return;
}
- scrub_type = (vs->vs_scrub_type == POOL_SCRUB_RESILVER) ?
- "resilver" : "scrub";
-
- start = vs->vs_scrub_start;
- end = vs->vs_scrub_end;
- now = time(NULL);
- examined = vs->vs_scrub_examined;
- total = vs->vs_alloc;
-
- if (end != 0) {
- minutes_taken = (uint64_t)((end - start) / 60);
+ start = ps->pss_start_time;
+ end = ps->pss_end_time;
+ zfs_nicenum(ps->pss_processed, processed_buf, sizeof (processed_buf));
- (void) printf(gettext("%s %s after %lluh%um with %llu errors "
- "on %s"),
- scrub_type, vs->vs_scrub_complete ? "completed" : "stopped",
+ assert(ps->pss_func == POOL_SCAN_SCRUB ||
+ ps->pss_func == POOL_SCAN_RESILVER);
+ /*
+ * Scan is finished or canceled.
+ */
+ if (ps->pss_state == DSS_FINISHED) {
+ uint64_t minutes_taken = (end - start) / 60;
+ char *fmt;
+
+ if (ps->pss_func == POOL_SCAN_SCRUB) {
+ fmt = gettext("scrub repaired %s in %lluh%um with "
+ "%llu errors on %s");
+ } else if (ps->pss_func == POOL_SCAN_RESILVER) {
+ fmt = gettext("resilvered %s in %lluh%um with "
+ "%llu errors on %s");
+ }
+ /* LINTED */
+ (void) printf(fmt, processed_buf,
(u_longlong_t)(minutes_taken / 60),
(uint_t)(minutes_taken % 60),
- (u_longlong_t)vs->vs_scrub_errors, ctime(&end));
+ (u_longlong_t)ps->pss_errors,
+ ctime((time_t *)&end));
+ return;
+ } else if (ps->pss_state == DSS_CANCELED) {
+ if (ps->pss_func == POOL_SCAN_SCRUB) {
+ (void) printf(gettext("scrub canceled on %s"),
+ ctime(&end));
+ } else if (ps->pss_func == POOL_SCAN_RESILVER) {
+ (void) printf(gettext("resilver canceled on %s"),
+ ctime(&end));
+ }
return;
}
- if (examined == 0)
- examined = 1;
- if (examined > total)
- total = examined;
+ assert(ps->pss_state == DSS_SCANNING);
+ /*
+ * Scan is in progress.
+ */
+ if (ps->pss_func == POOL_SCAN_SCRUB) {
+ (void) printf(gettext("scrub in progress since %s"),
+ ctime(&start));
+ } else if (ps->pss_func == POOL_SCAN_RESILVER) {
+ (void) printf(gettext("resilver in progress since %s"),
+ ctime(&start));
+ }
+
+ examined = ps->pss_examined ? ps->pss_examined : 1;
+ total = ps->pss_to_examine;
fraction_done = (double)examined / total;
- minutes_left = (uint64_t)((now - start) *
- (1 - fraction_done) / fraction_done / 60);
- minutes_taken = (uint64_t)((now - start) / 60);
-
- (void) printf(gettext("%s in progress for %lluh%um, %.2f%% done, "
- "%lluh%um to go\n"),
- scrub_type, (u_longlong_t)(minutes_taken / 60),
- (uint_t)(minutes_taken % 60), 100 * fraction_done,
- (u_longlong_t)(minutes_left / 60), (uint_t)(minutes_left % 60));
+
+ /* elapsed time for this pass */
+ elapsed = time(NULL) - ps->pss_pass_start;
+ elapsed = elapsed ? elapsed : 1;
+ pass_exam = ps->pss_pass_exam ? ps->pss_pass_exam : 1;
+ rate = pass_exam / elapsed;
+ rate = rate ? rate : 1;
+ mins_left = ((total - examined) / rate) / 60;
+
+ zfs_nicenum(examined, examined_buf, sizeof (examined_buf));
+ zfs_nicenum(total, total_buf, sizeof (total_buf));
+ zfs_nicenum(rate, rate_buf, sizeof (rate_buf));
+
+ (void) printf(gettext(" %s scanned out of %s at "
+ "%s/s, %lluh%um to go\n"), examined_buf, total_buf, rate_buf,
+ (u_longlong_t)(mins_left / 60),
+ (uint_t)(mins_left % 60));
+
+ if (ps->pss_func == POOL_SCAN_RESILVER) {
+ (void) printf(gettext(" %s resilvered, %.2f%% done\n"),
+ processed_buf, 100 * fraction_done);
+ } else if (ps->pss_func == POOL_SCAN_SCRUB) {
+ (void) printf(gettext(" %s repaired, %.2f%% done\n"),
+ processed_buf, 100 * fraction_done);
+ }
}
static void
@@ -3378,7 +3470,7 @@ status_callback(zpool_handle_t *zhp, void *data)
verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
&nvroot) == 0);
- verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS,
+ verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_VDEV_STATS,
(uint64_t **)&vs, &c) == 0);
health = zpool_state_to_name(vs->vs_state, vs->vs_aux);
@@ -3451,7 +3543,6 @@ status_callback(zpool_handle_t *zhp, void *data)
"replace'.\n"));
break;
-
case ZPOOL_STATUS_RESILVERING:
(void) printf(gettext("status: One or more devices is "
"currently being resilvered. The pool will\n\tcontinue "
@@ -3549,10 +3640,11 @@ status_callback(zpool_handle_t *zhp, void *data)
uint64_t nerr;
nvlist_t **spares, **l2cache;
uint_t nspares, nl2cache;
+ pool_scan_stat_t *ps = NULL;
-
- (void) printf(gettext(" scrub: "));
- print_scrub_status(nvroot);
+ (void) nvlist_lookup_uint64_array(nvroot,
+ ZPOOL_CONFIG_SCAN_STATS, (uint64_t **)&ps, &c);
+ print_scan_status(ps);
namewidth = max_width(zhp, nvroot, 0, 0);
if (namewidth < 10)
@@ -3620,11 +3712,12 @@ status_callback(zpool_handle_t *zhp, void *data)
}
/*
- * zpool status [-vx] [pool] ...
+ * zpool status [-vx] [-T d|u] [pool] ... [interval [count]]
*
* -v Display complete error logs
* -x Display only pools with potential problems
* -D Display dedup status (undocumented)
+ * -T Display a timestamp in date(1) or Unix format
*
* Describes the health status of all pools or some subset.
*/
@@ -3633,10 +3726,11 @@ zpool_do_status(int argc, char **argv)
{
int c;
int ret;
+ unsigned long interval = 0, count = 0;
status_cbdata_t cb = { 0 };
/* check options */
- while ((c = getopt(argc, argv, "vxD")) != -1) {
+ while ((c = getopt(argc, argv, "vxDT:")) != -1) {
switch (c) {
case 'v':
cb.cb_verbose = B_TRUE;
@@ -3647,6 +3741,9 @@ zpool_do_status(int argc, char **argv)
case 'D':
cb.cb_dedup_stats = B_TRUE;
break;
+ case 'T':
+ get_timestamp_arg(*optarg);
+ break;
case '?':
(void) fprintf(stderr, gettext("invalid option '%c'\n"),
optopt);
@@ -3657,19 +3754,38 @@ zpool_do_status(int argc, char **argv)
argc -= optind;
argv += optind;
- cb.cb_first = B_TRUE;
+ get_interval_count(&argc, argv, &interval, &count);
if (argc == 0)
cb.cb_allpools = B_TRUE;
- ret = for_each_pool(argc, argv, B_TRUE, NULL, status_callback, &cb);
+ cb.cb_first = B_TRUE;
- if (argc == 0 && cb.cb_count == 0)
- (void) printf(gettext("no pools available\n"));
- else if (cb.cb_explain && cb.cb_first && cb.cb_allpools)
- (void) printf(gettext("all pools are healthy\n"));
+ for (;;) {
+ if (timestamp_fmt != NODATE)
+ print_timestamp(timestamp_fmt);
- return (ret);
+ ret = for_each_pool(argc, argv, B_TRUE, NULL,
+ status_callback, &cb);
+
+ if (argc == 0 && cb.cb_count == 0)
+ (void) printf(gettext("no pools available\n"));
+ else if (cb.cb_explain && cb.cb_first && cb.cb_allpools)
+ (void) printf(gettext("all pools are healthy\n"));
+
+ if (ret != 0)
+ return (ret);
+
+ if (interval == 0)
+ break;
+
+ if (count != 0 && --count == 0)
+ break;
+
+ (void) sleep(interval);
+ }
+
+ return (0);
}
typedef struct upgrade_cbdata {
@@ -3890,6 +4006,7 @@ zpool_do_upgrade(int argc, char **argv)
(void) printf(gettext(" 22 Received properties\n"));
(void) printf(gettext(" 23 Slim ZIL\n"));
(void) printf(gettext(" 24 System attributes\n"));
+ (void) printf(gettext(" 25 Improved scrub stats\n"));
(void) printf(gettext("\nFor more information on a particular "
"version, including supported releases, see:\n\n"));
(void) printf("http://www.opensolaris.org/os/community/zfs/"
@@ -3993,7 +4110,7 @@ get_history_one(zpool_handle_t *zhp, void *data)
(void) snprintf(internalstr,
sizeof (internalstr),
"[internal %s txg:%lld] %s",
- hist_event_table[ievent], txg,
+ zfs_history_event_names[ievent], txg,
pathstr);
cmdstr = internalstr;
}
diff --git a/usr/src/cmd/zpool/zpool_util.h b/usr/src/cmd/zpool/zpool_util.h
index a18b8b705f..134c730fcf 100644
--- a/usr/src/cmd/zpool/zpool_util.h
+++ b/usr/src/cmd/zpool/zpool_util.h
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#ifndef ZPOOL_UTIL_H
@@ -45,7 +44,7 @@ uint_t num_logs(nvlist_t *nv);
*/
nvlist_t *make_root_vdev(zpool_handle_t *zhp, int force, int check_rep,
- boolean_t isreplace, boolean_t dryrun, int argc, char **argv);
+ boolean_t replacing, boolean_t dryrun, int argc, char **argv);
nvlist_t *split_mirror_vdev(zpool_handle_t *zhp, char *newname,
nvlist_t *props, splitflags_t flags, int argc, char **argv);
diff --git a/usr/src/cmd/zpool/zpool_vdev.c b/usr/src/cmd/zpool/zpool_vdev.c
index 3c725d232c..53c2e60b7d 100644
--- a/usr/src/cmd/zpool/zpool_vdev.c
+++ b/usr/src/cmd/zpool/zpool_vdev.c
@@ -20,8 +20,7 @@
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/*
@@ -1004,8 +1003,8 @@ is_spare(nvlist_t *config, const char *path)
return (B_FALSE);
}
free(name);
-
(void) close(fd);
+
verify(nvlist_lookup_uint64(label, ZPOOL_CONFIG_GUID, &guid) == 0);
nvlist_free(label);
@@ -1029,8 +1028,8 @@ is_spare(nvlist_t *config, const char *path)
* the majority of this task.
*/
static int
-check_in_use(nvlist_t *config, nvlist_t *nv, int force, int isreplacing,
- int isspare)
+check_in_use(nvlist_t *config, nvlist_t *nv, boolean_t force,
+ boolean_t replacing, boolean_t isspare)
{
nvlist_t **child;
uint_t c, children;
@@ -1051,13 +1050,14 @@ check_in_use(nvlist_t *config, nvlist_t *nv, int force, int isreplacing,
* hot spare within the same pool. If so, we allow it
* regardless of what libdiskmgt or zpool_in_use() says.
*/
- if (isreplacing) {
+ if (replacing) {
if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK,
&wholedisk) == 0 && wholedisk)
(void) snprintf(buf, sizeof (buf), "%ss0",
path);
else
(void) strlcpy(buf, path, sizeof (buf));
+
if (is_spare(config, buf))
return (0);
}
@@ -1073,21 +1073,21 @@ check_in_use(nvlist_t *config, nvlist_t *nv, int force, int isreplacing,
for (c = 0; c < children; c++)
if ((ret = check_in_use(config, child[c], force,
- isreplacing, B_FALSE)) != 0)
+ replacing, B_FALSE)) != 0)
return (ret);
if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
&child, &children) == 0)
for (c = 0; c < children; c++)
if ((ret = check_in_use(config, child[c], force,
- isreplacing, B_TRUE)) != 0)
+ replacing, B_TRUE)) != 0)
return (ret);
if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
&child, &children) == 0)
for (c = 0; c < children; c++)
if ((ret = check_in_use(config, child[c], force,
- isreplacing, B_FALSE)) != 0)
+ replacing, B_FALSE)) != 0)
return (ret);
return (0);
@@ -1419,7 +1419,7 @@ split_mirror_vdev(zpool_handle_t *zhp, char *newname, nvlist_t *props,
*/
nvlist_t *
make_root_vdev(zpool_handle_t *zhp, int force, int check_rep,
- boolean_t isreplacing, boolean_t dryrun, int argc, char **argv)
+ boolean_t replacing, boolean_t dryrun, int argc, char **argv)
{
nvlist_t *newroot;
nvlist_t *poolconfig = NULL;
@@ -1442,8 +1442,7 @@ make_root_vdev(zpool_handle_t *zhp, int force, int check_rep,
* uses (such as a dedicated dump device) that even '-f' cannot
* override.
*/
- if (check_in_use(poolconfig, newroot, force, isreplacing,
- B_FALSE) != 0) {
+ if (check_in_use(poolconfig, newroot, force, replacing, B_FALSE) != 0) {
nvlist_free(newroot);
return (NULL);
}
diff --git a/usr/src/cmd/ztest/ztest.c b/usr/src/cmd/ztest/ztest.c
index eea3aa0d39..e0fabd7234 100644
--- a/usr/src/cmd/ztest/ztest.c
+++ b/usr/src/cmd/ztest/ztest.c
@@ -93,6 +93,7 @@
#include <sys/metaslab_impl.h>
#include <sys/dsl_prop.h>
#include <sys/dsl_dataset.h>
+#include <sys/dsl_scan.h>
#include <sys/refcount.h>
#include <stdio.h>
#include <stdio_ext.h>
@@ -284,9 +285,9 @@ ztest_info_t ztest_info[] = {
{ ztest_spa_rename, 1, &zopt_rarely },
{ ztest_scrub, 1, &zopt_rarely },
{ ztest_dsl_dataset_promote_busy, 1, &zopt_rarely },
- { ztest_vdev_attach_detach, 1, &zopt_rarely },
+ { ztest_vdev_attach_detach, 1, &zopt_rarely },
{ ztest_vdev_LUN_growth, 1, &zopt_rarely },
- { ztest_vdev_add_remove, 1, &zopt_vdevtime },
+ { ztest_vdev_add_remove, 1, &zopt_vdevtime },
{ ztest_vdev_aux_add_remove, 1, &zopt_vdevtime },
};
@@ -4662,9 +4663,9 @@ ztest_scrub(ztest_ds_t *zd, uint64_t id)
ztest_shared_t *zs = ztest_shared;
spa_t *spa = zs->zs_spa;
- (void) spa_scrub(spa, POOL_SCRUB_EVERYTHING);
+ (void) spa_scan(spa, POOL_SCAN_SCRUB);
(void) poll(NULL, 0, 100); /* wait a moment, then force a restart */
- (void) spa_scrub(spa, POOL_SCRUB_EVERYTHING);
+ (void) spa_scan(spa, POOL_SCAN_SCRUB);
}
/*
@@ -4817,7 +4818,7 @@ ztest_spa_import_export(char *oldname, char *newname)
* Kick off a scrub to tickle scrub/export races.
*/
if (ztest_random(2) == 0)
- (void) spa_scrub(spa, POOL_SCRUB_EVERYTHING);
+ (void) spa_scan(spa, POOL_SCAN_SCRUB);
pool_guid = spa_guid(spa);
spa_close(spa, FTAG);