Home | History | Annotate | Download | only in availdevs
      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 2007 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 "availdevs.h"
     29 #include <libzfs.h>
     30 #include <libzfs_jni_diskmgt.h>
     31 #include <libzfs_jni_ipool.h>
     32 #include <libxml/parser.h>
     33 
     34 /*
     35  * Function prototypes
     36  */
     37 
     38 static void handle_error(const char *, va_list);
     39 static void set_uint64_prop(xmlNodePtr, const char *, uint64_t);
     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 void
     57 set_uint64_prop(xmlNodePtr node, const char *attr, uint64_t value)
     58 {
     59 	static char tmp[64];
     60 	(void) snprintf(tmp, sizeof (tmp), "%llu", value);
     61 	xmlSetProp(node, (xmlChar *)attr, (xmlChar *)tmp);
     62 }
     63 
     64 static int
     65 add_disk_to_xml(dmgt_disk_t *dp, void *data)
     66 {
     67 	int i;
     68 	xmlNodePtr available = *((xmlNodePtr *)data);
     69 
     70 	xmlNodePtr disk = xmlNewChild(
     71 	    available, NULL, (xmlChar *)ELEMENT_DISK, NULL);
     72 	xmlSetProp(disk,
     73 	    (xmlChar *)ATTR_DISK_NAME, (xmlChar *)dp->name);
     74 
     75 	set_uint64_prop(disk, ATTR_DISK_SIZE, dp->size);
     76 
     77 	xmlSetProp(disk, (xmlChar *)ATTR_DISK_INUSE, (xmlChar *)
     78 	    (dp->in_use ? VAL_ATTR_TRUE : VAL_ATTR_FALSE));
     79 
     80 	if (dp->aliases != NULL) {
     81 		for (i = 0; dp->aliases[i] != NULL; i++) {
     82 			xmlNodePtr alias = xmlNewChild(
     83 			    disk, NULL, (xmlChar *)ELEMENT_ALIAS, NULL);
     84 			xmlSetProp(alias,
     85 			    (xmlChar *)ATTR_ALIAS_NAME,
     86 			    (xmlChar *)dp->aliases[i]);
     87 		}
     88 	}
     89 
     90 	if (dp->slices != NULL) {
     91 		for (i = 0; dp->slices[i] != NULL; i++) {
     92 			dmgt_slice_t *sp = dp->slices[i];
     93 			xmlNodePtr slice = xmlNewChild(
     94 			    disk, NULL, (xmlChar *)ELEMENT_SLICE, NULL);
     95 			xmlSetProp(slice,
     96 			    (xmlChar *)ATTR_SLICE_NAME, (xmlChar *)sp->name);
     97 
     98 			set_uint64_prop(slice, ATTR_SLICE_SIZE, sp->size);
     99 			set_uint64_prop(slice, ATTR_SLICE_START, sp->start);
    100 
    101 			if (sp->used_name != NULL) {
    102 				xmlSetProp(slice,
    103 				    (xmlChar *)ATTR_SLICE_USED_NAME,
    104 				    (xmlChar *)sp->used_name);
    105 			}
    106 
    107 			if (sp->used_by != NULL) {
    108 				xmlSetProp(slice, (xmlChar *)ATTR_SLICE_USED_BY,
    109 				    (xmlChar *)sp->used_by);
    110 			}
    111 		}
    112 	}
    113 
    114 	return (0);
    115 }
    116 
    117 static int
    118 add_pool_to_xml(nvlist_t *config, void *data)
    119 {
    120 	char *c;
    121 	char *name;
    122 	uint64_t guid;
    123 	uint64_t version;
    124 	uint64_t state;
    125 	nvlist_t *devices;
    126 	uint_t n;
    127 	vdev_stat_t *vs;
    128 	xmlNodePtr pool;
    129 	xmlNodePtr importable = *((xmlNodePtr *)data);
    130 
    131 	if (nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME, &name) ||
    132 	    nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, &guid) ||
    133 	    nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION, &version) ||
    134 	    nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE, &state) ||
    135 	    nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, &devices) ||
    136 	    nvlist_lookup_uint64_array(
    137 	    devices, ZPOOL_CONFIG_STATS, (uint64_t **)&vs, &n)) {
    138 		return (-1);
    139 	}
    140 
    141 	pool = xmlNewChild(importable, NULL, (xmlChar *)ELEMENT_POOL, NULL);
    142 	xmlSetProp(pool, (xmlChar *)ATTR_POOL_NAME, (xmlChar *)name);
    143 
    144 	set_uint64_prop(pool, ATTR_POOL_ID, guid);
    145 	set_uint64_prop(pool, ATTR_POOL_VERSION, version);
    146 	set_uint64_prop(pool, ATTR_POOL_USED, vs->vs_alloc);
    147 	set_uint64_prop(pool, ATTR_POOL_SIZE, vs->vs_space);
    148 	set_uint64_prop(pool, ATTR_POOL_REPLACEMENT_SIZE, vs->vs_rsize);
    149 	set_uint64_prop(pool, ATTR_POOL_READ_BYTES,
    150 	    vs->vs_bytes[ZIO_TYPE_READ]);
    151 	set_uint64_prop(pool, ATTR_POOL_WRITE_BYTES,
    152 	    vs->vs_bytes[ZIO_TYPE_WRITE]);
    153 	set_uint64_prop(pool, ATTR_POOL_READ_OPERATIONS,
    154 	    vs->vs_ops[ZIO_TYPE_READ]);
    155 	set_uint64_prop(pool, ATTR_POOL_WRITE_OPERATIONS,
    156 	    vs->vs_ops[ZIO_TYPE_WRITE]);
    157 	set_uint64_prop(pool, ATTR_POOL_READ_ERRORS, vs->vs_read_errors);
    158 	set_uint64_prop(pool, ATTR_POOL_WRITE_ERRORS, vs->vs_write_errors);
    159 	set_uint64_prop(pool, ATTR_POOL_CHECKSUM_ERRORS,
    160 	    vs->vs_checksum_errors);
    161 
    162 	xmlSetProp(pool, (xmlChar *)ATTR_DEVICE_STATE,
    163 	    (xmlChar *)zjni_vdev_state_to_str(vs->vs_state));
    164 
    165 	xmlSetProp(pool, (xmlChar *)ATTR_DEVICE_STATUS,
    166 	    (xmlChar *)zjni_vdev_aux_to_str(vs->vs_aux));
    167 
    168 	xmlSetProp(pool, (xmlChar *)ATTR_POOL_STATE,
    169 	    (xmlChar *)zjni_pool_state_to_str(state));
    170 
    171 	xmlSetProp(pool, (xmlChar *)ATTR_POOL_STATUS, (xmlChar *)
    172 	    zjni_pool_status_to_str(zpool_import_status(config, &c)));
    173 
    174 	return (0);
    175 }
    176 
    177 static xmlDocPtr
    178 create_doc(void)
    179 {
    180 	/* Create the XML document */
    181 	xmlDocPtr doc = xmlNewDoc((xmlChar *)"1.0");
    182 
    183 	/* Create the root node */
    184 	xmlNodePtr root = xmlNewDocNode(
    185 	    doc, NULL, (xmlChar *)ELEMENT_ROOT, NULL);
    186 	xmlAddChild((xmlNodePtr) doc, (xmlNodePtr)root);
    187 
    188 	return (doc);
    189 }
    190 
    191 /*
    192  * Main entry to availdisks.
    193  *
    194  * @return      0 on successful exit, non-zero otherwise
    195  */
    196 int
    197 main(int argc, char **argv)
    198 {
    199 	int error = 0;
    200 	int get_pools = 0;
    201 	int get_devices = 0;
    202 
    203 	/* Examine first arg */
    204 	int c = getopt(argc, argv, CLI_OPTSTRING);
    205 	switch (c) {
    206 		case CLI_ARG_ALL:
    207 			get_devices = 1;
    208 			get_pools = 1;
    209 			break;
    210 
    211 		case CLI_ARG_DEVICES:
    212 			get_devices = 1;
    213 			break;
    214 
    215 		case CLI_ARG_POOLS:
    216 			get_pools = 1;
    217 			break;
    218 
    219 		default:
    220 			return (1);
    221 			break;
    222 	}
    223 
    224 	argc -= optind;
    225 	argv += optind;
    226 
    227 	if (get_pools || get_devices) {
    228 		xmlDocPtr doc = create_doc();
    229 		xmlNodePtr root = xmlDocGetRootElement(doc);
    230 
    231 		if (get_devices) {
    232 			/* Create the available node */
    233 			xmlNodePtr available = xmlNewChild(root, NULL,
    234 			    (xmlChar *)ELEMENT_AVAILABLE, NULL);
    235 
    236 			/* libzfs_jni_diskmgt.o error handler */
    237 			dmgt_set_error_handler(handle_error);
    238 
    239 			error = dmgt_avail_disk_iter(
    240 			    add_disk_to_xml, &available);
    241 		}
    242 
    243 		if (get_pools && !error) {
    244 			/* Create the importable node */
    245 			xmlNodePtr importable = xmlNewChild(root, NULL,
    246 			    (xmlChar *)ELEMENT_IMPORTABLE, NULL);
    247 
    248 			error = zjni_ipool_iter(
    249 			    argc, argv, add_pool_to_xml, &importable);
    250 		}
    251 
    252 		if (!error) {
    253 			/* Print out XML */
    254 			xmlDocFormatDump(stdout, doc, 1);
    255 		}
    256 
    257 		xmlFreeDoc(doc);
    258 	}
    259 
    260 	return (error != 0);
    261 }
    262