xref: /illumos-gate/usr/src/lib/libzfs_jni/common/libzfs_jni_pool.c (revision e8031f0a8ed0e45c6d8847c5e09424e66fd34a4b)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include "libzfs_jni_pool.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_setIndex;
50 } VirtualDeviceBean_t;
51 
52 typedef struct DiskVirtualDeviceBean {
53 	VirtualDeviceBean_t super;
54 
55 	jmethodID method_setDiskName;
56 } DiskVirtualDeviceBean_t;
57 
58 typedef struct FileVirtualDeviceBean {
59 	VirtualDeviceBean_t super;
60 
61 	jmethodID method_setFileName;
62 } FileVirtualDeviceBean_t;
63 
64 typedef struct RAIDVirtualDeviceBean {
65 	VirtualDeviceBean_t super;
66 } RAIDVirtualDeviceBean_t;
67 
68 typedef struct MirrorVirtualDeviceBean {
69 	VirtualDeviceBean_t super;
70 } MirrorVirtualDeviceBean_t;
71 
72 /*
73  * Data
74  */
75 
76 /* vdev_state_t to DeviceStats$DeviceState map */
77 static zjni_field_mapping_t vdev_state_map[] = {
78 	{ VDEV_STATE_CANT_OPEN, "VDEV_STATE_CANT_OPEN" },
79 	{ VDEV_STATE_CLOSED, "VDEV_STATE_CLOSED" },
80 	{ VDEV_STATE_DEGRADED, "VDEV_STATE_DEGRADED" },
81 	{ VDEV_STATE_HEALTHY, "VDEV_STATE_HEALTHY" },
82 	{ VDEV_STATE_OFFLINE, "VDEV_STATE_OFFLINE" },
83 	{ VDEV_STATE_UNKNOWN, "VDEV_STATE_UNKNOWN" },
84 	{ -1, NULL },
85 };
86 
87 /* vdev_aux_t to DeviceStats$DeviceStatus map */
88 static zjni_field_mapping_t vdev_aux_map[] = {
89 	{ VDEV_AUX_NONE, "VDEV_AUX_NONE" },
90 	{ VDEV_AUX_OPEN_FAILED, "VDEV_AUX_OPEN_FAILED" },
91 	{ VDEV_AUX_CORRUPT_DATA, "VDEV_AUX_CORRUPT_DATA" },
92 	{ VDEV_AUX_NO_REPLICAS, "VDEV_AUX_NO_REPLICAS" },
93 	{ VDEV_AUX_BAD_GUID_SUM, "VDEV_AUX_BAD_GUID_SUM" },
94 	{ VDEV_AUX_TOO_SMALL, "VDEV_AUX_TOO_SMALL" },
95 	{ VDEV_AUX_BAD_LABEL, "VDEV_AUX_BAD_LABEL" },
96 	{ -1, NULL },
97 };
98 
99 /* zpool_state_t to PoolStats$PoolState map */
100 static zjni_field_mapping_t pool_state_map[] = {
101 	{ POOL_STATE_ACTIVE, "POOL_STATE_ACTIVE" },
102 	{ POOL_STATE_EXPORTED, "POOL_STATE_EXPORTED" },
103 	{ POOL_STATE_DESTROYED, "POOL_STATE_DESTROYED" },
104 	{ POOL_STATE_UNINITIALIZED, "POOL_STATE_UNINITIALIZED" },
105 	{ POOL_STATE_UNAVAIL, "POOL_STATE_UNAVAIL" },
106 	{ -1, NULL },
107 };
108 
109 /* zpool_status_t to PoolStats$PoolStatus map */
110 static zjni_field_mapping_t zpool_status_map[] = {
111 	{ ZPOOL_STATUS_CORRUPT_CACHE,
112 	    "ZPOOL_STATUS_CORRUPT_CACHE" },
113 	{ ZPOOL_STATUS_MISSING_DEV_R,
114 	    "ZPOOL_STATUS_MISSING_DEV_R" },
115 	{ ZPOOL_STATUS_MISSING_DEV_NR,
116 	    "ZPOOL_STATUS_MISSING_DEV_NR" },
117 	{ ZPOOL_STATUS_CORRUPT_LABEL_R,
118 	    "ZPOOL_STATUS_CORRUPT_LABEL_R" },
119 	{ ZPOOL_STATUS_CORRUPT_LABEL_NR,
120 	    "ZPOOL_STATUS_CORRUPT_LABEL_NR" },
121 	{ ZPOOL_STATUS_BAD_GUID_SUM, "ZPOOL_STATUS_BAD_GUID_SUM" },
122 	{ ZPOOL_STATUS_CORRUPT_POOL, "ZPOOL_STATUS_CORRUPT_POOL" },
123 	{ ZPOOL_STATUS_CORRUPT_DATA, "ZPOOL_STATUS_CORRUPT_DATA" },
124 	{ ZPOOL_STATUS_FAILING_DEV, "ZPOOL_STATUS_FAILING_DEV" },
125 	{ ZPOOL_STATUS_VERSION_MISMATCH,
126 	    "ZPOOL_STATUS_VERSION_MISMATCH" },
127 	{ ZPOOL_STATUS_RESILVERING, "ZPOOL_STATUS_RESILVERING" },
128 	{ ZPOOL_STATUS_OFFLINE_DEV, "ZPOOL_STATUS_OFFLINE_DEV" },
129 	{ ZPOOL_STATUS_OK, "ZPOOL_STATUS_OK" },
130 	{ -1, NULL },
131 };
132 
133 /*
134  * Function prototypes
135  */
136 
137 static void new_ImportablePoolBean(JNIEnv *, ImportablePoolBean_t *);
138 static void new_VirtualDevice(JNIEnv *, VirtualDeviceBean_t *);
139 static void new_DiskVirtualDeviceBean(JNIEnv *, DiskVirtualDeviceBean_t *);
140 static void new_FileVirtualDeviceBean(JNIEnv *, FileVirtualDeviceBean_t *);
141 static void new_RAIDVirtualDeviceBean(JNIEnv *, RAIDVirtualDeviceBean_t *);
142 static void new_MirrorVirtualDeviceBean(JNIEnv *, MirrorVirtualDeviceBean_t *);
143 static int populate_ImportablePoolBean(
144     JNIEnv *, ImportablePoolBean_t *, nvlist_t *);
145 static int populate_VirtualDeviceBean(
146     JNIEnv *, zpool_handle_t *, nvlist_t *, VirtualDeviceBean_t *);
147 static int populate_DiskVirtualDeviceBean(
148     JNIEnv *, zpool_handle_t *, nvlist_t *, DiskVirtualDeviceBean_t *);
149 static int populate_FileVirtualDeviceBean(
150     JNIEnv *, zpool_handle_t *, nvlist_t *, FileVirtualDeviceBean_t *);
151 static int populate_RAIDVirtualDeviceBean(
152     JNIEnv *, zpool_handle_t *, nvlist_t *, RAIDVirtualDeviceBean_t *);
153 static int populate_MirrorVirtualDeviceBean(
154     JNIEnv *, zpool_handle_t *, nvlist_t *, MirrorVirtualDeviceBean_t *);
155 static jobject create_ImportablePoolBean(JNIEnv *, nvlist_t *);
156 static jobject create_DiskVirtualDeviceBean(
157     JNIEnv *, zpool_handle_t *, nvlist_t *);
158 static jobject create_FileVirtualDeviceBean(
159     JNIEnv *, zpool_handle_t *, nvlist_t *);
160 static jobject create_RAIDVirtualDeviceBean(
161     JNIEnv *, zpool_handle_t *, nvlist_t *);
162 static jobject create_MirrorVirtualDeviceBean(
163     JNIEnv *, zpool_handle_t *, nvlist_t *);
164 static char *find_field(const zjni_field_mapping_t *, int);
165 static jobject zjni_vdev_state_to_obj(JNIEnv *, vdev_state_t);
166 static jobject zjni_vdev_aux_to_obj(JNIEnv *, vdev_aux_t);
167 
168 /*
169  * Static functions
170  */
171 
172 /* Create a ImportablePoolBean */
173 static void
174 new_ImportablePoolBean(JNIEnv *env, ImportablePoolBean_t *bean)
175 {
176 	zjni_Object_t *object = (zjni_Object_t *)bean;
177 
178 	if (object->object == NULL) {
179 		object->class =
180 		    (*env)->FindClass(env,
181 			ZFSJNI_PACKAGE_DATA "ImportablePoolBean");
182 
183 		object->constructor =
184 		    (*env)->GetMethodID(env, object->class, "<init>", "()V");
185 
186 		object->object =
187 		    (*env)->NewObject(env, object->class, object->constructor);
188 	}
189 
190 	new_PoolStats(env, &(bean->interface_PoolStats), object);
191 
192 	bean->method_setName = (*env)->GetMethodID(
193 	    env, object->class, "setName", "(Ljava/lang/String;)V");
194 
195 	bean->method_setId = (*env)->GetMethodID(
196 	    env, object->class, "setId", "(J)V");
197 }
198 
199 /* Create a VirtualDeviceBean */
200 static void
201 new_VirtualDevice(JNIEnv *env, VirtualDeviceBean_t *bean)
202 {
203 	zjni_Object_t *object = (zjni_Object_t *)bean;
204 
205 	if (object->object == NULL) {
206 		object->class =
207 		    (*env)->FindClass(env,
208 			ZFSJNI_PACKAGE_DATA "VirtualDeviceBean");
209 
210 		object->constructor =
211 		    (*env)->GetMethodID(env, object->class, "<init>", "()V");
212 
213 		object->object =
214 		    (*env)->NewObject(env, object->class, object->constructor);
215 	}
216 
217 	new_DeviceStats(env, &(bean->interface_DeviceStats), object);
218 
219 	bean->method_setPoolName = (*env)->GetMethodID(
220 	    env, object->class, "setPoolName", "(Ljava/lang/String;)V");
221 
222 	bean->method_setIndex = (*env)->GetMethodID(
223 	    env, object->class, "setIndex", "(J)V");
224 }
225 
226 /* Create a DiskVirtualDeviceBean */
227 static void
228 new_DiskVirtualDeviceBean(JNIEnv *env, DiskVirtualDeviceBean_t *bean)
229 {
230 	zjni_Object_t *object = (zjni_Object_t *)bean;
231 
232 	if (object->object == NULL) {
233 		object->class = (*env)->FindClass(
234 		    env, ZFSJNI_PACKAGE_DATA "DiskVirtualDeviceBean");
235 
236 		object->constructor =
237 		    (*env)->GetMethodID(env, object->class, "<init>", "()V");
238 
239 		object->object =
240 		    (*env)->NewObject(env, object->class, object->constructor);
241 	}
242 
243 	new_VirtualDevice(env, (VirtualDeviceBean_t *)bean);
244 
245 	bean->method_setDiskName = (*env)->GetMethodID(
246 	    env, object->class, "setDiskName", "(Ljava/lang/String;)V");
247 
248 }
249 
250 /* Create a FileVirtualDeviceBean */
251 static void
252 new_FileVirtualDeviceBean(JNIEnv *env, FileVirtualDeviceBean_t *bean)
253 {
254 	zjni_Object_t *object = (zjni_Object_t *)bean;
255 
256 	if (object->object == NULL) {
257 		object->class = (*env)->FindClass(
258 		    env, ZFSJNI_PACKAGE_DATA "FileVirtualDeviceBean");
259 
260 		object->constructor =
261 		    (*env)->GetMethodID(env, object->class, "<init>", "()V");
262 
263 		object->object =
264 		    (*env)->NewObject(env, object->class, object->constructor);
265 	}
266 
267 	new_VirtualDevice(env, (VirtualDeviceBean_t *)bean);
268 
269 	bean->method_setFileName = (*env)->GetMethodID(
270 	    env, object->class, "setFileName", "(Ljava/lang/String;)V");
271 }
272 
273 /* Create a RAIDVirtualDeviceBean */
274 static void
275 new_RAIDVirtualDeviceBean(JNIEnv *env, RAIDVirtualDeviceBean_t *bean)
276 {
277 	zjni_Object_t *object = (zjni_Object_t *)bean;
278 
279 	if (object->object == NULL) {
280 
281 		object->class = (*env)->FindClass(
282 		    env, ZFSJNI_PACKAGE_DATA "RAIDVirtualDeviceBean");
283 
284 		object->constructor =
285 		    (*env)->GetMethodID(env, object->class, "<init>", "()V");
286 
287 		object->object =
288 		    (*env)->NewObject(env, object->class, object->constructor);
289 	}
290 
291 	new_VirtualDevice(env, (VirtualDeviceBean_t *)bean);
292 }
293 
294 /* Create a MirrorVirtualDeviceBean */
295 static void
296 new_MirrorVirtualDeviceBean(JNIEnv *env, MirrorVirtualDeviceBean_t *bean)
297 {
298 	zjni_Object_t *object = (zjni_Object_t *)bean;
299 
300 	if (object->object == NULL) {
301 		object->class = (*env)->FindClass(
302 		    env, ZFSJNI_PACKAGE_DATA "MirrorVirtualDeviceBean");
303 
304 		object->constructor =
305 		    (*env)->GetMethodID(env, object->class, "<init>", "()V");
306 
307 		object->object =
308 		    (*env)->NewObject(env, object->class, object->constructor);
309 	}
310 
311 	new_VirtualDevice(env, (VirtualDeviceBean_t *)bean);
312 }
313 
314 static int
315 populate_ImportablePoolBean(JNIEnv *env, ImportablePoolBean_t *bean,
316     nvlist_t *config)
317 {
318 	char *c;
319 	char *name;
320 	uint64_t guid;
321 	uint64_t state;
322 	nvlist_t *devices;
323 
324 	zjni_Object_t *object = (zjni_Object_t *)bean;
325 	PoolStatsBean_t *pool_stats = &(bean->interface_PoolStats);
326 	DeviceStatsBean_t *dev_stats = (DeviceStatsBean_t *)pool_stats;
327 
328 	if (nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME, &name) ||
329 	    nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, &guid) ||
330 	    nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE, &state) ||
331 	    nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, &devices) ||
332 	    populate_DeviceStatsBean(env, devices, dev_stats, object)) {
333 		return (-1);
334 	}
335 
336 	(*env)->CallVoidMethod(env, object->object,
337 	    bean->method_setName, (*env)->NewStringUTF(env, name));
338 
339 	(*env)->CallVoidMethod(env, object->object,
340 	    bean->method_setId, (jlong)guid);
341 
342 	(*env)->CallVoidMethod(env, object->object,
343 	    pool_stats->method_setPoolState,
344 	    zjni_pool_state_to_obj(env, (pool_state_t)state));
345 
346 	(*env)->CallVoidMethod(env, object->object,
347 	    pool_stats->method_setPoolStatus,
348 	    zjni_pool_status_to_obj(env, zpool_import_status(config, &c)));
349 
350 	return (0);
351 }
352 
353 static int
354 populate_VirtualDeviceBean(JNIEnv *env, zpool_handle_t *zhp,
355     nvlist_t *vdev, VirtualDeviceBean_t *bean)
356 {
357 	int result;
358 	uint64_t vdev_id;
359 	jstring poolUTF;
360 
361 	zjni_Object_t *object = (zjni_Object_t *)bean;
362 	DeviceStatsBean_t *stats = &(bean->interface_DeviceStats);
363 
364 	result = populate_DeviceStatsBean(env, vdev, stats, object);
365 	if (result != 0) {
366 		return (1);
367 	}
368 
369 	/* Set pool name */
370 	poolUTF = (*env)->NewStringUTF(env, zpool_get_name(zhp));
371 	(*env)->CallVoidMethod(
372 	    env, object->object, bean->method_setPoolName, poolUTF);
373 
374 	/* Get index */
375 	result = nvlist_lookup_uint64(vdev, ZPOOL_CONFIG_GUID, &vdev_id);
376 	if (result != 0) {
377 		zjni_throw_exception(env,
378 		    "could not retrieve virtual device ID (pool %s)",
379 		    zpool_get_name(zhp));
380 		return (1);
381 	}
382 
383 	(*env)->CallVoidMethod(
384 	    env, object->object, bean->method_setIndex, (jlong)vdev_id);
385 
386 	return (0);
387 }
388 
389 static int
390 populate_DiskVirtualDeviceBean(JNIEnv *env, zpool_handle_t *zhp,
391     nvlist_t *vdev, DiskVirtualDeviceBean_t *bean)
392 {
393 	char *path;
394 	int result = populate_VirtualDeviceBean(
395 	    env, zhp, vdev, (VirtualDeviceBean_t *)bean);
396 
397 	if (result) {
398 		/* Must not call any more Java methods to preserve exception */
399 		return (-1);
400 	}
401 
402 	/* Set path */
403 	result = nvlist_lookup_string(vdev, ZPOOL_CONFIG_PATH, &path);
404 	if (result != 0) {
405 		zjni_throw_exception(env,
406 		    "could not retrive path from disk virtual device (pool %s)",
407 		    zpool_get_name(zhp));
408 	} else {
409 
410 		jstring pathUTF = (*env)->NewStringUTF(env, path);
411 		(*env)->CallVoidMethod(env, ((zjni_Object_t *)bean)->object,
412 		    bean->method_setDiskName, pathUTF);
413 	}
414 
415 	return (result != 0);
416 }
417 
418 static int
419 populate_FileVirtualDeviceBean(JNIEnv *env, zpool_handle_t *zhp,
420     nvlist_t *vdev, FileVirtualDeviceBean_t *bean)
421 {
422 	char *path;
423 	int result = populate_VirtualDeviceBean(
424 	    env, zhp, vdev, (VirtualDeviceBean_t *)bean);
425 
426 	if (result) {
427 		/* Must not call any more Java methods to preserve exception */
428 		return (-1);
429 	}
430 
431 	/* Set path */
432 	result = nvlist_lookup_string(vdev, ZPOOL_CONFIG_PATH, &path);
433 	if (result != 0) {
434 		zjni_throw_exception(env,
435 		    "could not retrive path from disk virtual device (pool %s)",
436 		    zpool_get_name(zhp));
437 	} else {
438 
439 		jstring pathUTF = (*env)->NewStringUTF(env, path);
440 		(*env)->CallVoidMethod(env, ((zjni_Object_t *)bean)->object,
441 		    bean->method_setFileName, pathUTF);
442 	}
443 
444 	return (result != 0);
445 }
446 
447 static int
448 populate_RAIDVirtualDeviceBean(JNIEnv *env, zpool_handle_t *zhp,
449     nvlist_t *vdev, RAIDVirtualDeviceBean_t *bean)
450 {
451 	return (populate_VirtualDeviceBean(env, zhp, vdev,
452 	    (VirtualDeviceBean_t *)bean));
453 }
454 
455 static int
456 populate_MirrorVirtualDeviceBean(JNIEnv *env, zpool_handle_t *zhp,
457     nvlist_t *vdev, MirrorVirtualDeviceBean_t *bean)
458 {
459 	return (populate_VirtualDeviceBean(env, zhp, vdev,
460 	    (VirtualDeviceBean_t *)bean));
461 }
462 
463 static jobject
464 create_ImportablePoolBean(JNIEnv *env, nvlist_t *config)
465 {
466 	int result;
467 	ImportablePoolBean_t bean_obj = {0};
468 	ImportablePoolBean_t *bean = &bean_obj;
469 
470 	/* Construct ImportablePoolBean */
471 	new_ImportablePoolBean(env, bean);
472 
473 	result = populate_ImportablePoolBean(env, bean, config);
474 	if (result) {
475 		/* Must not call any more Java methods to preserve exception */
476 		return (NULL);
477 	}
478 
479 	return (((zjni_Object_t *)bean)->object);
480 }
481 
482 static jobject
483 create_DiskVirtualDeviceBean(JNIEnv *env, zpool_handle_t *zhp, nvlist_t *vdev)
484 {
485 	int result;
486 	DiskVirtualDeviceBean_t bean_obj = {0};
487 	DiskVirtualDeviceBean_t *bean = &bean_obj;
488 
489 	/* Construct DiskVirtualDeviceBean */
490 	new_DiskVirtualDeviceBean(env, bean);
491 
492 	result = populate_DiskVirtualDeviceBean(env, zhp, vdev, bean);
493 	if (result) {
494 		/* Must not call any more Java methods to preserve exception */
495 		return (NULL);
496 	}
497 
498 	return (((zjni_Object_t *)bean)->object);
499 }
500 
501 static jobject
502 create_FileVirtualDeviceBean(JNIEnv *env, zpool_handle_t *zhp, nvlist_t *vdev)
503 {
504 	int result;
505 	FileVirtualDeviceBean_t bean_obj = {0};
506 	FileVirtualDeviceBean_t *bean = &bean_obj;
507 
508 	/* Construct FileVirtualDeviceBean */
509 	new_FileVirtualDeviceBean(env, bean);
510 
511 	result = populate_FileVirtualDeviceBean(env, zhp, vdev, bean);
512 	if (result) {
513 		/* Must not call any more Java methods to preserve exception */
514 		return (NULL);
515 	}
516 
517 	return (((zjni_Object_t *)bean)->object);
518 }
519 
520 static jobject
521 create_RAIDVirtualDeviceBean(JNIEnv *env, zpool_handle_t *zhp, nvlist_t *vdev)
522 {
523 	int result;
524 	RAIDVirtualDeviceBean_t bean_obj = {0};
525 	RAIDVirtualDeviceBean_t *bean = &bean_obj;
526 
527 	((zjni_Object_t *)bean)->object = NULL;
528 
529 	/* Construct RAIDVirtualDeviceBean */
530 	new_RAIDVirtualDeviceBean(env, bean);
531 
532 	result = populate_RAIDVirtualDeviceBean(env, zhp, vdev, bean);
533 	if (result) {
534 		/* Must not call any more Java methods to preserve exception */
535 		return (NULL);
536 	}
537 
538 	return (((zjni_Object_t *)bean)->object);
539 }
540 
541 static jobject
542 create_MirrorVirtualDeviceBean(JNIEnv *env, zpool_handle_t *zhp, nvlist_t *vdev)
543 {
544 	int result;
545 	MirrorVirtualDeviceBean_t bean_obj = {0};
546 	MirrorVirtualDeviceBean_t *bean = &bean_obj;
547 
548 	/* Construct MirrorVirtualDeviceBean */
549 	new_MirrorVirtualDeviceBean(env, bean);
550 
551 	result = populate_MirrorVirtualDeviceBean(env, zhp, vdev, bean);
552 	if (result) {
553 		/* Must not call any more Java methods to preserve exception */
554 		return (NULL);
555 	}
556 
557 	return (((zjni_Object_t *)bean)->object);
558 }
559 
560 static char *
561 find_field(const zjni_field_mapping_t *mapping, int value) {
562 	int i;
563 	for (i = 0; mapping[i].name != NULL; i++) {
564 		if (value == mapping[i].value) {
565 			return (mapping[i].name);
566 		}
567 	}
568 	return (NULL);
569 }
570 
571 /*
572  * Converts a vdev_state_t to a Java DeviceStats$DeviceState object.
573  */
574 static jobject
575 zjni_vdev_state_to_obj(JNIEnv *env, vdev_state_t state)
576 {
577 	return (zjni_int_to_enum(env, state,
578 	    ZFSJNI_PACKAGE_DATA "DeviceStats$DeviceState",
579 	    "VDEV_STATE_UNKNOWN", vdev_state_map));
580 }
581 
582 /*
583  * Converts a vdev_aux_t to a Java DeviceStats$DeviceStatus object.
584  */
585 static jobject
586 zjni_vdev_aux_to_obj(JNIEnv *env, vdev_aux_t aux)
587 {
588 	return (zjni_int_to_enum(env, aux,
589 	    ZFSJNI_PACKAGE_DATA "DeviceStats$DeviceStatus",
590 	    "VDEV_AUX_NONE", vdev_aux_map));
591 }
592 
593 /*
594  * Package-private functions
595  */
596 
597 /* Create a DeviceStatsBean */
598 void
599 new_DeviceStats(JNIEnv *env, DeviceStatsBean_t *bean, zjni_Object_t *object)
600 {
601 	bean->method_setSize = (*env)->GetMethodID(
602 	    env, object->class, "setSize", "(J)V");
603 
604 	bean->method_setUsed = (*env)->GetMethodID(
605 	    env, object->class, "setUsed", "(J)V");
606 
607 	bean->method_setReadBytes = (*env)->GetMethodID(
608 	    env, object->class, "setReadBytes", "(J)V");
609 
610 	bean->method_setWriteBytes = (*env)->GetMethodID(
611 	    env, object->class, "setWriteBytes", "(J)V");
612 
613 	bean->method_setReadOperations = (*env)->GetMethodID(
614 	    env, object->class, "setReadOperations", "(J)V");
615 
616 	bean->method_setWriteOperations = (*env)->GetMethodID(
617 	    env, object->class, "setWriteOperations", "(J)V");
618 
619 	bean->method_setReadErrors = (*env)->GetMethodID(
620 	    env, object->class, "setReadErrors", "(J)V");
621 
622 	bean->method_setWriteErrors = (*env)->GetMethodID(
623 	    env, object->class, "setWriteErrors", "(J)V");
624 
625 	bean->method_setChecksumErrors = (*env)->GetMethodID(
626 	    env, object->class, "setChecksumErrors", "(J)V");
627 
628 	bean->method_setDeviceState = (*env)->GetMethodID(
629 	    env, object->class, "setDeviceState",
630 	    "(L" ZFSJNI_PACKAGE_DATA "DeviceStats$DeviceState;)V");
631 
632 	bean->method_setDeviceStatus = (*env)->GetMethodID(
633 	    env, object->class, "setDeviceStatus",
634 	    "(L" ZFSJNI_PACKAGE_DATA "DeviceStats$DeviceStatus;)V");
635 }
636 
637 /* Create a PoolStatsBean */
638 void
639 new_PoolStats(JNIEnv *env, PoolStatsBean_t *bean, zjni_Object_t *object)
640 {
641 	new_DeviceStats(env, (DeviceStatsBean_t *)bean, object);
642 
643 	bean->method_setPoolState = (*env)->GetMethodID(
644 	    env, object->class, "setPoolState",
645 	    "(L" ZFSJNI_PACKAGE_DATA "PoolStats$PoolState;)V");
646 
647 	bean->method_setPoolStatus = (*env)->GetMethodID(
648 	    env, object->class, "setPoolStatus",
649 	    "(L" ZFSJNI_PACKAGE_DATA "PoolStats$PoolStatus;)V");
650 }
651 
652 /*
653  * Gets the root vdev (an nvlist_t *) for the given pool.
654  */
655 nvlist_t *
656 zjni_get_root_vdev(zpool_handle_t *zhp)
657 {
658 	nvlist_t *root = NULL;
659 
660 	if (zhp != NULL) {
661 		nvlist_t *attrs = zpool_get_config(zhp, NULL);
662 
663 		if (attrs != NULL) {
664 			int result = nvlist_lookup_nvlist(
665 			    attrs, ZPOOL_CONFIG_VDEV_TREE, &root);
666 			if (result != 0) {
667 				root = NULL;
668 			}
669 		}
670 	}
671 
672 	return (root);
673 }
674 
675 /*
676  * Gets the vdev (an nvlist_t *) with the given vdev_id, below the
677  * given vdev.  If the given vdev is NULL, all vdevs within the given
678  * pool are searched.
679  */
680 nvlist_t *
681 zjni_get_vdev(zpool_handle_t *zhp, nvlist_t *vdev_parent,
682     uint64_t vdev_id_to_find)
683 {
684 	int result;
685 
686 	/* Was a vdev specified? */
687 	if (vdev_parent == NULL) {
688 		/* No -- retrieve the top-level pool vdev */
689 		vdev_parent = zjni_get_root_vdev(zhp);
690 	} else {
691 		/* Get index of this vdev and compare with vdev_id_to_find */
692 		uint64_t id;
693 		result = nvlist_lookup_uint64(
694 		    vdev_parent, ZPOOL_CONFIG_GUID, &id);
695 		if (result == 0 && id == vdev_id_to_find) {
696 			return (vdev_parent);
697 		}
698 	}
699 
700 	if (vdev_parent != NULL) {
701 
702 		nvlist_t **children;
703 		uint_t nelem = 0;
704 
705 		/* Get the vdevs under this vdev */
706 		result = nvlist_lookup_nvlist_array(
707 		    vdev_parent, ZPOOL_CONFIG_CHILDREN, &children, &nelem);
708 
709 		if (result == 0) {
710 
711 			int i;
712 			nvlist_t *child;
713 
714 			/* For each vdev child... */
715 			for (i = 0; i < nelem; i++) {
716 				child = zjni_get_vdev(zhp, children[i],
717 				    vdev_id_to_find);
718 				if (child != NULL) {
719 					return (child);
720 				}
721 			}
722 		}
723 	}
724 
725 	return (NULL);
726 }
727 
728 jobject
729 zjni_get_VirtualDevice_from_vdev(JNIEnv *env, zpool_handle_t *zhp,
730     nvlist_t *vdev)
731 {
732 	jobject obj = NULL;
733 	char *type = NULL;
734 	int result = nvlist_lookup_string(vdev, ZPOOL_CONFIG_TYPE, &type);
735 
736 	if (result == 0) {
737 		if (strcmp(type, VDEV_TYPE_DISK) == 0) {
738 			obj = create_DiskVirtualDeviceBean(env, zhp, vdev);
739 		} else if (strcmp(type, VDEV_TYPE_FILE) == 0) {
740 			obj = create_FileVirtualDeviceBean(env, zhp, vdev);
741 		} else if (strcmp(type, VDEV_TYPE_RAIDZ) == 0) {
742 			obj = create_RAIDVirtualDeviceBean(env, zhp, vdev);
743 		} else if (strcmp(type, VDEV_TYPE_MIRROR) == 0) {
744 			obj = create_MirrorVirtualDeviceBean(env, zhp, vdev);
745 		} else if (strcmp(type, VDEV_TYPE_REPLACING) == 0) {
746 
747 			/* Get the vdevs under this vdev */
748 			nvlist_t **children;
749 			uint_t nelem = 0;
750 			int result = nvlist_lookup_nvlist_array(
751 			    vdev, ZPOOL_CONFIG_CHILDREN, &children, &nelem);
752 
753 			if (result == 0 && nelem > 0) {
754 
755 				/* Get last vdev child (replacement device) */
756 				nvlist_t *child = children[nelem - 1];
757 
758 				obj = zjni_get_VirtualDevice_from_vdev(env,
759 				    zhp, child);
760 			}
761 		}
762 	}
763 
764 	return (obj);
765 }
766 
767 jobject
768 zjni_get_VirtualDevices_from_vdev(JNIEnv *env, zpool_handle_t *zhp,
769     nvlist_t *vdev_parent)
770 {
771 	/* Create an array list for the vdevs */
772 	zjni_ArrayList_t list_class = {0};
773 	zjni_ArrayList_t *list_class_p = &list_class;
774 	zjni_new_ArrayList(env, list_class_p);
775 
776 	/* Was a vdev specified? */
777 	if (vdev_parent == NULL) {
778 		/* No -- retrieve the top-level pool vdev */
779 		vdev_parent = zjni_get_root_vdev(zhp);
780 	}
781 
782 	if (vdev_parent != NULL) {
783 
784 		/* Get the vdevs under this vdev */
785 		nvlist_t **children;
786 		uint_t nelem = 0;
787 		int result = nvlist_lookup_nvlist_array(
788 		    vdev_parent, ZPOOL_CONFIG_CHILDREN, &children, &nelem);
789 
790 		if (result == 0) {
791 
792 			/* For each vdev child... */
793 			int i;
794 			for (i = 0; i < nelem; i++) {
795 				nvlist_t *child = children[i];
796 
797 				/* Create a Java object from this vdev */
798 				jobject obj =
799 				    zjni_get_VirtualDevice_from_vdev(env,
800 					zhp, child);
801 
802 				if ((*env)->ExceptionOccurred(env) != NULL) {
803 					/*
804 					 * Must not call any more Java methods
805 					 * to preserve exception
806 					 */
807 					return (NULL);
808 				}
809 
810 				if (obj != NULL) {
811 				    /* Add child to child vdev list */
812 				    (*env)->CallBooleanMethod(env,
813 					((zjni_Object_t *)list_class_p)->object,
814 					((zjni_Collection_t *)list_class_p)->
815 					method_add, obj);
816 				}
817 			}
818 		}
819 	}
820 
821 	return (zjni_Collection_to_array(
822 	    env, (zjni_Collection_t *)list_class_p,
823 	    ZFSJNI_PACKAGE_DATA "VirtualDevice"));
824 }
825 
826 int
827 zjni_create_add_ImportablePool(nvlist_t *config, void *data) {
828 
829 	JNIEnv *env = ((zjni_ArrayCallbackData_t *)data)->env;
830 	zjni_Collection_t *list = ((zjni_ArrayCallbackData_t *)data)->list;
831 
832 	/* Construct ImportablePool object */
833 	jobject bean = create_ImportablePoolBean(env, config);
834 	if (bean == NULL) {
835 		return (-1);
836 	}
837 
838 	/* Add bean to list */
839 	(*env)->CallBooleanMethod(env, ((zjni_Object_t *)list)->object,
840 	    ((zjni_Collection_t *)list)->method_add, bean);
841 
842 	return (0);
843 }
844 
845 int
846 populate_DeviceStatsBean(JNIEnv *env, nvlist_t *vdev,
847     DeviceStatsBean_t *bean, zjni_Object_t *object)
848 {
849 	uint_t c;
850 	vdev_stat_t *vs;
851 
852 	int result = nvlist_lookup_uint64_array(
853 	    vdev, ZPOOL_CONFIG_STATS, (uint64_t **)&vs, &c);
854 	if (result != 0) {
855 		zjni_throw_exception(env,
856 		    "could not retrieve virtual device statistics");
857 		return (1);
858 	}
859 
860 	(*env)->CallVoidMethod(env, object->object,
861 	    bean->method_setUsed, (jlong)vs->vs_alloc);
862 
863 	(*env)->CallVoidMethod(env, object->object,
864 	    bean->method_setSize, (jlong)vs->vs_space);
865 
866 	(*env)->CallVoidMethod(env, object->object,
867 	    bean->method_setReadBytes, (jlong)vs->vs_bytes[ZIO_TYPE_READ]);
868 
869 	(*env)->CallVoidMethod(env, object->object,
870 	    bean->method_setWriteBytes, (jlong)vs->vs_bytes[ZIO_TYPE_WRITE]);
871 
872 	(*env)->CallVoidMethod(env, object->object,
873 	    bean->method_setReadOperations, (jlong)vs->vs_ops[ZIO_TYPE_READ]);
874 
875 	(*env)->CallVoidMethod(env, object->object,
876 	    bean->method_setWriteOperations, (jlong)vs->vs_ops[ZIO_TYPE_WRITE]);
877 
878 	(*env)->CallVoidMethod(env, object->object,
879 	    bean->method_setReadErrors, (jlong)vs->vs_read_errors);
880 
881 	(*env)->CallVoidMethod(env, object->object,
882 	    bean->method_setWriteErrors, (jlong)vs->vs_write_errors);
883 
884 	(*env)->CallVoidMethod(env, object->object,
885 	    bean->method_setChecksumErrors, (jlong)vs->vs_checksum_errors);
886 
887 	(*env)->CallVoidMethod(env, object->object,
888 	    bean->method_setDeviceState,
889 	    zjni_vdev_state_to_obj(env, vs->vs_state));
890 
891 	(*env)->CallVoidMethod(env, object->object,
892 	    bean->method_setDeviceStatus,
893 	    zjni_vdev_aux_to_obj(env, vs->vs_aux));
894 
895 	return (0);
896 }
897 
898 /*
899  * Converts a pool_state_t to a Java PoolStats$PoolState object.
900  */
901 jobject
902 zjni_pool_state_to_obj(JNIEnv *env, pool_state_t state)
903 {
904 	return (zjni_int_to_enum(env, state,
905 	    ZFSJNI_PACKAGE_DATA "PoolStats$PoolState",
906 	    "POOL_STATE_ACTIVE", pool_state_map));
907 }
908 
909 /*
910  * Converts a zpool_status_t to a Java PoolStats$PoolStatus object.
911  */
912 jobject
913 zjni_pool_status_to_obj(JNIEnv *env, zpool_status_t status)
914 {
915 	return (zjni_int_to_enum(env, status,
916 	    ZFSJNI_PACKAGE_DATA "PoolStats$PoolStatus",
917 	    "ZPOOL_STATUS_OK", zpool_status_map));
918 }
919 
920 /*
921  * Extern functions
922  */
923 
924 /*
925  * Iterates through each importable pool on the system.  For each
926  * importable pool, runs the given function with the given void as the
927  * last arg.
928  */
929 int
930 zjni_ipool_iter(int argc, char **argv, zjni_ipool_iter_f func, void *data)
931 {
932 	nvlist_t *pools = zpool_find_import(argc, argv);
933 
934 	if (pools != NULL) {
935 		nvpair_t *elem = NULL;
936 
937 		while ((elem = nvlist_next_nvpair(pools, elem)) != NULL) {
938 			nvlist_t *config;
939 
940 			if (nvpair_value_nvlist(elem, &config) != 0 ||
941 			    func(config, data)) {
942 				return (-1);
943 			}
944 		}
945 	}
946 
947 	return (0);
948 }
949 
950 char *
951 zjni_vdev_state_to_str(vdev_state_t state) {
952 	return (find_field(vdev_state_map, state));
953 }
954 
955 char *
956 zjni_vdev_aux_to_str(vdev_aux_t aux) {
957 	return (find_field(vdev_aux_map, aux));
958 }
959 
960 char *
961 zjni_pool_state_to_str(pool_state_t state) {
962 	return (find_field(pool_state_map, state));
963 }
964 
965 char *
966 zjni_pool_status_to_str(zpool_status_t status) {
967 	return (find_field(zpool_status_map, status));
968 }
969