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