Home | History | Annotate | Download | only in common
      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 /*
     23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 #include "libzfs_jni_util.h"
     28 #include "libzfs_jni_pool.h"
     29 #include <strings.h>
     30 
     31 /*
     32  * Types
     33  */
     34 
     35 typedef struct ImportablePoolBean {
     36 	zjni_Object_t super;
     37 	PoolStatsBean_t interface_PoolStats;
     38 
     39 	jmethodID method_setName;
     40 	jmethodID method_setId;
     41 } ImportablePoolBean_t;
     42 
     43 typedef struct VirtualDeviceBean {
     44 	zjni_Object_t super;
     45 	DeviceStatsBean_t interface_DeviceStats;
     46 
     47 	jmethodID method_setPoolName;
     48 	jmethodID method_setParentIndex;
     49 	jmethodID method_setIndex;
     50 } VirtualDeviceBean_t;
     51 
     52 typedef struct LeafVirtualDeviceBean {
     53 	VirtualDeviceBean_t super;
     54 
     55 	jmethodID method_setName;
     56 } LeafVirtualDeviceBean_t;
     57 
     58 typedef struct DiskVirtualDeviceBean {
     59 	LeafVirtualDeviceBean_t super;
     60 } DiskVirtualDeviceBean_t;
     61 
     62 typedef struct SliceVirtualDeviceBean {
     63 	LeafVirtualDeviceBean_t super;
     64 } SliceVirtualDeviceBean_t;
     65 
     66 typedef struct FileVirtualDeviceBean {
     67 	LeafVirtualDeviceBean_t super;
     68 } FileVirtualDeviceBean_t;
     69 
     70 typedef struct RAIDVirtualDeviceBean {
     71 	VirtualDeviceBean_t super;
     72 
     73 	jmethodID method_setParity;
     74 } RAIDVirtualDeviceBean_t;
     75 
     76 typedef struct MirrorVirtualDeviceBean {
     77 	VirtualDeviceBean_t super;
     78 } MirrorVirtualDeviceBean_t;
     79 
     80 /*
     81  * Data
     82  */
     83 
     84 /* vdev_state_t to DeviceStats$DeviceState map */
     85 static zjni_field_mapping_t vdev_state_map[] = {
     86 	{ VDEV_STATE_CANT_OPEN, "VDEV_STATE_CANT_OPEN" },
     87 	{ VDEV_STATE_CLOSED, "VDEV_STATE_CLOSED" },
     88 	{ VDEV_STATE_DEGRADED, "VDEV_STATE_DEGRADED" },
     89 	{ VDEV_STATE_HEALTHY, "VDEV_STATE_HEALTHY" },
     90 	{ VDEV_STATE_OFFLINE, "VDEV_STATE_OFFLINE" },
     91 	{ VDEV_STATE_UNKNOWN, "VDEV_STATE_UNKNOWN" },
     92 	{ -1, NULL },
     93 };
     94 
     95 /* vdev_aux_t to DeviceStats$DeviceStatus map */
     96 static zjni_field_mapping_t vdev_aux_map[] = {
     97 	{ VDEV_AUX_NONE, "VDEV_AUX_NONE" },
     98 	{ VDEV_AUX_OPEN_FAILED, "VDEV_AUX_OPEN_FAILED" },
     99 	{ VDEV_AUX_CORRUPT_DATA, "VDEV_AUX_CORRUPT_DATA" },
    100 	{ VDEV_AUX_NO_REPLICAS, "VDEV_AUX_NO_REPLICAS" },
    101 	{ VDEV_AUX_BAD_GUID_SUM, "VDEV_AUX_BAD_GUID_SUM" },
    102 	{ VDEV_AUX_TOO_SMALL, "VDEV_AUX_TOO_SMALL" },
    103 	{ VDEV_AUX_BAD_LABEL, "VDEV_AUX_BAD_LABEL" },
    104 	{ -1, NULL },
    105 };
    106 
    107 /* zpool_state_t to PoolStats$PoolState map */
    108 static zjni_field_mapping_t pool_state_map[] = {
    109 	{ POOL_STATE_ACTIVE, "POOL_STATE_ACTIVE" },
    110 	{ POOL_STATE_EXPORTED, "POOL_STATE_EXPORTED" },
    111 	{ POOL_STATE_DESTROYED, "POOL_STATE_DESTROYED" },
    112 	{ POOL_STATE_SPARE, "POOL_STATE_SPARE" },
    113 	{ POOL_STATE_UNINITIALIZED, "POOL_STATE_UNINITIALIZED" },
    114 	{ POOL_STATE_UNAVAIL, "POOL_STATE_UNAVAIL" },
    115 	{ POOL_STATE_POTENTIALLY_ACTIVE, "POOL_STATE_POTENTIALLY_ACTIVE" },
    116 	{ -1, NULL },
    117 };
    118 
    119 /* zpool_status_t to PoolStats$PoolStatus map */
    120 static zjni_field_mapping_t zpool_status_map[] = {
    121 	{ ZPOOL_STATUS_CORRUPT_CACHE, "ZPOOL_STATUS_CORRUPT_CACHE" },
    122 	{ ZPOOL_STATUS_MISSING_DEV_R, "ZPOOL_STATUS_MISSING_DEV_R" },
    123 	{ ZPOOL_STATUS_MISSING_DEV_NR, "ZPOOL_STATUS_MISSING_DEV_NR" },
    124 	{ ZPOOL_STATUS_CORRUPT_LABEL_R, "ZPOOL_STATUS_CORRUPT_LABEL_R" },
    125 	{ ZPOOL_STATUS_CORRUPT_LABEL_NR, "ZPOOL_STATUS_CORRUPT_LABEL_NR" },
    126 	{ ZPOOL_STATUS_BAD_GUID_SUM, "ZPOOL_STATUS_BAD_GUID_SUM" },
    127 	{ ZPOOL_STATUS_CORRUPT_POOL, "ZPOOL_STATUS_CORRUPT_POOL" },
    128 	{ ZPOOL_STATUS_CORRUPT_DATA, "ZPOOL_STATUS_CORRUPT_DATA" },
    129 	{ ZPOOL_STATUS_FAILING_DEV, "ZPOOL_STATUS_FAILING_DEV" },
    130 	{ ZPOOL_STATUS_VERSION_NEWER, "ZPOOL_STATUS_VERSION_NEWER" },
    131 	{ ZPOOL_STATUS_HOSTID_MISMATCH, "ZPOOL_STATUS_HOSTID_MISMATCH" },
    132 	{ ZPOOL_STATUS_FAULTED_DEV_R, "ZPOOL_STATUS_FAULTED_DEV_R" },
    133 	{ ZPOOL_STATUS_FAULTED_DEV_NR, "ZPOOL_STATUS_FAULTED_DEV_NR" },
    134 	{ ZPOOL_STATUS_BAD_LOG, "ZPOOL_STATUS_BAD_LOG" },
    135 	{ ZPOOL_STATUS_VERSION_OLDER, "ZPOOL_STATUS_VERSION_OLDER" },
    136 	{ ZPOOL_STATUS_RESILVERING, "ZPOOL_STATUS_RESILVERING" },
    137 	{ ZPOOL_STATUS_OFFLINE_DEV, "ZPOOL_STATUS_OFFLINE_DEV" },
    138 	{ ZPOOL_STATUS_REMOVED_DEV, "ZPOOL_STATUS_REMOVED_DEV" },
    139 	{ ZPOOL_STATUS_OK, "ZPOOL_STATUS_OK" },
    140 	{ -1, NULL }
    141 };
    142 
    143 /*
    144  * Function prototypes
    145  */
    146 
    147 static void new_ImportablePoolBean(JNIEnv *, ImportablePoolBean_t *);
    148 static void new_VirtualDevice(JNIEnv *, VirtualDeviceBean_t *);
    149 static void new_LeafVirtualDevice(JNIEnv *, LeafVirtualDeviceBean_t *);
    150 static void new_DiskVirtualDeviceBean(JNIEnv *, DiskVirtualDeviceBean_t *);
    151 static void new_SliceVirtualDeviceBean(JNIEnv *, SliceVirtualDeviceBean_t *);
    152 static void new_FileVirtualDeviceBean(JNIEnv *, FileVirtualDeviceBean_t *);
    153 static void new_RAIDVirtualDeviceBean(JNIEnv *, RAIDVirtualDeviceBean_t *);
    154 static void new_MirrorVirtualDeviceBean(JNIEnv *, MirrorVirtualDeviceBean_t *);
    155 static int populate_ImportablePoolBean(
    156     JNIEnv *, ImportablePoolBean_t *, nvlist_t *);
    157 static int populate_VirtualDeviceBean(JNIEnv *, zpool_handle_t *,
    158     nvlist_t *, uint64_t *p_vdev_id, VirtualDeviceBean_t *);
    159 static int populate_LeafVirtualDeviceBean(JNIEnv *, zpool_handle_t *,
    160     nvlist_t *, uint64_t *p_vdev_id, LeafVirtualDeviceBean_t *);
    161 static int populate_DiskVirtualDeviceBean(JNIEnv *, zpool_handle_t *,
    162     nvlist_t *, uint64_t *p_vdev_id, DiskVirtualDeviceBean_t *);
    163 static int populate_SliceVirtualDeviceBean(JNIEnv *, zpool_handle_t *,
    164     nvlist_t *, uint64_t *p_vdev_id, SliceVirtualDeviceBean_t *);
    165 static int populate_FileVirtualDeviceBean(JNIEnv *, zpool_handle_t *,
    166     nvlist_t *, uint64_t *p_vdev_id, FileVirtualDeviceBean_t *);
    167 static int populate_RAIDVirtualDeviceBean(JNIEnv *, zpool_handle_t *,
    168     nvlist_t *, uint64_t *p_vdev_id, RAIDVirtualDeviceBean_t *);
    169 static int populate_MirrorVirtualDeviceBean(JNIEnv *, zpool_handle_t *,
    170     nvlist_t *, uint64_t *p_vdev_id, MirrorVirtualDeviceBean_t *);
    171 static jobject create_ImportablePoolBean(JNIEnv *, nvlist_t *);
    172 static jobject create_DiskVirtualDeviceBean(
    173     JNIEnv *, zpool_handle_t *, nvlist_t *, uint64_t *p_vdev_id);
    174 static jobject create_SliceVirtualDeviceBean(
    175     JNIEnv *, zpool_handle_t *, nvlist_t *, uint64_t *p_vdev_id);
    176 static jobject create_FileVirtualDeviceBean(
    177     JNIEnv *, zpool_handle_t *, nvlist_t *, uint64_t *p_vdev_id);
    178 static jobject create_RAIDVirtualDeviceBean(
    179     JNIEnv *, zpool_handle_t *, nvlist_t *, uint64_t *p_vdev_id);
    180 static jobject create_MirrorVirtualDeviceBean(
    181     JNIEnv *, zpool_handle_t *, nvlist_t *, uint64_t *p_vdev_id);
    182 static char *find_field(const zjni_field_mapping_t *, int);
    183 static jobject zjni_vdev_state_to_obj(JNIEnv *, vdev_state_t);
    184 static jobject zjni_vdev_aux_to_obj(JNIEnv *, vdev_aux_t);
    185 
    186 /*
    187  * Static functions
    188  */
    189 
    190 /* Create a ImportablePoolBean */
    191 static void
    192 new_ImportablePoolBean(JNIEnv *env, ImportablePoolBean_t *bean)
    193 {
    194 	zjni_Object_t *object = (zjni_Object_t *)bean;
    195 
    196 	if (object->object == NULL) {
    197 		object->class =
    198 		    (*env)->FindClass(env,
    199 		    ZFSJNI_PACKAGE_DATA "ImportablePoolBean");
    200 
    201 		object->constructor =
    202 		    (*env)->GetMethodID(env, object->class, "<init>", "()V");
    203 
    204 		object->object =
    205 		    (*env)->NewObject(env, object->class, object->constructor);
    206 	}
    207 
    208 	new_PoolStats(env, &(bean->interface_PoolStats), object);
    209 
    210 	bean->method_setName = (*env)->GetMethodID(
    211 	    env, object->class, "setName", "(Ljava/lang/String;)V");
    212 
    213 	bean->method_setId = (*env)->GetMethodID(
    214 	    env, object->class, "setId", "(J)V");
    215 }
    216 
    217 /* Create a VirtualDeviceBean */
    218 static void
    219 new_VirtualDevice(JNIEnv *env, VirtualDeviceBean_t *bean)
    220 {
    221 	zjni_Object_t *object = (zjni_Object_t *)bean;
    222 
    223 	if (object->object == NULL) {
    224 		object->class =
    225 		    (*env)->FindClass(env,
    226 		    ZFSJNI_PACKAGE_DATA "VirtualDeviceBean");
    227 
    228 		object->constructor =
    229 		    (*env)->GetMethodID(env, object->class, "<init>", "()V");
    230 
    231 		object->object =
    232 		    (*env)->NewObject(env, object->class, object->constructor);
    233 	}
    234 
    235 	new_DeviceStats(env, &(bean->interface_DeviceStats), object);
    236 
    237 	bean->method_setPoolName = (*env)->GetMethodID(
    238 	    env, object->class, "setPoolName", "(Ljava/lang/String;)V");
    239 
    240 	bean->method_setParentIndex = (*env)->GetMethodID(
    241 	    env, object->class, "setParentIndex", "(Ljava/lang/Long;)V");
    242 
    243 	bean->method_setIndex = (*env)->GetMethodID(
    244 	    env, object->class, "setIndex", "(J)V");
    245 }
    246 
    247 /* Create a LeafVirtualDeviceBean */
    248 static void
    249 new_LeafVirtualDevice(JNIEnv *env, LeafVirtualDeviceBean_t *bean)
    250 {
    251 	zjni_Object_t *object = (zjni_Object_t *)bean;
    252 
    253 	if (object->object == NULL) {
    254 		object->class =
    255 		    (*env)->FindClass(env,
    256 		    ZFSJNI_PACKAGE_DATA "LeafVirtualDeviceBean");
    257 
    258 		object->constructor =
    259 		    (*env)->GetMethodID(env, object->class, "<init>", "()V");
    260 
    261 		object->object =
    262 		    (*env)->NewObject(env, object->class, object->constructor);
    263 	}
    264 
    265 	new_VirtualDevice(env, (VirtualDeviceBean_t *)bean);
    266 
    267 	bean->method_setName = (*env)->GetMethodID(
    268 	    env, object->class, "setName", "(Ljava/lang/String;)V");
    269 }
    270 
    271 /* Create a DiskVirtualDeviceBean */
    272 static void
    273 new_DiskVirtualDeviceBean(JNIEnv *env, DiskVirtualDeviceBean_t *bean)
    274 {
    275 	zjni_Object_t *object = (zjni_Object_t *)bean;
    276 
    277 	if (object->object == NULL) {
    278 		object->class = (*env)->FindClass(
    279 		    env, ZFSJNI_PACKAGE_DATA "DiskVirtualDeviceBean");
    280 
    281 		object->constructor =
    282 		    (*env)->GetMethodID(env, object->class, "<init>", "()V");
    283 
    284 		object->object =
    285 		    (*env)->NewObject(env, object->class, object->constructor);
    286 	}
    287 
    288 	new_LeafVirtualDevice(env, (LeafVirtualDeviceBean_t *)bean);
    289 }
    290 
    291 /* Create a SliceVirtualDeviceBean */
    292 static void
    293 new_SliceVirtualDeviceBean(JNIEnv *env, SliceVirtualDeviceBean_t *bean)
    294 {
    295 	zjni_Object_t *object = (zjni_Object_t *)bean;
    296 
    297 	if (object->object == NULL) {
    298 		object->class = (*env)->FindClass(
    299 		    env, ZFSJNI_PACKAGE_DATA "SliceVirtualDeviceBean");
    300 
    301 		object->constructor =
    302 		    (*env)->GetMethodID(env, object->class, "<init>", "()V");
    303 
    304 		object->object =
    305 		    (*env)->NewObject(env, object->class, object->constructor);
    306 	}
    307 
    308 	new_LeafVirtualDevice(env, (LeafVirtualDeviceBean_t *)bean);
    309 }
    310 
    311 /* Create a FileVirtualDeviceBean */
    312 static void
    313 new_FileVirtualDeviceBean(JNIEnv *env, FileVirtualDeviceBean_t *bean)
    314 {
    315 	zjni_Object_t *object = (zjni_Object_t *)bean;
    316 
    317 	if (object->object == NULL) {
    318 		object->class = (*env)->FindClass(
    319 		    env, ZFSJNI_PACKAGE_DATA "FileVirtualDeviceBean");
    320 
    321 		object->constructor =
    322 		    (*env)->GetMethodID(env, object->class, "<init>", "()V");
    323 
    324 		object->object =
    325 		    (*env)->NewObject(env, object->class, object->constructor);
    326 	}
    327 
    328 	new_LeafVirtualDevice(env, (LeafVirtualDeviceBean_t *)bean);
    329 }
    330 
    331 /* Create a RAIDVirtualDeviceBean */
    332 static void
    333 new_RAIDVirtualDeviceBean(JNIEnv *env, RAIDVirtualDeviceBean_t *bean)
    334 {
    335 	zjni_Object_t *object = (zjni_Object_t *)bean;
    336 
    337 	if (object->object == NULL) {
    338 
    339 		object->class = (*env)->FindClass(
    340 		    env, ZFSJNI_PACKAGE_DATA "RAIDVirtualDeviceBean");
    341 
    342 		object->constructor =
    343 		    (*env)->GetMethodID(env, object->class, "<init>", "()V");
    344 
    345 		object->object =
    346 		    (*env)->NewObject(env, object->class, object->constructor);
    347 	}
    348 
    349 	new_VirtualDevice(env, (VirtualDeviceBean_t *)bean);
    350 
    351 	bean->method_setParity = (*env)->GetMethodID(
    352 	    env, object->class, "setParity", "(J)V");
    353 }
    354 
    355 /* Create a MirrorVirtualDeviceBean */
    356 static void
    357 new_MirrorVirtualDeviceBean(JNIEnv *env, MirrorVirtualDeviceBean_t *bean)
    358 {
    359 	zjni_Object_t *object = (zjni_Object_t *)bean;
    360 
    361 	if (object->object == NULL) {
    362 		object->class = (*env)->FindClass(
    363 		    env, ZFSJNI_PACKAGE_DATA "MirrorVirtualDeviceBean");
    364 
    365 		object->constructor =
    366 		    (*env)->GetMethodID(env, object->class, "<init>", "()V");
    367 
    368 		object->object =
    369 		    (*env)->NewObject(env, object->class, object->constructor);
    370 	}
    371 
    372 	new_VirtualDevice(env, (VirtualDeviceBean_t *)bean);
    373 }
    374 
    375 static int
    376 populate_ImportablePoolBean(JNIEnv *env, ImportablePoolBean_t *bean,
    377     nvlist_t *config)
    378 {
    379 	char *c;
    380 	char *name;
    381 	uint64_t guid;
    382 	uint64_t state;
    383 	uint64_t version;
    384 	nvlist_t *devices;
    385 
    386 	zjni_Object_t *object = (zjni_Object_t *)bean;
    387 	PoolStatsBean_t *pool_stats = &(bean->interface_PoolStats);
    388 	DeviceStatsBean_t *dev_stats = (DeviceStatsBean_t *)pool_stats;
    389 
    390 	if (nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME, &name) ||
    391 	    nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, &guid) ||
    392 	    nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE, &state) ||
    393 	    nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION, &version) ||
    394 	    nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, &devices) ||
    395 	    populate_DeviceStatsBean(env, devices, dev_stats, object)) {
    396 		return (-1);
    397 	}
    398 
    399 	(*env)->CallVoidMethod(env, object->object,
    400 	    bean->method_setName, (*env)->NewStringUTF(env, name));
    401 
    402 	(*env)->CallVoidMethod(env, object->object,
    403 	    bean->method_setId, (jlong)guid);
    404 
    405 	(*env)->CallVoidMethod(env, object->object,
    406 	    pool_stats->method_setPoolState,
    407 	    zjni_pool_state_to_obj(env, (pool_state_t)state));
    408 
    409 	(*env)->CallVoidMethod(env, object->object,
    410 	    pool_stats->method_setPoolStatus,
    411 	    zjni_pool_status_to_obj(env, zpool_import_status(config, &c)));
    412 
    413 	(*env)->CallVoidMethod(env, object->object,
    414 	    pool_stats->method_setPoolVersion, (jlong)version);
    415 
    416 	return (0);
    417 }
    418 
    419 static int
    420 populate_VirtualDeviceBean(JNIEnv *env, zpool_handle_t *zhp,
    421     nvlist_t *vdev, uint64_t *p_vdev_id, VirtualDeviceBean_t *bean)
    422 {
    423 	int result;
    424 	uint64_t vdev_id;
    425 	jstring poolUTF;
    426 
    427 	zjni_Object_t *object = (zjni_Object_t *)bean;
    428 	DeviceStatsBean_t *stats = &(bean->interface_DeviceStats);
    429 
    430 	result = populate_DeviceStatsBean(env, vdev, stats, object);
    431 	if (result != 0) {
    432 		return (1);
    433 	}
    434 
    435 	/* Set pool name */
    436 	poolUTF = (*env)->NewStringUTF(env, zpool_get_name(zhp));
    437 	(*env)->CallVoidMethod(
    438 	    env, object->object, bean->method_setPoolName, poolUTF);
    439 
    440 	/* Set parent vdev index */
    441 	(*env)->CallVoidMethod(
    442 	    env, object->object, bean->method_setParentIndex,
    443 	    p_vdev_id == NULL ? NULL :
    444 	    zjni_long_to_Long(env, *p_vdev_id));
    445 
    446 	/* Get index */
    447 	result = nvlist_lookup_uint64(vdev, ZPOOL_CONFIG_GUID, &vdev_id);
    448 	if (result != 0) {
    449 		zjni_throw_exception(env,
    450 		    "could not retrieve virtual device ID (pool %s)",
    451 		    zpool_get_name(zhp));
    452 		return (1);
    453 	}
    454 
    455 	(*env)->CallVoidMethod(
    456 	    env, object->object, bean->method_setIndex, (jlong)vdev_id);
    457 
    458 	return (0);
    459 }
    460 
    461 static int
    462 populate_LeafVirtualDeviceBean(JNIEnv *env, zpool_handle_t *zhp,
    463     nvlist_t *vdev, uint64_t *p_vdev_id, LeafVirtualDeviceBean_t *bean)
    464 {
    465 	return (populate_VirtualDeviceBean(
    466 	    env, zhp, vdev, p_vdev_id, (VirtualDeviceBean_t *)bean));
    467 }
    468 
    469 static int
    470 populate_DiskVirtualDeviceBean(JNIEnv *env, zpool_handle_t *zhp,
    471     nvlist_t *vdev, uint64_t *p_vdev_id, DiskVirtualDeviceBean_t *bean)
    472 {
    473 	char *path;
    474 	int result = populate_LeafVirtualDeviceBean(
    475 	    env, zhp, vdev, p_vdev_id, (LeafVirtualDeviceBean_t *)bean);
    476 
    477 	if (result) {
    478 		/* Must not call any more Java methods to preserve exception */
    479 		return (-1);
    480 	}
    481 
    482 	/* Set path */
    483 	result = nvlist_lookup_string(vdev, ZPOOL_CONFIG_PATH, &path);
    484 	if (result != 0) {
    485 		zjni_throw_exception(env,
    486 		    "could not retrieve path from disk virtual device "
    487 		    "(pool %s)", zpool_get_name(zhp));
    488 	} else {
    489 
    490 		regex_t re;
    491 		regmatch_t matches[2];
    492 		jstring pathUTF = NULL;
    493 
    494 		/* Strip off slice portion of name, if applicable */
    495 		if (regcomp(&re, "^(/dev/dsk/.*)s[0-9]+$", REG_EXTENDED) == 0) {
    496 			if (regexec(&re, path, 2, matches, 0) == 0) {
    497 				regmatch_t *match = matches + 1;
    498 				if (match->rm_so != -1 && match->rm_eo != -1) {
    499 					char *tmp = strdup(path);
    500 					if (tmp != NULL) {
    501 						char *end = tmp + match->rm_eo;
    502 						*end = '\0';
    503 						pathUTF = (*env)->NewStringUTF(
    504 						    env, tmp);
    505 						free(tmp);
    506 					}
    507 				}
    508 			}
    509 			regfree(&re);
    510 		}
    511 
    512 		if (pathUTF == NULL) {
    513 			pathUTF = (*env)->NewStringUTF(env, path);
    514 		}
    515 
    516 		(*env)->CallVoidMethod(env, ((zjni_Object_t *)bean)->object,
    517 		    ((LeafVirtualDeviceBean_t *)bean)->method_setName, pathUTF);
    518 	}
    519 
    520 	return (result != 0);
    521 }
    522 
    523 static int
    524 populate_SliceVirtualDeviceBean(JNIEnv *env, zpool_handle_t *zhp,
    525     nvlist_t *vdev, uint64_t *p_vdev_id, SliceVirtualDeviceBean_t *bean)
    526 {
    527 	char *path;
    528 	int result = populate_LeafVirtualDeviceBean(
    529 	    env, zhp, vdev, p_vdev_id, (LeafVirtualDeviceBean_t *)bean);
    530 
    531 	if (result) {
    532 		/* Must not call any more Java methods to preserve exception */
    533 		return (-1);
    534 	}
    535 
    536 	/* Set path */
    537 	result = nvlist_lookup_string(vdev, ZPOOL_CONFIG_PATH, &path);
    538 	if (result != 0) {
    539 		zjni_throw_exception(env,
    540 		    "could not retrieve path from slice virtual device (pool "
    541 		    "%s)", zpool_get_name(zhp));
    542 	} else {
    543 
    544 		jstring pathUTF = (*env)->NewStringUTF(env, path);
    545 		(*env)->CallVoidMethod(env, ((zjni_Object_t *)bean)->object,
    546 		    ((LeafVirtualDeviceBean_t *)bean)->method_setName,
    547 		    pathUTF);
    548 	}
    549 
    550 	return (result != 0);
    551 }
    552 
    553 static int
    554 populate_FileVirtualDeviceBean(JNIEnv *env, zpool_handle_t *zhp,
    555     nvlist_t *vdev, uint64_t *p_vdev_id, FileVirtualDeviceBean_t *bean)
    556 {
    557 	char *path;
    558 	int result = populate_LeafVirtualDeviceBean(
    559 	    env, zhp, vdev, p_vdev_id, (LeafVirtualDeviceBean_t *)bean);
    560 
    561 	if (result) {
    562 		/* Must not call any more Java methods to preserve exception */
    563 		return (-1);
    564 	}
    565 
    566 	/* Set path */
    567 	result = nvlist_lookup_string(vdev, ZPOOL_CONFIG_PATH, &path);
    568 	if (result != 0) {
    569 		zjni_throw_exception(env,
    570 		    "could not retrieve path from disk virtual device "
    571 		    "(pool %s)", zpool_get_name(zhp));
    572 	} else {
    573 
    574 		jstring pathUTF = (*env)->NewStringUTF(env, path);
    575 		(*env)->CallVoidMethod(env, ((zjni_Object_t *)bean)->object,
    576 		    ((LeafVirtualDeviceBean_t *)bean)->method_setName, pathUTF);
    577 	}
    578 
    579 	return (result != 0);
    580 }
    581 
    582 static int
    583 populate_RAIDVirtualDeviceBean(JNIEnv *env, zpool_handle_t *zhp,
    584     nvlist_t *vdev, uint64_t *p_vdev_id, RAIDVirtualDeviceBean_t *bean)
    585 {
    586 	return (populate_VirtualDeviceBean(env, zhp, vdev, p_vdev_id,
    587 	    (VirtualDeviceBean_t *)bean));
    588 }
    589 
    590 static int
    591 populate_MirrorVirtualDeviceBean(JNIEnv *env, zpool_handle_t *zhp,
    592     nvlist_t *vdev, uint64_t *p_vdev_id, MirrorVirtualDeviceBean_t *bean)
    593 {
    594 	return (populate_VirtualDeviceBean(env, zhp, vdev, p_vdev_id,
    595 	    (VirtualDeviceBean_t *)bean));
    596 }
    597 
    598 static jobject
    599 create_ImportablePoolBean(JNIEnv *env, nvlist_t *config)
    600 {
    601 	int result;
    602 	ImportablePoolBean_t bean_obj = {0};
    603 	ImportablePoolBean_t *bean = &bean_obj;
    604 
    605 	/* Construct ImportablePoolBean */
    606 	new_ImportablePoolBean(env, bean);
    607 
    608 	result = populate_ImportablePoolBean(env, bean, config);
    609 	if (result) {
    610 		/* Must not call any more Java methods to preserve exception */
    611 		return (NULL);
    612 	}
    613 
    614 	return (((zjni_Object_t *)bean)->object);
    615 }
    616 
    617 static jobject
    618 create_DiskVirtualDeviceBean(JNIEnv *env, zpool_handle_t *zhp,
    619     nvlist_t *vdev, uint64_t *p_vdev_id)
    620 {
    621 	int result;
    622 	DiskVirtualDeviceBean_t bean_obj = {0};
    623 	DiskVirtualDeviceBean_t *bean = &bean_obj;
    624 
    625 	/* Construct DiskVirtualDeviceBean */
    626 	new_DiskVirtualDeviceBean(env, bean);
    627 
    628 	result = populate_DiskVirtualDeviceBean(
    629 	    env, zhp, vdev, p_vdev_id, bean);
    630 	if (result) {
    631 		/* Must not call any more Java methods to preserve exception */
    632 		return (NULL);
    633 	}
    634 
    635 	return (((zjni_Object_t *)bean)->object);
    636 }
    637 
    638 static jobject
    639 create_SliceVirtualDeviceBean(JNIEnv *env, zpool_handle_t *zhp,
    640     nvlist_t *vdev, uint64_t *p_vdev_id)
    641 {
    642 	int result;
    643 	SliceVirtualDeviceBean_t bean_obj = {0};
    644 	SliceVirtualDeviceBean_t *bean = &bean_obj;
    645 
    646 	/* Construct SliceVirtualDeviceBean */
    647 	new_SliceVirtualDeviceBean(env, bean);
    648 
    649 	result = populate_SliceVirtualDeviceBean(
    650 	    env, zhp, vdev, p_vdev_id, bean);
    651 	if (result) {
    652 		/* Must not call any more Java methods to preserve exception */
    653 		return (NULL);
    654 	}
    655 
    656 	return (((zjni_Object_t *)bean)->object);
    657 }
    658 
    659 static jobject
    660 create_FileVirtualDeviceBean(JNIEnv *env, zpool_handle_t *zhp,
    661     nvlist_t *vdev, uint64_t *p_vdev_id)
    662 {
    663 	int result;
    664 	FileVirtualDeviceBean_t bean_obj = {0};
    665 	FileVirtualDeviceBean_t *bean = &bean_obj;
    666 
    667 	/* Construct FileVirtualDeviceBean */
    668 	new_FileVirtualDeviceBean(env, bean);
    669 
    670 	result = populate_FileVirtualDeviceBean(
    671 	    env, zhp, vdev, p_vdev_id, bean);
    672 	if (result) {
    673 		/* Must not call any more Java methods to preserve exception */
    674 		return (NULL);
    675 	}
    676 
    677 	return (((zjni_Object_t *)bean)->object);
    678 }
    679 
    680 static jobject
    681 create_RAIDVirtualDeviceBean(JNIEnv *env, zpool_handle_t *zhp,
    682     nvlist_t *vdev, uint64_t *p_vdev_id)
    683 {
    684 	int result;
    685 	uint64_t parity;
    686 	RAIDVirtualDeviceBean_t bean_obj = {0};
    687 	RAIDVirtualDeviceBean_t *bean = &bean_obj;
    688 
    689 	((zjni_Object_t *)bean)->object = NULL;
    690 
    691 	/* Construct RAIDVirtualDeviceBean */
    692 	new_RAIDVirtualDeviceBean(env, bean);
    693 
    694 	/* Set parity bit */
    695 	result = nvlist_lookup_uint64(vdev, ZPOOL_CONFIG_NPARITY,
    696 	    &parity);
    697 	if (result) {
    698 		/* Default to RAID-Z1 in case of error */
    699 		parity = 1;
    700 	}
    701 
    702 	(*env)->CallVoidMethod(
    703 	    env, ((zjni_Object_t *)bean)->object, bean->method_setParity,
    704 	    (jlong)parity);
    705 
    706 
    707 	result = populate_RAIDVirtualDeviceBean(
    708 	    env, zhp, vdev, p_vdev_id, bean);
    709 	if (result) {
    710 		/* Must not call any more Java methods to preserve exception */
    711 		return (NULL);
    712 	}
    713 
    714 	return (((zjni_Object_t *)bean)->object);
    715 }
    716 
    717 static jobject
    718 create_MirrorVirtualDeviceBean(JNIEnv *env, zpool_handle_t *zhp,
    719     nvlist_t *vdev, uint64_t *p_vdev_id)
    720 {
    721 	int result;
    722 	MirrorVirtualDeviceBean_t bean_obj = {0};
    723 	MirrorVirtualDeviceBean_t *bean = &bean_obj;
    724 
    725 	/* Construct MirrorVirtualDeviceBean */
    726 	new_MirrorVirtualDeviceBean(env, bean);
    727 
    728 	result = populate_MirrorVirtualDeviceBean(
    729 	    env, zhp, vdev, p_vdev_id, bean);
    730 	if (result) {
    731 		/* Must not call any more Java methods to preserve exception */
    732 		return (NULL);
    733 	}
    734 
    735 	return (((zjni_Object_t *)bean)->object);
    736 }
    737 
    738 static char *
    739 find_field(const zjni_field_mapping_t *mapping, int value) {
    740 	int i;
    741 	for (i = 0; mapping[i].name != NULL; i++) {
    742 		if (value == mapping[i].value) {
    743 			return (mapping[i].name);
    744 		}
    745 	}
    746 	return (NULL);
    747 }
    748 
    749 /*
    750  * Converts a vdev_state_t to a Java DeviceStats$DeviceState object.
    751  */
    752 static jobject
    753 zjni_vdev_state_to_obj(JNIEnv *env, vdev_state_t state)
    754 {
    755 	return (zjni_int_to_enum(env, state,
    756 	    ZFSJNI_PACKAGE_DATA "DeviceStats$DeviceState",
    757 	    "VDEV_STATE_UNKNOWN", vdev_state_map));
    758 }
    759 
    760 /*
    761  * Converts a vdev_aux_t to a Java DeviceStats$DeviceStatus object.
    762  */
    763 static jobject
    764 zjni_vdev_aux_to_obj(JNIEnv *env, vdev_aux_t aux)
    765 {
    766 	return (zjni_int_to_enum(env, aux,
    767 	    ZFSJNI_PACKAGE_DATA "DeviceStats$DeviceStatus",
    768 	    "VDEV_AUX_NONE", vdev_aux_map));
    769 }
    770 
    771 /*
    772  * Package-private functions
    773  */
    774 
    775 /* Create a DeviceStatsBean */
    776 void
    777 new_DeviceStats(JNIEnv *env, DeviceStatsBean_t *bean, zjni_Object_t *object)
    778 {
    779 	bean->method_setSize = (*env)->GetMethodID(
    780 	    env, object->class, "setSize", "(J)V");
    781 
    782 	bean->method_setReplacementSize = (*env)->GetMethodID(
    783 	    env, object->class, "setReplacementSize", "(J)V");
    784 
    785 	bean->method_setUsed = (*env)->GetMethodID(
    786 	    env, object->class, "setUsed", "(J)V");
    787 
    788 	bean->method_setReadBytes = (*env)->GetMethodID(
    789 	    env, object->class, "setReadBytes", "(J)V");
    790 
    791 	bean->method_setWriteBytes = (*env)->GetMethodID(
    792 	    env, object->class, "setWriteBytes", "(J)V");
    793 
    794 	bean->method_setReadOperations = (*env)->GetMethodID(
    795 	    env, object->class, "setReadOperations", "(J)V");
    796 
    797 	bean->method_setWriteOperations = (*env)->GetMethodID(
    798 	    env, object->class, "setWriteOperations", "(J)V");
    799 
    800 	bean->method_setReadErrors = (*env)->GetMethodID(
    801 	    env, object->class, "setReadErrors", "(J)V");
    802 
    803 	bean->method_setWriteErrors = (*env)->GetMethodID(
    804 	    env, object->class, "setWriteErrors", "(J)V");
    805 
    806 	bean->method_setChecksumErrors = (*env)->GetMethodID(
    807 	    env, object->class, "setChecksumErrors", "(J)V");
    808 
    809 	bean->method_setDeviceState = (*env)->GetMethodID(
    810 	    env, object->class, "setDeviceState",
    811 	    "(L" ZFSJNI_PACKAGE_DATA "DeviceStats$DeviceState;)V");
    812 
    813 	bean->method_setDeviceStatus = (*env)->GetMethodID(
    814 	    env, object->class, "setDeviceStatus",
    815 	    "(L" ZFSJNI_PACKAGE_DATA "DeviceStats$DeviceStatus;)V");
    816 }
    817 
    818 /* Create a PoolStatsBean */
    819 void
    820 new_PoolStats(JNIEnv *env, PoolStatsBean_t *bean, zjni_Object_t *object)
    821 {
    822 	new_DeviceStats(env, (DeviceStatsBean_t *)bean, object);
    823 
    824 	bean->method_setPoolState = (*env)->GetMethodID(
    825 	    env, object->class, "setPoolState",
    826 	    "(L" ZFSJNI_PACKAGE_DATA "PoolStats$PoolState;)V");
    827 
    828 	bean->method_setPoolStatus = (*env)->GetMethodID(
    829 	    env, object->class, "setPoolStatus",
    830 	    "(L" ZFSJNI_PACKAGE_DATA "PoolStats$PoolStatus;)V");
    831 
    832 	bean->method_setPoolVersion = (*env)->GetMethodID(
    833 	    env, object->class, "setPoolVersion", "(J)V");
    834 }
    835 
    836 /*
    837  * Gets the root vdev (an nvlist_t *) for the given pool.
    838  */
    839 nvlist_t *
    840 zjni_get_root_vdev(zpool_handle_t *zhp)
    841 {
    842 	nvlist_t *root = NULL;
    843 
    844 	if (zhp != NULL) {
    845 		nvlist_t *attrs = zpool_get_config(zhp, NULL);
    846 
    847 		if (attrs != NULL) {
    848 			int result = nvlist_lookup_nvlist(
    849 			    attrs, ZPOOL_CONFIG_VDEV_TREE, &root);
    850 			if (result != 0) {
    851 				root = NULL;
    852 			}
    853 		}
    854 	}
    855 
    856 	return (root);
    857 }
    858 
    859 /*
    860  * Gets the vdev (an nvlist_t *) with the given vdev_id, below the
    861  * given vdev.  If the given vdev is NULL, all vdevs within the given
    862  * pool are searched.
    863  *
    864  * If p_vdev_id is not NULL, it will be set to the ID of the parent
    865  * vdev, if any, or to vdev_id_to_find if the searched-for vdev is a
    866  * toplevel vdev.
    867  */
    868 nvlist_t *
    869 zjni_get_vdev(zpool_handle_t *zhp, nvlist_t *vdev_parent,
    870     uint64_t vdev_id_to_find, uint64_t *p_vdev_id)
    871 {
    872 	int result;
    873 	uint64_t id = vdev_id_to_find;
    874 
    875 	/* Was a vdev specified? */
    876 	if (vdev_parent == NULL) {
    877 		/* No -- retrieve the top-level pool vdev */
    878 		vdev_parent = zjni_get_root_vdev(zhp);
    879 	} else {
    880 		/* Get index of this vdev and compare with vdev_id_to_find */
    881 		result = nvlist_lookup_uint64(
    882 		    vdev_parent, ZPOOL_CONFIG_GUID, &id);
    883 		if (result == 0 && id == vdev_id_to_find) {
    884 			return (vdev_parent);
    885 		}
    886 	}
    887 
    888 	if (vdev_parent != NULL) {
    889 
    890 		nvlist_t **children;
    891 		uint_t nelem = 0;
    892 
    893 		/* Get the vdevs under this vdev */
    894 		result = nvlist_lookup_nvlist_array(
    895 		    vdev_parent, ZPOOL_CONFIG_CHILDREN, &children, &nelem);
    896 
    897 		if (result == 0) {
    898 
    899 			int i;
    900 			nvlist_t *child;
    901 
    902 			/* For each vdev child... */
    903 			for (i = 0; i < nelem; i++) {
    904 				if (p_vdev_id != NULL) {
    905 					/* Save parent vdev id */
    906 					*p_vdev_id = id;
    907 				}
    908 
    909 				child = zjni_get_vdev(zhp, children[i],
    910 				    vdev_id_to_find, p_vdev_id);
    911 				if (child != NULL) {
    912 					return (child);
    913 				}
    914 			}
    915 		}
    916 	}
    917 
    918 	return (NULL);
    919 }
    920 
    921 jobject
    922 zjni_get_VirtualDevice_from_vdev(JNIEnv *env, zpool_handle_t *zhp,
    923     nvlist_t *vdev, uint64_t *p_vdev_id)
    924 {
    925 	jobject obj = NULL;
    926 	char *type = NULL;
    927 	int result = nvlist_lookup_string(vdev, ZPOOL_CONFIG_TYPE, &type);
    928 
    929 	if (result == 0) {
    930 		if (strcmp(type, VDEV_TYPE_DISK) == 0) {
    931 			uint64_t wholedisk;
    932 			if (nvlist_lookup_uint64(vdev, ZPOOL_CONFIG_WHOLE_DISK,
    933 			    &wholedisk) == 0 && wholedisk) {
    934 				obj = create_DiskVirtualDeviceBean(
    935 				    env, zhp, vdev, p_vdev_id);
    936 			} else {
    937 				obj = create_SliceVirtualDeviceBean(
    938 				    env, zhp, vdev, p_vdev_id);
    939 			}
    940 		} else if (strcmp(type, VDEV_TYPE_FILE) == 0) {
    941 			obj = create_FileVirtualDeviceBean(
    942 			    env, zhp, vdev, p_vdev_id);
    943 		} else if (strcmp(type, VDEV_TYPE_RAIDZ) == 0) {
    944 			obj = create_RAIDVirtualDeviceBean(
    945 			    env, zhp, vdev, p_vdev_id);
    946 		} else if (strcmp(type, VDEV_TYPE_MIRROR) == 0) {
    947 			obj = create_MirrorVirtualDeviceBean(
    948 			    env, zhp, vdev, p_vdev_id);
    949 		} else if (strcmp(type, VDEV_TYPE_REPLACING) == 0) {
    950 
    951 			/* Get the vdevs under this vdev */
    952 			nvlist_t **children;
    953 			uint_t nelem = 0;
    954 			int result = nvlist_lookup_nvlist_array(
    955 			    vdev, ZPOOL_CONFIG_CHILDREN, &children, &nelem);
    956 
    957 			if (result == 0 && nelem > 0) {
    958 
    959 				/* Get last vdev child (replacement device) */
    960 				nvlist_t *child = children[nelem - 1];
    961 
    962 				obj = zjni_get_VirtualDevice_from_vdev(env,
    963 				    zhp, child, p_vdev_id);
    964 			}
    965 		}
    966 	}
    967 
    968 	return (obj);
    969 }
    970 
    971 jobject
    972 zjni_get_VirtualDevices_from_vdev(JNIEnv *env, zpool_handle_t *zhp,
    973     nvlist_t *vdev_parent, uint64_t *p_vdev_id)
    974 {
    975 	/* Create an array list for the vdevs */
    976 	zjni_ArrayList_t list_class = {0};
    977 	zjni_ArrayList_t *list_class_p = &list_class;
    978 	zjni_new_ArrayList(env, list_class_p);
    979 
    980 	/* Was a vdev specified? */
    981 	if (vdev_parent == NULL) {
    982 		/* No -- retrieve the top-level pool vdev */
    983 		vdev_parent = zjni_get_root_vdev(zhp);
    984 	}
    985 
    986 	if (vdev_parent != NULL) {
    987 
    988 		/* Get the vdevs under this vdev */
    989 		nvlist_t **children;
    990 		uint_t nelem = 0;
    991 		int result = nvlist_lookup_nvlist_array(
    992 		    vdev_parent, ZPOOL_CONFIG_CHILDREN, &children, &nelem);
    993 
    994 		if (result == 0) {
    995 
    996 			/* For each vdev child... */
    997 			int i;
    998 			for (i = 0; i < nelem; i++) {
    999 				nvlist_t *child = children[i];
   1000 
   1001 				/* Create a Java object from this vdev */
   1002 				jobject obj =
   1003 				    zjni_get_VirtualDevice_from_vdev(env,
   1004 				    zhp, child, p_vdev_id);
   1005 
   1006 				if ((*env)->ExceptionOccurred(env) != NULL) {
   1007 					/*
   1008 					 * Must not call any more Java methods
   1009 					 * to preserve exception
   1010 					 */
   1011 					return (NULL);
   1012 				}
   1013 
   1014 				if (obj != NULL) {
   1015 				    /* Add child to child vdev list */
   1016 					(*env)->CallBooleanMethod(env,
   1017 					    ((zjni_Object_t *)
   1018 					    list_class_p)->object,
   1019 					    ((zjni_Collection_t *)
   1020 					    list_class_p)->method_add, obj);
   1021 				}
   1022 			}
   1023 		}
   1024 	}
   1025 
   1026 	return (zjni_Collection_to_array(
   1027 	    env, (zjni_Collection_t *)list_class_p,
   1028 	    ZFSJNI_PACKAGE_DATA "VirtualDevice"));
   1029 }
   1030 
   1031 int
   1032 zjni_create_add_ImportablePool(nvlist_t *config, void *data) {
   1033 
   1034 	JNIEnv *env = ((zjni_ArrayCallbackData_t *)data)->env;
   1035 	zjni_Collection_t *list = ((zjni_ArrayCallbackData_t *)data)->list;
   1036 
   1037 	/* Construct ImportablePool object */
   1038 	jobject bean = create_ImportablePoolBean(env, config);
   1039 	if (bean == NULL) {
   1040 		return (-1);
   1041 	}
   1042 
   1043 	/* Add bean to list */
   1044 	(*env)->CallBooleanMethod(env, ((zjni_Object_t *)list)->object,
   1045 	    ((zjni_Collection_t *)list)->method_add, bean);
   1046 
   1047 	return (0);
   1048 }
   1049 
   1050 int
   1051 populate_DeviceStatsBean(JNIEnv *env, nvlist_t *vdev,
   1052     DeviceStatsBean_t *bean, zjni_Object_t *object)
   1053 {
   1054 	uint_t c;
   1055 	vdev_stat_t *vs;
   1056 
   1057 	int result = nvlist_lookup_uint64_array(
   1058 	    vdev, ZPOOL_CONFIG_STATS, (uint64_t **)&vs, &c);
   1059 	if (result != 0) {
   1060 		zjni_throw_exception(env,
   1061 		    "could not retrieve virtual device statistics");
   1062 		return (1);
   1063 	}
   1064 
   1065 	(*env)->CallVoidMethod(env, object->object,
   1066 	    bean->method_setUsed, (jlong)vs->vs_alloc);
   1067 
   1068 	(*env)->CallVoidMethod(env, object->object,
   1069 	    bean->method_setSize, (jlong)vs->vs_space);
   1070 
   1071 	(*env)->CallVoidMethod(env, object->object,
   1072 	    bean->method_setReplacementSize, (jlong)vs->vs_rsize);
   1073 
   1074 	(*env)->CallVoidMethod(env, object->object,
   1075 	    bean->method_setReadBytes, (jlong)vs->vs_bytes[ZIO_TYPE_READ]);
   1076 
   1077 	(*env)->CallVoidMethod(env, object->object,
   1078 	    bean->method_setWriteBytes, (jlong)vs->vs_bytes[ZIO_TYPE_WRITE]);
   1079 
   1080 	(*env)->CallVoidMethod(env, object->object,
   1081 	    bean->method_setReadOperations, (jlong)vs->vs_ops[ZIO_TYPE_READ]);
   1082 
   1083 	(*env)->CallVoidMethod(env, object->object,
   1084 	    bean->method_setWriteOperations, (jlong)vs->vs_ops[ZIO_TYPE_WRITE]);
   1085 
   1086 	(*env)->CallVoidMethod(env, object->object,
   1087 	    bean->method_setReadErrors, (jlong)vs->vs_read_errors);
   1088 
   1089 	(*env)->CallVoidMethod(env, object->object,
   1090 	    bean->method_setWriteErrors, (jlong)vs->vs_write_errors);
   1091 
   1092 	(*env)->CallVoidMethod(env, object->object,
   1093 	    bean->method_setChecksumErrors, (jlong)vs->vs_checksum_errors);
   1094 
   1095 	(*env)->CallVoidMethod(env, object->object,
   1096 	    bean->method_setDeviceState,
   1097 	    zjni_vdev_state_to_obj(env, vs->vs_state));
   1098 
   1099 	(*env)->CallVoidMethod(env, object->object,
   1100 	    bean->method_setDeviceStatus,
   1101 	    zjni_vdev_aux_to_obj(env, vs->vs_aux));
   1102 
   1103 	return (0);
   1104 }
   1105 
   1106 /*
   1107  * Converts a pool_state_t to a Java PoolStats$PoolState object.
   1108  */
   1109 jobject
   1110 zjni_pool_state_to_obj(JNIEnv *env, pool_state_t state)
   1111 {
   1112 	return (zjni_int_to_enum(env, state,
   1113 	    ZFSJNI_PACKAGE_DATA "PoolStats$PoolState",
   1114 	    "POOL_STATE_ACTIVE", pool_state_map));
   1115 }
   1116 
   1117 /*
   1118  * Converts a zpool_status_t to a Java PoolStats$PoolStatus object.
   1119  */
   1120 jobject
   1121 zjni_pool_status_to_obj(JNIEnv *env, zpool_status_t status)
   1122 {
   1123 	return (zjni_int_to_enum(env, status,
   1124 	    ZFSJNI_PACKAGE_DATA "PoolStats$PoolStatus",
   1125 	    "ZPOOL_STATUS_OK", zpool_status_map));
   1126 }
   1127 
   1128 /*
   1129  * Extern functions
   1130  */
   1131 
   1132 /*
   1133  * Iterates through each importable pool on the system.  For each
   1134  * importable pool, runs the given function with the given void as the
   1135  * last arg.
   1136  */
   1137 int
   1138 zjni_ipool_iter(int argc, char **argv, zjni_ipool_iter_f func, void *data)
   1139 {
   1140 	nvlist_t *pools = zpool_find_import(g_zfs, argc, argv);
   1141 
   1142 	if (pools != NULL) {
   1143 		nvpair_t *elem = NULL;
   1144 
   1145 		while ((elem = nvlist_next_nvpair(pools, elem)) != NULL) {
   1146 			nvlist_t *config;
   1147 
   1148 			if (nvpair_value_nvlist(elem, &config) != 0 ||
   1149 			    func(config, data)) {
   1150 				return (-1);
   1151 			}
   1152 		}
   1153 	}
   1154 
   1155 	return (0);
   1156 }
   1157 
   1158 char *
   1159 zjni_vdev_state_to_str(vdev_state_t state) {
   1160 	return (find_field(vdev_state_map, state));
   1161 }
   1162 
   1163 char *
   1164 zjni_vdev_aux_to_str(vdev_aux_t aux) {
   1165 	return (find_field(vdev_aux_map, aux));
   1166 }
   1167 
   1168 char *
   1169 zjni_pool_state_to_str(pool_state_t state) {
   1170 	return (find_field(pool_state_map, state));
   1171 }
   1172 
   1173 char *
   1174 zjni_pool_status_to_str(zpool_status_t status) {
   1175 	return (find_field(zpool_status_map, status));
   1176 }
   1177