155714Skris/*
255714Skris * CDDL HEADER START
355714Skris *
455714Skris * The contents of this file are subject to the terms of the
555714Skris * Common Development and Distribution License (the "License").
655714Skris * You may not use this file except in compliance with the License.
755714Skris *
8280304Sjkim * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
955714Skris * or http://www.opensolaris.org/os/licensing.
1055714Skris * See the License for the specific language governing permissions
1155714Skris * and limitations under the License.
1255714Skris *
1355714Skris * When distributing Covered Code, include this CDDL HEADER in each
1455714Skris * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15280304Sjkim * If applicable, add the following below this CDDL HEADER, with the
1655714Skris * fields enclosed by brackets "[]" replaced with your own identifying
1755714Skris * information: Portions Copyright [yyyy] [name of copyright owner]
1855714Skris *
1955714Skris * CDDL HEADER END
2055714Skris */
2155714Skris/*
22280304Sjkim * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
2355714Skris */
2455714Skris
2555714Skris#include <assert.h>
2655714Skris#include <sys/zfs_context.h>
2755714Skris#include <sys/avl.h>
2855714Skris#include <string.h>
2955714Skris#include <stdio.h>
3055714Skris#include <stdlib.h>
3155714Skris#include <sys/spa.h>
3255714Skris#include <sys/fs/zfs.h>
3355714Skris#include <sys/refcount.h>
3455714Skris
3555714Skris/*
3655714Skris * Routines needed by more than one client of libzpool.
37280304Sjkim */
3855714Skris
3955714Skrisvoid
40280304Sjkimnicenum(uint64_t num, char *buf)
4155714Skris{
4255714Skris	uint64_t n = num;
4355714Skris	int index = 0;
4455714Skris	char u;
4555714Skris
4655714Skris	while (n >= 1024) {
4755714Skris		n = (n + (1024 / 2)) / 1024; /* Round up or down */
4855714Skris		index++;
4955714Skris	}
5055714Skris
5155714Skris	u = " KMGTPE"[index];
52280304Sjkim
5355714Skris	if (index == 0) {
5455714Skris		(void) sprintf(buf, "%llu", (u_longlong_t)n);
5555714Skris	} else if (n < 10 && (num & (num - 1)) != 0) {
5655714Skris		(void) sprintf(buf, "%.2f%c",
5755714Skris		    (double)num / (1ULL << 10 * index), u);
5859191Skris	} else if (n < 100 && (num & (num - 1)) != 0) {
59100928Snectar		(void) sprintf(buf, "%.1f%c",
6059191Skris		    (double)num / (1ULL << 10 * index), u);
6159191Skris	} else {
6259191Skris		(void) sprintf(buf, "%llu%c", (u_longlong_t)n, u);
6359191Skris	}
6459191Skris}
6559191Skris
66280304Sjkimstatic void
6759191Skrisshow_vdev_stats(const char *desc, const char *ctype, nvlist_t *nv, int indent)
6859191Skris{
6959191Skris	vdev_stat_t *vs;
7059191Skris	vdev_stat_t v0 = { 0 };
7159191Skris	uint64_t sec;
7259191Skris	uint64_t is_log = 0;
7359191Skris	nvlist_t **child;
7459191Skris	uint_t c, children;
7559191Skris	char used[6], avail[6];
7659191Skris	char rops[6], wops[6], rbytes[6], wbytes[6], rerr[6], werr[6], cerr[6];
7759191Skris	char *prefix = "";
7859191Skris
7959191Skris	if (indent == 0 && desc != NULL) {
8059191Skris		(void) printf("                           "
8159191Skris		    " capacity   operations   bandwidth  ---- errors ----\n");
8259191Skris		(void) printf("description                "
8359191Skris		    "used avail  read write  read write  read write cksum\n");
8459191Skris	}
8559191Skris
8659191Skris	if (desc != NULL) {
8759191Skris		(void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_IS_LOG, &is_log);
8859191Skris
8959191Skris		if (is_log)
9059191Skris			prefix = "log ";
9159191Skris
9259191Skris		if (nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
9359191Skris		    (uint64_t **)&vs, &c) != 0)
9459191Skris			vs = &v0;
9559191Skris
9659191Skris		sec = MAX(1, vs->vs_timestamp / NANOSEC);
9759191Skris
9859191Skris		nicenum(vs->vs_alloc, used);
9959191Skris		nicenum(vs->vs_space - vs->vs_alloc, avail);
10059191Skris		nicenum(vs->vs_ops[ZIO_TYPE_READ] / sec, rops);
10159191Skris		nicenum(vs->vs_ops[ZIO_TYPE_WRITE] / sec, wops);
10259191Skris		nicenum(vs->vs_bytes[ZIO_TYPE_READ] / sec, rbytes);
10359191Skris		nicenum(vs->vs_bytes[ZIO_TYPE_WRITE] / sec, wbytes);
10459191Skris		nicenum(vs->vs_read_errors, rerr);
10559191Skris		nicenum(vs->vs_write_errors, werr);
10659191Skris		nicenum(vs->vs_checksum_errors, cerr);
10759191Skris
10859191Skris		(void) printf("%*s%s%*s%*s%*s %5s %5s %5s %5s %5s %5s %5s\n",
10959191Skris		    indent, "",
11059191Skris		    prefix,
11155714Skris		    indent + strlen(prefix) - 25 - (vs->vs_space ? 0 : 12),
11255714Skris		    desc,
113267258Sjkim		    vs->vs_space ? 6 : 0, vs->vs_space ? used : "",
11455714Skris		    vs->vs_space ? 6 : 0, vs->vs_space ? avail : "",
11555714Skris		    rops, wops, rbytes, wbytes, rerr, werr, cerr);
116109998Smarkm	}
11755714Skris
11855714Skris	if (nvlist_lookup_nvlist_array(nv, ctype, &child, &children) != 0)
119238405Sjkim		return;
12055714Skris
12155714Skris	for (c = 0; c < children; c++) {
122280304Sjkim		nvlist_t *cnv = child[c];
12355714Skris		char *cname, *tname;
12459191Skris		uint64_t np;
125160814Ssimon		if (nvlist_lookup_string(cnv, ZPOOL_CONFIG_PATH, &cname) &&
126280304Sjkim		    nvlist_lookup_string(cnv, ZPOOL_CONFIG_TYPE, &cname))
127280304Sjkim			cname = "<unknown>";
128280304Sjkim		tname = calloc(1, strlen(cname) + 2);
129280304Sjkim		(void) strcpy(tname, cname);
130280304Sjkim		if (nvlist_lookup_uint64(cnv, ZPOOL_CONFIG_NPARITY, &np) == 0)
131280304Sjkim			tname[strlen(tname)] = '0' + np;
132280304Sjkim		show_vdev_stats(tname, ctype, cnv, indent + 2);
133280304Sjkim		free(tname);
134280304Sjkim	}
135280304Sjkim}
136280304Sjkim
137280304Sjkimvoid
13855714Skrisshow_pool_stats(spa_t *spa)
139280304Sjkim{
140280304Sjkim	nvlist_t *config, *nvroot;
141238405Sjkim	char *name;
142280304Sjkim
143280304Sjkim	VERIFY(spa_get_stats(spa_name(spa), &config, NULL, 0) == 0);
144280304Sjkim
145280304Sjkim	VERIFY(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
146238405Sjkim	    &nvroot) == 0);
147280304Sjkim	VERIFY(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
148238405Sjkim	    &name) == 0);
149280304Sjkim
150280304Sjkim	show_vdev_stats(name, ZPOOL_CONFIG_CHILDREN, nvroot, 0);
151238405Sjkim	show_vdev_stats(NULL, ZPOOL_CONFIG_L2CACHE, nvroot, 0);
152238405Sjkim	show_vdev_stats(NULL, ZPOOL_CONFIG_SPARES, nvroot, 0);
153280304Sjkim
154280304Sjkim	nvlist_free(config);
155280304Sjkim}
156280304Sjkim