diff options
author | Lin Ling <Lin.Ling@Sun.COM> | 2010-05-03 14:54:08 -0700 |
---|---|---|
committer | Lin Ling <Lin.Ling@Sun.COM> | 2010-05-03 14:54:08 -0700 |
commit | 3f9d6ad73e45c6823b409f93b0c8d4f62861d2d5 (patch) | |
tree | 195b2b1fa9e897a41897e12fed9b0c6e58d8107e /usr/src/cmd | |
parent | 3113f7cee6785cfe8d9e78c535cf9e2a79283275 (diff) | |
download | illumos-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.c | 5 | ||||
-rw-r--r-- | usr/src/cmd/fm/schemes/zfs/scheme.c | 5 | ||||
-rw-r--r-- | usr/src/cmd/mdb/common/modules/zfs/zfs.c | 105 | ||||
-rw-r--r-- | usr/src/cmd/ndmpd/ndmp/ndmpd_zfs.c | 2 | ||||
-rw-r--r-- | usr/src/cmd/truss/codes.c | 5 | ||||
-rw-r--r-- | usr/src/cmd/zdb/zdb.c | 105 | ||||
-rw-r--r-- | usr/src/cmd/zfs/zfs_main.c | 21 | ||||
-rw-r--r-- | usr/src/cmd/zpool/Makefile | 3 | ||||
-rw-r--r-- | usr/src/cmd/zpool/zpool_main.c | 397 | ||||
-rw-r--r-- | usr/src/cmd/zpool/zpool_util.h | 5 | ||||
-rw-r--r-- | usr/src/cmd/zpool/zpool_vdev.c | 23 | ||||
-rw-r--r-- | usr/src/cmd/ztest/ztest.c | 11 |
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); |