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