util.c revision ea8dc4b6d2251b437950c0056bc626b311c73c27
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/*
22 * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23 * Use is subject to license terms.
24 */
25
26#pragma ident	"%Z%%M%	%I%	%E% SMI"
27
28#include <assert.h>
29#include <sys/zfs_context.h>
30#include <sys/avl.h>
31#include <string.h>
32#include <stdio.h>
33#include <stdlib.h>
34#include <sys/spa.h>
35#include <sys/fs/zfs.h>
36#include <sys/refcount.h>
37
38/*
39 * Routines needed by more than one client of libzpool.
40 */
41
42void
43nicenum(uint64_t num, char *buf)
44{
45	uint64_t n = num;
46	int index = 0;
47	char u;
48
49	while (n >= 1024) {
50		n = (n + (1024 / 2)) / 1024; /* Round up or down */
51		index++;
52	}
53
54	u = " KMGTPE"[index];
55
56	if (index == 0) {
57		(void) sprintf(buf, "%llu", (u_longlong_t)n);
58	} else if (n < 10 && (num & (num - 1)) != 0) {
59		(void) sprintf(buf, "%.2f%c",
60		    (double)num / (1ULL << 10 * index), u);
61	} else if (n < 100 && (num & (num - 1)) != 0) {
62		(void) sprintf(buf, "%.1f%c",
63		    (double)num / (1ULL << 10 * index), u);
64	} else {
65		(void) sprintf(buf, "%llu%c", (u_longlong_t)n, u);
66	}
67}
68
69static void
70show_vdev_stats(const char *desc, nvlist_t *nv, int indent)
71{
72	nvlist_t **child;
73	uint_t c, children;
74	vdev_stat_t *vs;
75	uint64_t sec;
76	char used[6], avail[6];
77	char rops[6], wops[6], rbytes[6], wbytes[6], rerr[6], werr[6], cerr[6];
78
79	if (indent == 0) {
80		(void) printf("                     "
81		    " capacity   operations   bandwidth  ---- errors ----\n");
82		(void) printf("description          "
83		    "used avail  read write  read write  read write cksum\n");
84	}
85
86	VERIFY(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_STATS,
87	    (uint64_t **)&vs, &c) == 0);
88
89	sec = MAX(1, vs->vs_timestamp / NANOSEC);
90
91	nicenum(vs->vs_alloc, used);
92	nicenum(vs->vs_space - vs->vs_alloc, avail);
93	nicenum(vs->vs_ops[ZIO_TYPE_READ] / sec, rops);
94	nicenum(vs->vs_ops[ZIO_TYPE_WRITE] / sec, wops);
95	nicenum(vs->vs_bytes[ZIO_TYPE_READ] / sec, rbytes);
96	nicenum(vs->vs_bytes[ZIO_TYPE_WRITE] / sec, wbytes);
97	nicenum(vs->vs_read_errors, rerr);
98	nicenum(vs->vs_write_errors, werr);
99	nicenum(vs->vs_checksum_errors, cerr);
100
101	(void) printf("%*s%*s%*s%*s %5s %5s %5s %5s %5s %5s %5s\n",
102	    indent, "",
103	    indent - 19 - (vs->vs_space ? 0 : 12), desc,
104	    vs->vs_space ? 6 : 0, vs->vs_space ? used : "",
105	    vs->vs_space ? 6 : 0, vs->vs_space ? avail : "",
106	    rops, wops, rbytes, wbytes, rerr, werr, cerr);
107
108	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
109	    &child, &children) != 0)
110		return;
111
112	for (c = 0; c < children; c++) {
113		nvlist_t *cnv = child[c];
114		char *cname;
115		if (nvlist_lookup_string(cnv, ZPOOL_CONFIG_PATH, &cname) &&
116		    nvlist_lookup_string(cnv, ZPOOL_CONFIG_TYPE, &cname))
117			cname = "<unknown>";
118		show_vdev_stats(cname, cnv, indent + 2);
119	}
120}
121
122void
123show_pool_stats(spa_t *spa)
124{
125	nvlist_t *config = NULL;
126	nvlist_t *nvroot = NULL;
127
128	spa_config_enter(spa, RW_READER, FTAG);
129	VERIFY(spa_get_stats(spa_name(spa), &config, NULL, 0) == 0);
130	VERIFY(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
131	    &nvroot) == 0);
132
133	show_vdev_stats(spa_name(spa), nvroot, 0);
134	spa_config_exit(spa, FTAG);
135}
136