xref: /illumos-gate/usr/src/cmd/availdevs/availdevs.c (revision fbfd10ff571cfd0139aa5127460f1b8a53dac971)
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include "availdevs.h"
30 #include <libzfs.h>
31 #include <libzfs_jni_diskmgt.h>
32 #include <libzfs_jni_ipool.h>
33 #include <libxml/parser.h>
34 
35 /*
36  * Function prototypes
37  */
38 
39 static void handle_error(const char *, va_list);
40 static int add_disk_to_xml(dmgt_disk_t *, void *);
41 static int add_pool_to_xml(nvlist_t *, void *);
42 static xmlDocPtr create_doc();
43 int main();
44 
45 /*
46  * Static functions
47  */
48 
49 static void
50 handle_error(const char *fmt, va_list ap)
51 {
52 	(void) vfprintf(stderr, fmt, ap);
53 	(void) fprintf(stderr, "\n");
54 }
55 
56 static int
57 add_disk_to_xml(dmgt_disk_t *dp, void *data)
58 {
59 	int i;
60 	char tmp[64];
61 	xmlNodePtr available = *((xmlNodePtr *)data);
62 
63 	xmlNodePtr disk = xmlNewChild(
64 	    available, NULL, (xmlChar *)ELEMENT_DISK, NULL);
65 	xmlSetProp(disk,
66 	    (xmlChar *)ATTR_DISK_NAME, (xmlChar *)dp->name);
67 	(void) snprintf(tmp, sizeof (tmp), "%llu", dp->size);
68 	xmlSetProp(disk, (xmlChar *)ATTR_DISK_SIZE, (xmlChar *)tmp);
69 
70 	xmlSetProp(disk, (xmlChar *)ATTR_DISK_INUSE, (xmlChar *)
71 	    (dp->in_use ? VAL_ATTR_TRUE : VAL_ATTR_FALSE));
72 
73 	if (dp->aliases != NULL) {
74 		for (i = 0; dp->aliases[i] != NULL; i++) {
75 			xmlNodePtr alias = xmlNewChild(
76 			    disk, NULL, (xmlChar *)ELEMENT_ALIAS, NULL);
77 			xmlSetProp(alias,
78 			    (xmlChar *)ATTR_ALIAS_NAME,
79 			    (xmlChar *)dp->aliases[i]);
80 		}
81 	}
82 
83 	if (dp->slices != NULL) {
84 		for (i = 0; dp->slices[i] != NULL; i++) {
85 			dmgt_slice_t *sp = dp->slices[i];
86 			xmlNodePtr slice = xmlNewChild(
87 			    disk, NULL, (xmlChar *)ELEMENT_SLICE, NULL);
88 			xmlSetProp(slice,
89 			    (xmlChar *)ATTR_SLICE_NAME, (xmlChar *)sp->name);
90 
91 			(void) snprintf(tmp, sizeof (tmp), "%llu", sp->size);
92 			xmlSetProp(slice, (xmlChar *)ATTR_SLICE_SIZE,
93 			    (xmlChar *)tmp);
94 
95 			(void) snprintf(tmp, sizeof (tmp), "%llu", sp->start);
96 			xmlSetProp(slice, (xmlChar *)ATTR_SLICE_START,
97 			    (xmlChar *)tmp);
98 
99 			if (sp->used_name != NULL) {
100 				xmlSetProp(slice,
101 				    (xmlChar *)ATTR_SLICE_USED_NAME,
102 				    (xmlChar *)sp->used_name);
103 			}
104 
105 			if (sp->used_by != NULL) {
106 				xmlSetProp(slice, (xmlChar *)ATTR_SLICE_USED_BY,
107 				    (xmlChar *)sp->used_by);
108 			}
109 		}
110 	}
111 
112 	return (0);
113 }
114 
115 static int
116 add_pool_to_xml(nvlist_t *config, void *data)
117 {
118 	char *c;
119 	char *name;
120 	uint64_t guid;
121 	uint64_t state;
122 	nvlist_t *devices;
123 	uint_t n;
124 	vdev_stat_t *vs;
125 	char tmp[64];
126 	xmlNodePtr pool;
127 	xmlNodePtr importable = *((xmlNodePtr *)data);
128 
129 	if (nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME, &name) ||
130 	    nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, &guid) ||
131 	    nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE, &state) ||
132 	    nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, &devices) ||
133 	    nvlist_lookup_uint64_array(
134 		devices, ZPOOL_CONFIG_STATS, (uint64_t **)&vs, &n)) {
135 		return (-1);
136 	}
137 
138 	pool = xmlNewChild(importable, NULL, (xmlChar *)ELEMENT_POOL, NULL);
139 	xmlSetProp(pool, (xmlChar *)ATTR_POOL_NAME, (xmlChar *)name);
140 
141 	(void) snprintf(tmp, sizeof (tmp), "%llu", guid);
142 	xmlSetProp(pool, (xmlChar *)ATTR_POOL_ID, (xmlChar *)tmp);
143 
144 	(void) snprintf(tmp, sizeof (tmp), "%llu", vs->vs_alloc);
145 	xmlSetProp(pool, (xmlChar *)ATTR_POOL_USED, (xmlChar *)tmp);
146 
147 	(void) snprintf(tmp, sizeof (tmp), "%llu", vs->vs_space);
148 	xmlSetProp(pool, (xmlChar *)ATTR_POOL_SIZE, (xmlChar *)tmp);
149 
150 	(void) snprintf(tmp, sizeof (tmp), "%llu", vs->vs_bytes[ZIO_TYPE_READ]);
151 	xmlSetProp(pool, (xmlChar *)ATTR_POOL_READ_BYTES, (xmlChar *)tmp);
152 
153 	(void) snprintf(tmp, sizeof (tmp), "%llu",
154 	    vs->vs_bytes[ZIO_TYPE_WRITE]);
155 	xmlSetProp(pool, (xmlChar *)ATTR_POOL_WRITE_BYTES, (xmlChar *)tmp);
156 
157 	(void) snprintf(tmp, sizeof (tmp), "%llu", vs->vs_ops[ZIO_TYPE_READ]);
158 	xmlSetProp(pool, (xmlChar *)ATTR_POOL_READ_OPERATIONS, (xmlChar *)tmp);
159 
160 	(void) snprintf(tmp, sizeof (tmp), "%llu", vs->vs_ops[ZIO_TYPE_WRITE]);
161 	xmlSetProp(pool, (xmlChar *)ATTR_POOL_WRITE_OPERATIONS, (xmlChar *)tmp);
162 
163 	(void) snprintf(tmp, sizeof (tmp), "%llu", vs->vs_read_errors);
164 	xmlSetProp(pool, (xmlChar *)ATTR_POOL_READ_ERRORS, (xmlChar *)tmp);
165 
166 	(void) snprintf(tmp, sizeof (tmp), "%llu", vs->vs_write_errors);
167 	xmlSetProp(pool, (xmlChar *)ATTR_POOL_WRITE_ERRORS, (xmlChar *)tmp);
168 
169 	(void) snprintf(tmp, sizeof (tmp), "%llu", vs->vs_checksum_errors);
170 	xmlSetProp(pool, (xmlChar *)ATTR_POOL_CHECKSUM_ERRORS, (xmlChar *)tmp);
171 
172 	xmlSetProp(pool, (xmlChar *)ATTR_DEVICE_STATE,
173 	    (xmlChar *)zjni_vdev_state_to_str(vs->vs_state));
174 
175 	xmlSetProp(pool, (xmlChar *)ATTR_DEVICE_STATUS,
176 	    (xmlChar *)zjni_vdev_aux_to_str(vs->vs_aux));
177 
178 	xmlSetProp(pool, (xmlChar *)ATTR_POOL_STATE,
179 	    (xmlChar *)zjni_pool_state_to_str(state));
180 
181 	xmlSetProp(pool, (xmlChar *)ATTR_POOL_STATUS, (xmlChar *)
182 	    zjni_pool_status_to_str(zpool_import_status(config, &c)));
183 
184 	return (0);
185 }
186 
187 static xmlDocPtr
188 create_doc(void)
189 {
190 	/* Create the XML document */
191 	xmlDocPtr doc = xmlNewDoc((xmlChar *)"1.0");
192 
193 	/* Create the root node */
194 	xmlNodePtr root = xmlNewDocNode(
195 	    doc, NULL, (xmlChar *)ELEMENT_ROOT, NULL);
196 	xmlAddChild((xmlNodePtr) doc, (xmlNodePtr)root);
197 
198 	return (doc);
199 }
200 
201 /*
202  * Main entry to availdisks.
203  *
204  * @return      0 on successful exit, non-zero otherwise
205  */
206 int
207 main(int argc, char **argv)
208 {
209 	int error = 0;
210 	int get_pools = 0;
211 	int get_devices = 0;
212 
213 	/* Examine first arg */
214 	int c = getopt(argc, argv, CLI_OPTSTRING);
215 	switch (c) {
216 		case CLI_ARG_ALL:
217 			get_devices = 1;
218 			get_pools = 1;
219 			break;
220 
221 		case CLI_ARG_DEVICES:
222 			get_devices = 1;
223 			break;
224 
225 		case CLI_ARG_POOLS:
226 			get_pools = 1;
227 			break;
228 
229 		default:
230 			return (1);
231 			break;
232 	}
233 
234 	argc -= optind;
235 	argv += optind;
236 
237 	if (get_pools || get_devices) {
238 		xmlDocPtr doc = create_doc();
239 		xmlNodePtr root = xmlDocGetRootElement(doc);
240 
241 		if (get_devices) {
242 			/* Create the available node */
243 			xmlNodePtr available = xmlNewChild(root, NULL,
244 			    (xmlChar *)ELEMENT_AVAILABLE, NULL);
245 
246 			/* libzfs_jni_diskmgt.o error handler */
247 			dmgt_set_error_handler(handle_error);
248 
249 			error = dmgt_avail_disk_iter(
250 			    add_disk_to_xml, &available);
251 		}
252 
253 		if (get_pools && !error) {
254 			/* Create the importable node */
255 			xmlNodePtr importable = xmlNewChild(root, NULL,
256 			    (xmlChar *)ELEMENT_IMPORTABLE, NULL);
257 
258 			error = zjni_ipool_iter(
259 			    argc, argv, add_pool_to_xml, &importable);
260 		}
261 
262 		if (!error) {
263 			/* Print out XML */
264 			xmlDocFormatDump(stdout, doc, 1);
265 		}
266 
267 		xmlFreeDoc(doc);
268 	}
269 
270 	return (error != 0);
271 }
272