1789Sahrens /* 2789Sahrens * CDDL HEADER START 3789Sahrens * 4789Sahrens * The contents of this file are subject to the terms of the 51544Seschrock * Common Development and Distribution License (the "License"). 61544Seschrock * You may not use this file except in compliance with the License. 7789Sahrens * 8789Sahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9789Sahrens * or http://www.opensolaris.org/os/licensing. 10789Sahrens * See the License for the specific language governing permissions 11789Sahrens * and limitations under the License. 12789Sahrens * 13789Sahrens * When distributing Covered Code, include this CDDL HEADER in each 14789Sahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15789Sahrens * If applicable, add the following below this CDDL HEADER, with the 16789Sahrens * fields enclosed by brackets "[]" replaced with your own identifying 17789Sahrens * information: Portions Copyright [yyyy] [name of copyright owner] 18789Sahrens * 19789Sahrens * CDDL HEADER END 20789Sahrens */ 21789Sahrens /* 22*7754SJeff.Bonwick@Sun.COM * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23789Sahrens * Use is subject to license terms. 24789Sahrens */ 25789Sahrens 26789Sahrens #include <assert.h> 27789Sahrens #include <sys/zfs_context.h> 28789Sahrens #include <sys/avl.h> 29789Sahrens #include <string.h> 30789Sahrens #include <stdio.h> 31789Sahrens #include <stdlib.h> 32789Sahrens #include <sys/spa.h> 33789Sahrens #include <sys/fs/zfs.h> 341544Seschrock #include <sys/refcount.h> 35789Sahrens 36789Sahrens /* 37789Sahrens * Routines needed by more than one client of libzpool. 38789Sahrens */ 39789Sahrens 40789Sahrens void 41789Sahrens nicenum(uint64_t num, char *buf) 42789Sahrens { 43789Sahrens uint64_t n = num; 44789Sahrens int index = 0; 45789Sahrens char u; 46789Sahrens 47789Sahrens while (n >= 1024) { 48789Sahrens n = (n + (1024 / 2)) / 1024; /* Round up or down */ 49789Sahrens index++; 50789Sahrens } 51789Sahrens 52789Sahrens u = " KMGTPE"[index]; 53789Sahrens 54789Sahrens if (index == 0) { 55789Sahrens (void) sprintf(buf, "%llu", (u_longlong_t)n); 56789Sahrens } else if (n < 10 && (num & (num - 1)) != 0) { 57789Sahrens (void) sprintf(buf, "%.2f%c", 58789Sahrens (double)num / (1ULL << 10 * index), u); 59789Sahrens } else if (n < 100 && (num & (num - 1)) != 0) { 60789Sahrens (void) sprintf(buf, "%.1f%c", 61789Sahrens (double)num / (1ULL << 10 * index), u); 62789Sahrens } else { 63789Sahrens (void) sprintf(buf, "%llu%c", (u_longlong_t)n, u); 64789Sahrens } 65789Sahrens } 66789Sahrens 67789Sahrens static void 68*7754SJeff.Bonwick@Sun.COM show_vdev_stats(const char *desc, const char *ctype, nvlist_t *nv, int indent) 69789Sahrens { 70*7754SJeff.Bonwick@Sun.COM vdev_stat_t *vs; 71*7754SJeff.Bonwick@Sun.COM vdev_stat_t v0 = { 0 }; 72*7754SJeff.Bonwick@Sun.COM uint64_t sec; 73*7754SJeff.Bonwick@Sun.COM uint64_t is_log = 0; 74789Sahrens nvlist_t **child; 75789Sahrens uint_t c, children; 76789Sahrens char used[6], avail[6]; 77789Sahrens char rops[6], wops[6], rbytes[6], wbytes[6], rerr[6], werr[6], cerr[6]; 784527Sperrin char *prefix = ""; 79789Sahrens 80*7754SJeff.Bonwick@Sun.COM if (indent == 0 && desc != NULL) { 81*7754SJeff.Bonwick@Sun.COM (void) printf(" " 82789Sahrens " capacity operations bandwidth ---- errors ----\n"); 83*7754SJeff.Bonwick@Sun.COM (void) printf("description " 84789Sahrens "used avail read write read write read write cksum\n"); 85789Sahrens } 86789Sahrens 87*7754SJeff.Bonwick@Sun.COM if (desc != NULL) { 88*7754SJeff.Bonwick@Sun.COM (void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_IS_LOG, &is_log); 89*7754SJeff.Bonwick@Sun.COM 90*7754SJeff.Bonwick@Sun.COM if (is_log) 91*7754SJeff.Bonwick@Sun.COM prefix = "log "; 924527Sperrin 93*7754SJeff.Bonwick@Sun.COM if (nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_STATS, 94*7754SJeff.Bonwick@Sun.COM (uint64_t **)&vs, &c) != 0) 95*7754SJeff.Bonwick@Sun.COM vs = &v0; 96789Sahrens 97*7754SJeff.Bonwick@Sun.COM sec = MAX(1, vs->vs_timestamp / NANOSEC); 98789Sahrens 99*7754SJeff.Bonwick@Sun.COM nicenum(vs->vs_alloc, used); 100*7754SJeff.Bonwick@Sun.COM nicenum(vs->vs_space - vs->vs_alloc, avail); 101*7754SJeff.Bonwick@Sun.COM nicenum(vs->vs_ops[ZIO_TYPE_READ] / sec, rops); 102*7754SJeff.Bonwick@Sun.COM nicenum(vs->vs_ops[ZIO_TYPE_WRITE] / sec, wops); 103*7754SJeff.Bonwick@Sun.COM nicenum(vs->vs_bytes[ZIO_TYPE_READ] / sec, rbytes); 104*7754SJeff.Bonwick@Sun.COM nicenum(vs->vs_bytes[ZIO_TYPE_WRITE] / sec, wbytes); 105*7754SJeff.Bonwick@Sun.COM nicenum(vs->vs_read_errors, rerr); 106*7754SJeff.Bonwick@Sun.COM nicenum(vs->vs_write_errors, werr); 107*7754SJeff.Bonwick@Sun.COM nicenum(vs->vs_checksum_errors, cerr); 108789Sahrens 109*7754SJeff.Bonwick@Sun.COM (void) printf("%*s%s%*s%*s%*s %5s %5s %5s %5s %5s %5s %5s\n", 110*7754SJeff.Bonwick@Sun.COM indent, "", 111*7754SJeff.Bonwick@Sun.COM prefix, 112*7754SJeff.Bonwick@Sun.COM indent + strlen(prefix) - 25 - (vs->vs_space ? 0 : 12), 113*7754SJeff.Bonwick@Sun.COM desc, 114*7754SJeff.Bonwick@Sun.COM vs->vs_space ? 6 : 0, vs->vs_space ? used : "", 115*7754SJeff.Bonwick@Sun.COM vs->vs_space ? 6 : 0, vs->vs_space ? avail : "", 116*7754SJeff.Bonwick@Sun.COM rops, wops, rbytes, wbytes, rerr, werr, cerr); 117*7754SJeff.Bonwick@Sun.COM } 118789Sahrens 119*7754SJeff.Bonwick@Sun.COM if (nvlist_lookup_nvlist_array(nv, ctype, &child, &children) != 0) 120789Sahrens return; 121789Sahrens 122789Sahrens for (c = 0; c < children; c++) { 123789Sahrens nvlist_t *cnv = child[c]; 1242082Seschrock char *cname, *tname; 1252082Seschrock uint64_t np; 126789Sahrens if (nvlist_lookup_string(cnv, ZPOOL_CONFIG_PATH, &cname) && 127789Sahrens nvlist_lookup_string(cnv, ZPOOL_CONFIG_TYPE, &cname)) 128789Sahrens cname = "<unknown>"; 1292082Seschrock tname = calloc(1, strlen(cname) + 2); 1302082Seschrock (void) strcpy(tname, cname); 1312082Seschrock if (nvlist_lookup_uint64(cnv, ZPOOL_CONFIG_NPARITY, &np) == 0) 1322082Seschrock tname[strlen(tname)] = '0' + np; 133*7754SJeff.Bonwick@Sun.COM show_vdev_stats(tname, ctype, cnv, indent + 2); 1342082Seschrock free(tname); 135789Sahrens } 136789Sahrens } 137789Sahrens 138789Sahrens void 139789Sahrens show_pool_stats(spa_t *spa) 140789Sahrens { 1411635Sbonwick nvlist_t *config, *nvroot; 1421635Sbonwick char *name; 143789Sahrens 144*7754SJeff.Bonwick@Sun.COM VERIFY(spa_get_stats(spa_name(spa), &config, NULL, 0) == 0); 1451635Sbonwick 146789Sahrens VERIFY(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 147789Sahrens &nvroot) == 0); 1481635Sbonwick VERIFY(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME, 1491635Sbonwick &name) == 0); 150789Sahrens 151*7754SJeff.Bonwick@Sun.COM show_vdev_stats(name, ZPOOL_CONFIG_CHILDREN, nvroot, 0); 152*7754SJeff.Bonwick@Sun.COM show_vdev_stats(NULL, ZPOOL_CONFIG_L2CACHE, nvroot, 0); 153*7754SJeff.Bonwick@Sun.COM show_vdev_stats(NULL, ZPOOL_CONFIG_SPARES, nvroot, 0); 154*7754SJeff.Bonwick@Sun.COM 155*7754SJeff.Bonwick@Sun.COM nvlist_free(config); 156789Sahrens } 157