8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / lib / libzfs_jni / common / libzfs_jni_pool.c
blobebc800af80aa8542a1b109dc9268b99502f56915
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
23 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
26 #include "libzfs_jni_util.h"
27 #include "libzfs_jni_pool.h"
28 #include <strings.h>
31 * Types
34 typedef struct ImportablePoolBean {
35 zjni_Object_t super;
36 PoolStatsBean_t interface_PoolStats;
38 jmethodID method_setName;
39 jmethodID method_setId;
40 } ImportablePoolBean_t;
42 typedef struct VirtualDeviceBean {
43 zjni_Object_t super;
44 DeviceStatsBean_t interface_DeviceStats;
46 jmethodID method_setPoolName;
47 jmethodID method_setParentIndex;
48 jmethodID method_setIndex;
49 } VirtualDeviceBean_t;
51 typedef struct LeafVirtualDeviceBean {
52 VirtualDeviceBean_t super;
54 jmethodID method_setName;
55 } LeafVirtualDeviceBean_t;
57 typedef struct DiskVirtualDeviceBean {
58 LeafVirtualDeviceBean_t super;
59 } DiskVirtualDeviceBean_t;
61 typedef struct SliceVirtualDeviceBean {
62 LeafVirtualDeviceBean_t super;
63 } SliceVirtualDeviceBean_t;
65 typedef struct FileVirtualDeviceBean {
66 LeafVirtualDeviceBean_t super;
67 } FileVirtualDeviceBean_t;
69 typedef struct RAIDVirtualDeviceBean {
70 VirtualDeviceBean_t super;
72 jmethodID method_setParity;
73 } RAIDVirtualDeviceBean_t;
75 typedef struct MirrorVirtualDeviceBean {
76 VirtualDeviceBean_t super;
77 } MirrorVirtualDeviceBean_t;
80 * Data
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 },
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 },
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 },
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 }
143 * Function prototypes
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);
186 * Static functions
189 /* Create a ImportablePoolBean */
190 static void
191 new_ImportablePoolBean(JNIEnv *env, ImportablePoolBean_t *bean)
193 zjni_Object_t *object = (zjni_Object_t *)bean;
195 if (object->object == NULL) {
196 object->class =
197 (*env)->FindClass(env,
198 ZFSJNI_PACKAGE_DATA "ImportablePoolBean");
200 object->constructor =
201 (*env)->GetMethodID(env, object->class, "<init>", "()V");
203 object->object =
204 (*env)->NewObject(env, object->class, object->constructor);
207 new_PoolStats(env, &(bean->interface_PoolStats), object);
209 bean->method_setName = (*env)->GetMethodID(
210 env, object->class, "setName", "(Ljava/lang/String;)V");
212 bean->method_setId = (*env)->GetMethodID(
213 env, object->class, "setId", "(J)V");
216 /* Create a VirtualDeviceBean */
217 static void
218 new_VirtualDevice(JNIEnv *env, VirtualDeviceBean_t *bean)
220 zjni_Object_t *object = (zjni_Object_t *)bean;
222 if (object->object == NULL) {
223 object->class =
224 (*env)->FindClass(env,
225 ZFSJNI_PACKAGE_DATA "VirtualDeviceBean");
227 object->constructor =
228 (*env)->GetMethodID(env, object->class, "<init>", "()V");
230 object->object =
231 (*env)->NewObject(env, object->class, object->constructor);
234 new_DeviceStats(env, &(bean->interface_DeviceStats), object);
236 bean->method_setPoolName = (*env)->GetMethodID(
237 env, object->class, "setPoolName", "(Ljava/lang/String;)V");
239 bean->method_setParentIndex = (*env)->GetMethodID(
240 env, object->class, "setParentIndex", "(Ljava/lang/Long;)V");
242 bean->method_setIndex = (*env)->GetMethodID(
243 env, object->class, "setIndex", "(J)V");
246 /* Create a LeafVirtualDeviceBean */
247 static void
248 new_LeafVirtualDevice(JNIEnv *env, LeafVirtualDeviceBean_t *bean)
250 zjni_Object_t *object = (zjni_Object_t *)bean;
252 if (object->object == NULL) {
253 object->class =
254 (*env)->FindClass(env,
255 ZFSJNI_PACKAGE_DATA "LeafVirtualDeviceBean");
257 object->constructor =
258 (*env)->GetMethodID(env, object->class, "<init>", "()V");
260 object->object =
261 (*env)->NewObject(env, object->class, object->constructor);
264 new_VirtualDevice(env, (VirtualDeviceBean_t *)bean);
266 bean->method_setName = (*env)->GetMethodID(
267 env, object->class, "setName", "(Ljava/lang/String;)V");
270 /* Create a DiskVirtualDeviceBean */
271 static void
272 new_DiskVirtualDeviceBean(JNIEnv *env, DiskVirtualDeviceBean_t *bean)
274 zjni_Object_t *object = (zjni_Object_t *)bean;
276 if (object->object == NULL) {
277 object->class = (*env)->FindClass(
278 env, ZFSJNI_PACKAGE_DATA "DiskVirtualDeviceBean");
280 object->constructor =
281 (*env)->GetMethodID(env, object->class, "<init>", "()V");
283 object->object =
284 (*env)->NewObject(env, object->class, object->constructor);
287 new_LeafVirtualDevice(env, (LeafVirtualDeviceBean_t *)bean);
290 /* Create a SliceVirtualDeviceBean */
291 static void
292 new_SliceVirtualDeviceBean(JNIEnv *env, SliceVirtualDeviceBean_t *bean)
294 zjni_Object_t *object = (zjni_Object_t *)bean;
296 if (object->object == NULL) {
297 object->class = (*env)->FindClass(
298 env, ZFSJNI_PACKAGE_DATA "SliceVirtualDeviceBean");
300 object->constructor =
301 (*env)->GetMethodID(env, object->class, "<init>", "()V");
303 object->object =
304 (*env)->NewObject(env, object->class, object->constructor);
307 new_LeafVirtualDevice(env, (LeafVirtualDeviceBean_t *)bean);
310 /* Create a FileVirtualDeviceBean */
311 static void
312 new_FileVirtualDeviceBean(JNIEnv *env, FileVirtualDeviceBean_t *bean)
314 zjni_Object_t *object = (zjni_Object_t *)bean;
316 if (object->object == NULL) {
317 object->class = (*env)->FindClass(
318 env, ZFSJNI_PACKAGE_DATA "FileVirtualDeviceBean");
320 object->constructor =
321 (*env)->GetMethodID(env, object->class, "<init>", "()V");
323 object->object =
324 (*env)->NewObject(env, object->class, object->constructor);
327 new_LeafVirtualDevice(env, (LeafVirtualDeviceBean_t *)bean);
330 /* Create a RAIDVirtualDeviceBean */
331 static void
332 new_RAIDVirtualDeviceBean(JNIEnv *env, RAIDVirtualDeviceBean_t *bean)
334 zjni_Object_t *object = (zjni_Object_t *)bean;
336 if (object->object == NULL) {
338 object->class = (*env)->FindClass(
339 env, ZFSJNI_PACKAGE_DATA "RAIDVirtualDeviceBean");
341 object->constructor =
342 (*env)->GetMethodID(env, object->class, "<init>", "()V");
344 object->object =
345 (*env)->NewObject(env, object->class, object->constructor);
348 new_VirtualDevice(env, (VirtualDeviceBean_t *)bean);
350 bean->method_setParity = (*env)->GetMethodID(
351 env, object->class, "setParity", "(J)V");
354 /* Create a MirrorVirtualDeviceBean */
355 static void
356 new_MirrorVirtualDeviceBean(JNIEnv *env, MirrorVirtualDeviceBean_t *bean)
358 zjni_Object_t *object = (zjni_Object_t *)bean;
360 if (object->object == NULL) {
361 object->class = (*env)->FindClass(
362 env, ZFSJNI_PACKAGE_DATA "MirrorVirtualDeviceBean");
364 object->constructor =
365 (*env)->GetMethodID(env, object->class, "<init>", "()V");
367 object->object =
368 (*env)->NewObject(env, object->class, object->constructor);
371 new_VirtualDevice(env, (VirtualDeviceBean_t *)bean);
374 static int
375 populate_ImportablePoolBean(JNIEnv *env, ImportablePoolBean_t *bean,
376 nvlist_t *config)
378 char *c;
379 char *name;
380 uint64_t guid;
381 uint64_t state;
382 uint64_t version;
383 nvlist_t *devices;
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;
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);
398 (*env)->CallVoidMethod(env, object->object,
399 bean->method_setName, (*env)->NewStringUTF(env, name));
401 (*env)->CallVoidMethod(env, object->object,
402 bean->method_setId, (jlong)guid);
404 (*env)->CallVoidMethod(env, object->object,
405 pool_stats->method_setPoolState,
406 zjni_pool_state_to_obj(env, (pool_state_t)state));
408 (*env)->CallVoidMethod(env, object->object,
409 pool_stats->method_setPoolStatus,
410 zjni_pool_status_to_obj(env, zpool_import_status(config, &c)));
412 (*env)->CallVoidMethod(env, object->object,
413 pool_stats->method_setPoolVersion, (jlong)version);
415 return (0);
418 static int
419 populate_VirtualDeviceBean(JNIEnv *env, zpool_handle_t *zhp,
420 nvlist_t *vdev, uint64_t *p_vdev_id, VirtualDeviceBean_t *bean)
422 int result;
423 uint64_t vdev_id;
424 jstring poolUTF;
426 zjni_Object_t *object = (zjni_Object_t *)bean;
427 DeviceStatsBean_t *stats = &(bean->interface_DeviceStats);
429 result = populate_DeviceStatsBean(env, vdev, stats, object);
430 if (result != 0) {
431 return (1);
434 /* Set pool name */
435 poolUTF = (*env)->NewStringUTF(env, zpool_get_name(zhp));
436 (*env)->CallVoidMethod(
437 env, object->object, bean->method_setPoolName, poolUTF);
439 /* Set parent vdev index */
440 (*env)->CallVoidMethod(
441 env, object->object, bean->method_setParentIndex,
442 p_vdev_id == NULL ? NULL :
443 zjni_long_to_Long(env, *p_vdev_id));
445 /* Get index */
446 result = nvlist_lookup_uint64(vdev, ZPOOL_CONFIG_GUID, &vdev_id);
447 if (result != 0) {
448 zjni_throw_exception(env,
449 "could not retrieve virtual device ID (pool %s)",
450 zpool_get_name(zhp));
451 return (1);
454 (*env)->CallVoidMethod(
455 env, object->object, bean->method_setIndex, (jlong)vdev_id);
457 return (0);
460 static int
461 populate_LeafVirtualDeviceBean(JNIEnv *env, zpool_handle_t *zhp,
462 nvlist_t *vdev, uint64_t *p_vdev_id, LeafVirtualDeviceBean_t *bean)
464 return (populate_VirtualDeviceBean(
465 env, zhp, vdev, p_vdev_id, (VirtualDeviceBean_t *)bean));
468 static int
469 populate_DiskVirtualDeviceBean(JNIEnv *env, zpool_handle_t *zhp,
470 nvlist_t *vdev, uint64_t *p_vdev_id, DiskVirtualDeviceBean_t *bean)
472 char *path;
473 int result = populate_LeafVirtualDeviceBean(
474 env, zhp, vdev, p_vdev_id, (LeafVirtualDeviceBean_t *)bean);
476 if (result) {
477 /* Must not call any more Java methods to preserve exception */
478 return (-1);
481 /* Set path */
482 result = nvlist_lookup_string(vdev, ZPOOL_CONFIG_PATH, &path);
483 if (result != 0) {
484 zjni_throw_exception(env,
485 "could not retrieve path from disk virtual device "
486 "(pool %s)", zpool_get_name(zhp));
487 } else {
489 regex_t re;
490 regmatch_t matches[2];
491 jstring pathUTF = NULL;
493 /* Strip off slice portion of name, if applicable */
494 if (regcomp(&re, "^(/dev/dsk/.*)s[0-9]+$", REG_EXTENDED) == 0) {
495 if (regexec(&re, path, 2, matches, 0) == 0) {
496 regmatch_t *match = matches + 1;
497 if (match->rm_so != -1 && match->rm_eo != -1) {
498 char *tmp = strdup(path);
499 if (tmp != NULL) {
500 char *end = tmp + match->rm_eo;
501 *end = '\0';
502 pathUTF = (*env)->NewStringUTF(
503 env, tmp);
504 free(tmp);
508 regfree(&re);
510 if (regcomp(&re, "^(/dev/dsk/.*)s[0-9]+/old$", REG_EXTENDED) ==
511 0) {
512 if (regexec(&re, path, 2, matches, 0) == 0) {
513 regmatch_t *match = matches + 1;
514 if (match->rm_so != -1 && match->rm_eo != -1) {
515 char *tmp = strdup(path);
516 if (tmp != NULL) {
517 (void) strcpy(tmp +
518 match->rm_eo, "/old");
519 pathUTF = (*env)->NewStringUTF(
520 env, tmp);
521 free(tmp);
525 regfree(&re);
528 if (pathUTF == NULL) {
529 pathUTF = (*env)->NewStringUTF(env, path);
532 (*env)->CallVoidMethod(env, ((zjni_Object_t *)bean)->object,
533 ((LeafVirtualDeviceBean_t *)bean)->method_setName, pathUTF);
536 return (result != 0);
539 static int
540 populate_SliceVirtualDeviceBean(JNIEnv *env, zpool_handle_t *zhp,
541 nvlist_t *vdev, uint64_t *p_vdev_id, SliceVirtualDeviceBean_t *bean)
543 char *path;
544 int result = populate_LeafVirtualDeviceBean(
545 env, zhp, vdev, p_vdev_id, (LeafVirtualDeviceBean_t *)bean);
547 if (result) {
548 /* Must not call any more Java methods to preserve exception */
549 return (-1);
552 /* Set path */
553 result = nvlist_lookup_string(vdev, ZPOOL_CONFIG_PATH, &path);
554 if (result != 0) {
555 zjni_throw_exception(env,
556 "could not retrieve path from slice virtual device (pool "
557 "%s)", zpool_get_name(zhp));
558 } else {
560 jstring pathUTF = (*env)->NewStringUTF(env, path);
561 (*env)->CallVoidMethod(env, ((zjni_Object_t *)bean)->object,
562 ((LeafVirtualDeviceBean_t *)bean)->method_setName,
563 pathUTF);
566 return (result != 0);
569 static int
570 populate_FileVirtualDeviceBean(JNIEnv *env, zpool_handle_t *zhp,
571 nvlist_t *vdev, uint64_t *p_vdev_id, FileVirtualDeviceBean_t *bean)
573 char *path;
574 int result = populate_LeafVirtualDeviceBean(
575 env, zhp, vdev, p_vdev_id, (LeafVirtualDeviceBean_t *)bean);
577 if (result) {
578 /* Must not call any more Java methods to preserve exception */
579 return (-1);
582 /* Set path */
583 result = nvlist_lookup_string(vdev, ZPOOL_CONFIG_PATH, &path);
584 if (result != 0) {
585 zjni_throw_exception(env,
586 "could not retrieve path from disk virtual device "
587 "(pool %s)", zpool_get_name(zhp));
588 } else {
590 jstring pathUTF = (*env)->NewStringUTF(env, path);
591 (*env)->CallVoidMethod(env, ((zjni_Object_t *)bean)->object,
592 ((LeafVirtualDeviceBean_t *)bean)->method_setName, pathUTF);
595 return (result != 0);
598 static int
599 populate_RAIDVirtualDeviceBean(JNIEnv *env, zpool_handle_t *zhp,
600 nvlist_t *vdev, uint64_t *p_vdev_id, RAIDVirtualDeviceBean_t *bean)
602 return (populate_VirtualDeviceBean(env, zhp, vdev, p_vdev_id,
603 (VirtualDeviceBean_t *)bean));
606 static int
607 populate_MirrorVirtualDeviceBean(JNIEnv *env, zpool_handle_t *zhp,
608 nvlist_t *vdev, uint64_t *p_vdev_id, MirrorVirtualDeviceBean_t *bean)
610 return (populate_VirtualDeviceBean(env, zhp, vdev, p_vdev_id,
611 (VirtualDeviceBean_t *)bean));
614 static jobject
615 create_ImportablePoolBean(JNIEnv *env, nvlist_t *config)
617 int result;
618 ImportablePoolBean_t bean_obj = {0};
619 ImportablePoolBean_t *bean = &bean_obj;
621 /* Construct ImportablePoolBean */
622 new_ImportablePoolBean(env, bean);
624 result = populate_ImportablePoolBean(env, bean, config);
625 if (result) {
626 /* Must not call any more Java methods to preserve exception */
627 return (NULL);
630 return (((zjni_Object_t *)bean)->object);
633 static jobject
634 create_DiskVirtualDeviceBean(JNIEnv *env, zpool_handle_t *zhp,
635 nvlist_t *vdev, uint64_t *p_vdev_id)
637 int result;
638 DiskVirtualDeviceBean_t bean_obj = {0};
639 DiskVirtualDeviceBean_t *bean = &bean_obj;
641 /* Construct DiskVirtualDeviceBean */
642 new_DiskVirtualDeviceBean(env, bean);
644 result = populate_DiskVirtualDeviceBean(
645 env, zhp, vdev, p_vdev_id, bean);
646 if (result) {
647 /* Must not call any more Java methods to preserve exception */
648 return (NULL);
651 return (((zjni_Object_t *)bean)->object);
654 static jobject
655 create_SliceVirtualDeviceBean(JNIEnv *env, zpool_handle_t *zhp,
656 nvlist_t *vdev, uint64_t *p_vdev_id)
658 int result;
659 SliceVirtualDeviceBean_t bean_obj = {0};
660 SliceVirtualDeviceBean_t *bean = &bean_obj;
662 /* Construct SliceVirtualDeviceBean */
663 new_SliceVirtualDeviceBean(env, bean);
665 result = populate_SliceVirtualDeviceBean(
666 env, zhp, vdev, p_vdev_id, bean);
667 if (result) {
668 /* Must not call any more Java methods to preserve exception */
669 return (NULL);
672 return (((zjni_Object_t *)bean)->object);
675 static jobject
676 create_FileVirtualDeviceBean(JNIEnv *env, zpool_handle_t *zhp,
677 nvlist_t *vdev, uint64_t *p_vdev_id)
679 int result;
680 FileVirtualDeviceBean_t bean_obj = {0};
681 FileVirtualDeviceBean_t *bean = &bean_obj;
683 /* Construct FileVirtualDeviceBean */
684 new_FileVirtualDeviceBean(env, bean);
686 result = populate_FileVirtualDeviceBean(
687 env, zhp, vdev, p_vdev_id, bean);
688 if (result) {
689 /* Must not call any more Java methods to preserve exception */
690 return (NULL);
693 return (((zjni_Object_t *)bean)->object);
696 static jobject
697 create_RAIDVirtualDeviceBean(JNIEnv *env, zpool_handle_t *zhp,
698 nvlist_t *vdev, uint64_t *p_vdev_id)
700 int result;
701 uint64_t parity;
702 RAIDVirtualDeviceBean_t bean_obj = {0};
703 RAIDVirtualDeviceBean_t *bean = &bean_obj;
705 ((zjni_Object_t *)bean)->object = NULL;
707 /* Construct RAIDVirtualDeviceBean */
708 new_RAIDVirtualDeviceBean(env, bean);
710 /* Set parity bit */
711 result = nvlist_lookup_uint64(vdev, ZPOOL_CONFIG_NPARITY,
712 &parity);
713 if (result) {
714 /* Default to RAID-Z1 in case of error */
715 parity = 1;
718 (*env)->CallVoidMethod(
719 env, ((zjni_Object_t *)bean)->object, bean->method_setParity,
720 (jlong)parity);
723 result = populate_RAIDVirtualDeviceBean(
724 env, zhp, vdev, p_vdev_id, bean);
725 if (result) {
726 /* Must not call any more Java methods to preserve exception */
727 return (NULL);
730 return (((zjni_Object_t *)bean)->object);
733 static jobject
734 create_MirrorVirtualDeviceBean(JNIEnv *env, zpool_handle_t *zhp,
735 nvlist_t *vdev, uint64_t *p_vdev_id)
737 int result;
738 MirrorVirtualDeviceBean_t bean_obj = {0};
739 MirrorVirtualDeviceBean_t *bean = &bean_obj;
741 /* Construct MirrorVirtualDeviceBean */
742 new_MirrorVirtualDeviceBean(env, bean);
744 result = populate_MirrorVirtualDeviceBean(
745 env, zhp, vdev, p_vdev_id, bean);
746 if (result) {
747 /* Must not call any more Java methods to preserve exception */
748 return (NULL);
751 return (((zjni_Object_t *)bean)->object);
754 static char *
755 find_field(const zjni_field_mapping_t *mapping, int value) {
756 int i;
757 for (i = 0; mapping[i].name != NULL; i++) {
758 if (value == mapping[i].value) {
759 return (mapping[i].name);
762 return (NULL);
766 * Converts a vdev_state_t to a Java DeviceStats$DeviceState object.
768 static jobject
769 zjni_vdev_state_to_obj(JNIEnv *env, vdev_state_t state)
771 return (zjni_int_to_enum(env, state,
772 ZFSJNI_PACKAGE_DATA "DeviceStats$DeviceState",
773 "VDEV_STATE_UNKNOWN", vdev_state_map));
777 * Converts a vdev_aux_t to a Java DeviceStats$DeviceStatus object.
779 static jobject
780 zjni_vdev_aux_to_obj(JNIEnv *env, vdev_aux_t aux)
782 return (zjni_int_to_enum(env, aux,
783 ZFSJNI_PACKAGE_DATA "DeviceStats$DeviceStatus",
784 "VDEV_AUX_NONE", vdev_aux_map));
788 * Package-private functions
791 /* Create a DeviceStatsBean */
792 void
793 new_DeviceStats(JNIEnv *env, DeviceStatsBean_t *bean, zjni_Object_t *object)
795 bean->method_setSize = (*env)->GetMethodID(
796 env, object->class, "setSize", "(J)V");
798 bean->method_setReplacementSize = (*env)->GetMethodID(
799 env, object->class, "setReplacementSize", "(J)V");
801 bean->method_setUsed = (*env)->GetMethodID(
802 env, object->class, "setUsed", "(J)V");
804 bean->method_setReadBytes = (*env)->GetMethodID(
805 env, object->class, "setReadBytes", "(J)V");
807 bean->method_setWriteBytes = (*env)->GetMethodID(
808 env, object->class, "setWriteBytes", "(J)V");
810 bean->method_setReadOperations = (*env)->GetMethodID(
811 env, object->class, "setReadOperations", "(J)V");
813 bean->method_setWriteOperations = (*env)->GetMethodID(
814 env, object->class, "setWriteOperations", "(J)V");
816 bean->method_setReadErrors = (*env)->GetMethodID(
817 env, object->class, "setReadErrors", "(J)V");
819 bean->method_setWriteErrors = (*env)->GetMethodID(
820 env, object->class, "setWriteErrors", "(J)V");
822 bean->method_setChecksumErrors = (*env)->GetMethodID(
823 env, object->class, "setChecksumErrors", "(J)V");
825 bean->method_setDeviceState = (*env)->GetMethodID(
826 env, object->class, "setDeviceState",
827 "(L" ZFSJNI_PACKAGE_DATA "DeviceStats$DeviceState;)V");
829 bean->method_setDeviceStatus = (*env)->GetMethodID(
830 env, object->class, "setDeviceStatus",
831 "(L" ZFSJNI_PACKAGE_DATA "DeviceStats$DeviceStatus;)V");
834 /* Create a PoolStatsBean */
835 void
836 new_PoolStats(JNIEnv *env, PoolStatsBean_t *bean, zjni_Object_t *object)
838 new_DeviceStats(env, (DeviceStatsBean_t *)bean, object);
840 bean->method_setPoolState = (*env)->GetMethodID(
841 env, object->class, "setPoolState",
842 "(L" ZFSJNI_PACKAGE_DATA "PoolStats$PoolState;)V");
844 bean->method_setPoolStatus = (*env)->GetMethodID(
845 env, object->class, "setPoolStatus",
846 "(L" ZFSJNI_PACKAGE_DATA "PoolStats$PoolStatus;)V");
848 bean->method_setPoolVersion = (*env)->GetMethodID(
849 env, object->class, "setPoolVersion", "(J)V");
853 * Gets the root vdev (an nvlist_t *) for the given pool.
855 nvlist_t *
856 zjni_get_root_vdev(zpool_handle_t *zhp)
858 nvlist_t *root = NULL;
860 if (zhp != NULL) {
861 nvlist_t *attrs = zpool_get_config(zhp, NULL);
863 if (attrs != NULL) {
864 int result = nvlist_lookup_nvlist(
865 attrs, ZPOOL_CONFIG_VDEV_TREE, &root);
866 if (result != 0) {
867 root = NULL;
872 return (root);
876 * Gets the vdev (an nvlist_t *) with the given vdev_id, below the
877 * given vdev. If the given vdev is NULL, all vdevs within the given
878 * pool are searched.
880 * If p_vdev_id is not NULL, it will be set to the ID of the parent
881 * vdev, if any, or to vdev_id_to_find if the searched-for vdev is a
882 * toplevel vdev.
884 nvlist_t *
885 zjni_get_vdev(zpool_handle_t *zhp, nvlist_t *vdev_parent,
886 uint64_t vdev_id_to_find, uint64_t *p_vdev_id)
888 int result;
889 uint64_t id = vdev_id_to_find;
891 /* Was a vdev specified? */
892 if (vdev_parent == NULL) {
893 /* No -- retrieve the top-level pool vdev */
894 vdev_parent = zjni_get_root_vdev(zhp);
895 } else {
896 /* Get index of this vdev and compare with vdev_id_to_find */
897 result = nvlist_lookup_uint64(
898 vdev_parent, ZPOOL_CONFIG_GUID, &id);
899 if (result == 0 && id == vdev_id_to_find) {
900 return (vdev_parent);
904 if (vdev_parent != NULL) {
906 nvlist_t **children;
907 uint_t nelem = 0;
909 /* Get the vdevs under this vdev */
910 result = nvlist_lookup_nvlist_array(
911 vdev_parent, ZPOOL_CONFIG_CHILDREN, &children, &nelem);
913 if (result == 0) {
915 int i;
916 nvlist_t *child;
918 /* For each vdev child... */
919 for (i = 0; i < nelem; i++) {
920 if (p_vdev_id != NULL) {
921 /* Save parent vdev id */
922 *p_vdev_id = id;
925 child = zjni_get_vdev(zhp, children[i],
926 vdev_id_to_find, p_vdev_id);
927 if (child != NULL) {
928 return (child);
934 return (NULL);
937 jobject
938 zjni_get_VirtualDevice_from_vdev(JNIEnv *env, zpool_handle_t *zhp,
939 nvlist_t *vdev, uint64_t *p_vdev_id)
941 jobject obj = NULL;
942 char *type = NULL;
943 int result = nvlist_lookup_string(vdev, ZPOOL_CONFIG_TYPE, &type);
945 if (result == 0) {
946 if (strcmp(type, VDEV_TYPE_DISK) == 0) {
947 uint64_t wholedisk;
948 if (nvlist_lookup_uint64(vdev, ZPOOL_CONFIG_WHOLE_DISK,
949 &wholedisk) == 0 && wholedisk) {
950 obj = create_DiskVirtualDeviceBean(
951 env, zhp, vdev, p_vdev_id);
952 } else {
953 obj = create_SliceVirtualDeviceBean(
954 env, zhp, vdev, p_vdev_id);
956 } else if (strcmp(type, VDEV_TYPE_FILE) == 0) {
957 obj = create_FileVirtualDeviceBean(
958 env, zhp, vdev, p_vdev_id);
959 } else if (strcmp(type, VDEV_TYPE_RAIDZ) == 0) {
960 obj = create_RAIDVirtualDeviceBean(
961 env, zhp, vdev, p_vdev_id);
962 } else if (strcmp(type, VDEV_TYPE_MIRROR) == 0) {
963 obj = create_MirrorVirtualDeviceBean(
964 env, zhp, vdev, p_vdev_id);
965 } else if (strcmp(type, VDEV_TYPE_REPLACING) == 0) {
967 /* Get the vdevs under this vdev */
968 nvlist_t **children;
969 uint_t nelem = 0;
970 int result = nvlist_lookup_nvlist_array(
971 vdev, ZPOOL_CONFIG_CHILDREN, &children, &nelem);
973 if (result == 0 && nelem > 0) {
975 /* Get last vdev child (replacement device) */
976 nvlist_t *child = children[nelem - 1];
978 obj = zjni_get_VirtualDevice_from_vdev(env,
979 zhp, child, p_vdev_id);
984 return (obj);
987 jobject
988 zjni_get_VirtualDevices_from_vdev(JNIEnv *env, zpool_handle_t *zhp,
989 nvlist_t *vdev_parent, uint64_t *p_vdev_id)
991 /* Create an array list for the vdevs */
992 zjni_ArrayList_t list_class = {0};
993 zjni_ArrayList_t *list_class_p = &list_class;
994 zjni_new_ArrayList(env, list_class_p);
996 /* Was a vdev specified? */
997 if (vdev_parent == NULL) {
998 /* No -- retrieve the top-level pool vdev */
999 vdev_parent = zjni_get_root_vdev(zhp);
1002 if (vdev_parent != NULL) {
1004 /* Get the vdevs under this vdev */
1005 nvlist_t **children;
1006 uint_t nelem = 0;
1007 int result = nvlist_lookup_nvlist_array(
1008 vdev_parent, ZPOOL_CONFIG_CHILDREN, &children, &nelem);
1010 if (result == 0) {
1012 /* For each vdev child... */
1013 int i;
1014 for (i = 0; i < nelem; i++) {
1015 nvlist_t *child = children[i];
1017 /* Create a Java object from this vdev */
1018 jobject obj =
1019 zjni_get_VirtualDevice_from_vdev(env,
1020 zhp, child, p_vdev_id);
1022 if ((*env)->ExceptionOccurred(env) != NULL) {
1024 * Must not call any more Java methods
1025 * to preserve exception
1027 return (NULL);
1030 if (obj != NULL) {
1031 /* Add child to child vdev list */
1032 (*env)->CallBooleanMethod(env,
1033 ((zjni_Object_t *)
1034 list_class_p)->object,
1035 ((zjni_Collection_t *)
1036 list_class_p)->method_add, obj);
1042 return (zjni_Collection_to_array(
1043 env, (zjni_Collection_t *)list_class_p,
1044 ZFSJNI_PACKAGE_DATA "VirtualDevice"));
1048 zjni_create_add_ImportablePool(nvlist_t *config, void *data) {
1050 JNIEnv *env = ((zjni_ArrayCallbackData_t *)data)->env;
1051 zjni_Collection_t *list = ((zjni_ArrayCallbackData_t *)data)->list;
1053 /* Construct ImportablePool object */
1054 jobject bean = create_ImportablePoolBean(env, config);
1055 if (bean == NULL) {
1056 return (-1);
1059 /* Add bean to list */
1060 (*env)->CallBooleanMethod(env, ((zjni_Object_t *)list)->object,
1061 ((zjni_Collection_t *)list)->method_add, bean);
1063 return (0);
1067 populate_DeviceStatsBean(JNIEnv *env, nvlist_t *vdev,
1068 DeviceStatsBean_t *bean, zjni_Object_t *object)
1070 uint_t c;
1071 vdev_stat_t *vs;
1073 int result = nvlist_lookup_uint64_array(
1074 vdev, ZPOOL_CONFIG_VDEV_STATS, (uint64_t **)&vs, &c);
1075 if (result != 0) {
1076 zjni_throw_exception(env,
1077 "could not retrieve virtual device statistics");
1078 return (1);
1081 (*env)->CallVoidMethod(env, object->object,
1082 bean->method_setUsed, (jlong)vs->vs_alloc);
1084 (*env)->CallVoidMethod(env, object->object,
1085 bean->method_setSize, (jlong)vs->vs_space);
1087 (*env)->CallVoidMethod(env, object->object,
1088 bean->method_setReplacementSize, (jlong)vs->vs_rsize);
1090 (*env)->CallVoidMethod(env, object->object,
1091 bean->method_setReadBytes, (jlong)vs->vs_bytes[ZIO_TYPE_READ]);
1093 (*env)->CallVoidMethod(env, object->object,
1094 bean->method_setWriteBytes, (jlong)vs->vs_bytes[ZIO_TYPE_WRITE]);
1096 (*env)->CallVoidMethod(env, object->object,
1097 bean->method_setReadOperations, (jlong)vs->vs_ops[ZIO_TYPE_READ]);
1099 (*env)->CallVoidMethod(env, object->object,
1100 bean->method_setWriteOperations, (jlong)vs->vs_ops[ZIO_TYPE_WRITE]);
1102 (*env)->CallVoidMethod(env, object->object,
1103 bean->method_setReadErrors, (jlong)vs->vs_read_errors);
1105 (*env)->CallVoidMethod(env, object->object,
1106 bean->method_setWriteErrors, (jlong)vs->vs_write_errors);
1108 (*env)->CallVoidMethod(env, object->object,
1109 bean->method_setChecksumErrors, (jlong)vs->vs_checksum_errors);
1111 (*env)->CallVoidMethod(env, object->object,
1112 bean->method_setDeviceState,
1113 zjni_vdev_state_to_obj(env, vs->vs_state));
1115 (*env)->CallVoidMethod(env, object->object,
1116 bean->method_setDeviceStatus,
1117 zjni_vdev_aux_to_obj(env, vs->vs_aux));
1119 return (0);
1123 * Converts a pool_state_t to a Java PoolStats$PoolState object.
1125 jobject
1126 zjni_pool_state_to_obj(JNIEnv *env, pool_state_t state)
1128 return (zjni_int_to_enum(env, state,
1129 ZFSJNI_PACKAGE_DATA "PoolStats$PoolState",
1130 "POOL_STATE_ACTIVE", pool_state_map));
1134 * Converts a zpool_status_t to a Java PoolStats$PoolStatus object.
1136 jobject
1137 zjni_pool_status_to_obj(JNIEnv *env, zpool_status_t status)
1139 return (zjni_int_to_enum(env, status,
1140 ZFSJNI_PACKAGE_DATA "PoolStats$PoolStatus",
1141 "ZPOOL_STATUS_OK", zpool_status_map));
1145 * Extern functions
1149 * Iterates through each importable pool on the system. For each
1150 * importable pool, runs the given function with the given void as the
1151 * last arg.
1154 zjni_ipool_iter(int argc, char **argv, zjni_ipool_iter_f func, void *data)
1156 nvlist_t *pools = zpool_find_import(g_zfs, argc, argv);
1158 if (pools != NULL) {
1159 nvpair_t *elem = NULL;
1161 while ((elem = nvlist_next_nvpair(pools, elem)) != NULL) {
1162 nvlist_t *config;
1164 if (nvpair_value_nvlist(elem, &config) != 0 ||
1165 func(config, data)) {
1166 return (-1);
1171 return (0);
1174 char *
1175 zjni_vdev_state_to_str(vdev_state_t state) {
1176 return (find_field(vdev_state_map, state));
1179 char *
1180 zjni_vdev_aux_to_str(vdev_aux_t aux) {
1181 return (find_field(vdev_aux_map, aux));
1184 char *
1185 zjni_pool_state_to_str(pool_state_t state) {
1186 return (find_field(pool_state_map, state));
1189 char *
1190 zjni_pool_status_to_str(zpool_status_t status) {
1191 return (find_field(zpool_status_map, status));