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