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]
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"
34 typedef struct ImportablePoolBean
{
36 PoolStatsBean_t interface_PoolStats
;
38 jmethodID method_setName
;
39 jmethodID method_setId
;
40 } ImportablePoolBean_t
;
42 typedef struct VirtualDeviceBean
{
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
;
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" },
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" },
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" },
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" },
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
);
189 /* Create a ImportablePoolBean */
191 new_ImportablePoolBean(JNIEnv
*env
, ImportablePoolBean_t
*bean
)
193 zjni_Object_t
*object
= (zjni_Object_t
*)bean
;
195 if (object
->object
== NULL
) {
197 (*env
)->FindClass(env
,
198 ZFSJNI_PACKAGE_DATA
"ImportablePoolBean");
200 object
->constructor
=
201 (*env
)->GetMethodID(env
, object
->class, "<init>", "()V");
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 */
218 new_VirtualDevice(JNIEnv
*env
, VirtualDeviceBean_t
*bean
)
220 zjni_Object_t
*object
= (zjni_Object_t
*)bean
;
222 if (object
->object
== NULL
) {
224 (*env
)->FindClass(env
,
225 ZFSJNI_PACKAGE_DATA
"VirtualDeviceBean");
227 object
->constructor
=
228 (*env
)->GetMethodID(env
, object
->class, "<init>", "()V");
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 */
248 new_LeafVirtualDevice(JNIEnv
*env
, LeafVirtualDeviceBean_t
*bean
)
250 zjni_Object_t
*object
= (zjni_Object_t
*)bean
;
252 if (object
->object
== NULL
) {
254 (*env
)->FindClass(env
,
255 ZFSJNI_PACKAGE_DATA
"LeafVirtualDeviceBean");
257 object
->constructor
=
258 (*env
)->GetMethodID(env
, object
->class, "<init>", "()V");
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 */
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");
284 (*env
)->NewObject(env
, object
->class, object
->constructor
);
287 new_LeafVirtualDevice(env
, (LeafVirtualDeviceBean_t
*)bean
);
290 /* Create a SliceVirtualDeviceBean */
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");
304 (*env
)->NewObject(env
, object
->class, object
->constructor
);
307 new_LeafVirtualDevice(env
, (LeafVirtualDeviceBean_t
*)bean
);
310 /* Create a FileVirtualDeviceBean */
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");
324 (*env
)->NewObject(env
, object
->class, object
->constructor
);
327 new_LeafVirtualDevice(env
, (LeafVirtualDeviceBean_t
*)bean
);
330 /* Create a RAIDVirtualDeviceBean */
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");
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 */
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");
368 (*env
)->NewObject(env
, object
->class, object
->constructor
);
371 new_VirtualDevice(env
, (VirtualDeviceBean_t
*)bean
);
375 populate_ImportablePoolBean(JNIEnv
*env
, ImportablePoolBean_t
*bean
,
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
)) {
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
);
419 populate_VirtualDeviceBean(JNIEnv
*env
, zpool_handle_t
*zhp
,
420 nvlist_t
*vdev
, uint64_t *p_vdev_id
, VirtualDeviceBean_t
*bean
)
426 zjni_Object_t
*object
= (zjni_Object_t
*)bean
;
427 DeviceStatsBean_t
*stats
= &(bean
->interface_DeviceStats
);
429 result
= populate_DeviceStatsBean(env
, vdev
, stats
, object
);
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
));
446 result
= nvlist_lookup_uint64(vdev
, ZPOOL_CONFIG_GUID
, &vdev_id
);
448 zjni_throw_exception(env
,
449 "could not retrieve virtual device ID (pool %s)",
450 zpool_get_name(zhp
));
454 (*env
)->CallVoidMethod(
455 env
, object
->object
, bean
->method_setIndex
, (jlong
)vdev_id
);
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
));
469 populate_DiskVirtualDeviceBean(JNIEnv
*env
, zpool_handle_t
*zhp
,
470 nvlist_t
*vdev
, uint64_t *p_vdev_id
, DiskVirtualDeviceBean_t
*bean
)
473 int result
= populate_LeafVirtualDeviceBean(
474 env
, zhp
, vdev
, p_vdev_id
, (LeafVirtualDeviceBean_t
*)bean
);
477 /* Must not call any more Java methods to preserve exception */
482 result
= nvlist_lookup_string(vdev
, ZPOOL_CONFIG_PATH
, &path
);
484 zjni_throw_exception(env
,
485 "could not retrieve path from disk virtual device "
486 "(pool %s)", zpool_get_name(zhp
));
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
);
500 char *end
= tmp
+ match
->rm_eo
;
502 pathUTF
= (*env
)->NewStringUTF(
510 if (regcomp(&re
, "^(/dev/dsk/.*)s[0-9]+/old$", REG_EXTENDED
) ==
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
);
518 match
->rm_eo
, "/old");
519 pathUTF
= (*env
)->NewStringUTF(
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);
540 populate_SliceVirtualDeviceBean(JNIEnv
*env
, zpool_handle_t
*zhp
,
541 nvlist_t
*vdev
, uint64_t *p_vdev_id
, SliceVirtualDeviceBean_t
*bean
)
544 int result
= populate_LeafVirtualDeviceBean(
545 env
, zhp
, vdev
, p_vdev_id
, (LeafVirtualDeviceBean_t
*)bean
);
548 /* Must not call any more Java methods to preserve exception */
553 result
= nvlist_lookup_string(vdev
, ZPOOL_CONFIG_PATH
, &path
);
555 zjni_throw_exception(env
,
556 "could not retrieve path from slice virtual device (pool "
557 "%s)", zpool_get_name(zhp
));
560 jstring pathUTF
= (*env
)->NewStringUTF(env
, path
);
561 (*env
)->CallVoidMethod(env
, ((zjni_Object_t
*)bean
)->object
,
562 ((LeafVirtualDeviceBean_t
*)bean
)->method_setName
,
566 return (result
!= 0);
570 populate_FileVirtualDeviceBean(JNIEnv
*env
, zpool_handle_t
*zhp
,
571 nvlist_t
*vdev
, uint64_t *p_vdev_id
, FileVirtualDeviceBean_t
*bean
)
574 int result
= populate_LeafVirtualDeviceBean(
575 env
, zhp
, vdev
, p_vdev_id
, (LeafVirtualDeviceBean_t
*)bean
);
578 /* Must not call any more Java methods to preserve exception */
583 result
= nvlist_lookup_string(vdev
, ZPOOL_CONFIG_PATH
, &path
);
585 zjni_throw_exception(env
,
586 "could not retrieve path from disk virtual device "
587 "(pool %s)", zpool_get_name(zhp
));
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);
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
));
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
));
615 create_ImportablePoolBean(JNIEnv
*env
, nvlist_t
*config
)
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
);
626 /* Must not call any more Java methods to preserve exception */
630 return (((zjni_Object_t
*)bean
)->object
);
634 create_DiskVirtualDeviceBean(JNIEnv
*env
, zpool_handle_t
*zhp
,
635 nvlist_t
*vdev
, uint64_t *p_vdev_id
)
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
);
647 /* Must not call any more Java methods to preserve exception */
651 return (((zjni_Object_t
*)bean
)->object
);
655 create_SliceVirtualDeviceBean(JNIEnv
*env
, zpool_handle_t
*zhp
,
656 nvlist_t
*vdev
, uint64_t *p_vdev_id
)
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
);
668 /* Must not call any more Java methods to preserve exception */
672 return (((zjni_Object_t
*)bean
)->object
);
676 create_FileVirtualDeviceBean(JNIEnv
*env
, zpool_handle_t
*zhp
,
677 nvlist_t
*vdev
, uint64_t *p_vdev_id
)
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
);
689 /* Must not call any more Java methods to preserve exception */
693 return (((zjni_Object_t
*)bean
)->object
);
697 create_RAIDVirtualDeviceBean(JNIEnv
*env
, zpool_handle_t
*zhp
,
698 nvlist_t
*vdev
, uint64_t *p_vdev_id
)
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
);
711 result
= nvlist_lookup_uint64(vdev
, ZPOOL_CONFIG_NPARITY
,
714 /* Default to RAID-Z1 in case of error */
718 (*env
)->CallVoidMethod(
719 env
, ((zjni_Object_t
*)bean
)->object
, bean
->method_setParity
,
723 result
= populate_RAIDVirtualDeviceBean(
724 env
, zhp
, vdev
, p_vdev_id
, bean
);
726 /* Must not call any more Java methods to preserve exception */
730 return (((zjni_Object_t
*)bean
)->object
);
734 create_MirrorVirtualDeviceBean(JNIEnv
*env
, zpool_handle_t
*zhp
,
735 nvlist_t
*vdev
, uint64_t *p_vdev_id
)
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
);
747 /* Must not call any more Java methods to preserve exception */
751 return (((zjni_Object_t
*)bean
)->object
);
755 find_field(const zjni_field_mapping_t
*mapping
, int value
) {
757 for (i
= 0; mapping
[i
].name
!= NULL
; i
++) {
758 if (value
== mapping
[i
].value
) {
759 return (mapping
[i
].name
);
766 * Converts a vdev_state_t to a Java DeviceStats$DeviceState object.
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.
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 */
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 */
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.
856 zjni_get_root_vdev(zpool_handle_t
*zhp
)
858 nvlist_t
*root
= NULL
;
861 nvlist_t
*attrs
= zpool_get_config(zhp
, NULL
);
864 int result
= nvlist_lookup_nvlist(
865 attrs
, ZPOOL_CONFIG_VDEV_TREE
, &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
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
885 zjni_get_vdev(zpool_handle_t
*zhp
, nvlist_t
*vdev_parent
,
886 uint64_t vdev_id_to_find
, uint64_t *p_vdev_id
)
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
);
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
) {
909 /* Get the vdevs under this vdev */
910 result
= nvlist_lookup_nvlist_array(
911 vdev_parent
, ZPOOL_CONFIG_CHILDREN
, &children
, &nelem
);
918 /* For each vdev child... */
919 for (i
= 0; i
< nelem
; i
++) {
920 if (p_vdev_id
!= NULL
) {
921 /* Save parent vdev id */
925 child
= zjni_get_vdev(zhp
, children
[i
],
926 vdev_id_to_find
, p_vdev_id
);
938 zjni_get_VirtualDevice_from_vdev(JNIEnv
*env
, zpool_handle_t
*zhp
,
939 nvlist_t
*vdev
, uint64_t *p_vdev_id
)
943 int result
= nvlist_lookup_string(vdev
, ZPOOL_CONFIG_TYPE
, &type
);
946 if (strcmp(type
, VDEV_TYPE_DISK
) == 0) {
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
);
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 */
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
);
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
;
1007 int result
= nvlist_lookup_nvlist_array(
1008 vdev_parent
, ZPOOL_CONFIG_CHILDREN
, &children
, &nelem
);
1012 /* For each vdev child... */
1014 for (i
= 0; i
< nelem
; i
++) {
1015 nvlist_t
*child
= children
[i
];
1017 /* Create a Java object from this vdev */
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
1031 /* Add child to child vdev list */
1032 (*env
)->CallBooleanMethod(env
,
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
);
1059 /* Add bean to list */
1060 (*env
)->CallBooleanMethod(env
, ((zjni_Object_t
*)list
)->object
,
1061 ((zjni_Collection_t
*)list
)->method_add
, bean
);
1067 populate_DeviceStatsBean(JNIEnv
*env
, nvlist_t
*vdev
,
1068 DeviceStatsBean_t
*bean
, zjni_Object_t
*object
)
1073 int result
= nvlist_lookup_uint64_array(
1074 vdev
, ZPOOL_CONFIG_VDEV_STATS
, (uint64_t **)&vs
, &c
);
1076 zjni_throw_exception(env
,
1077 "could not retrieve virtual device statistics");
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
));
1123 * Converts a pool_state_t to a Java PoolStats$PoolState object.
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.
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
));
1149 * Iterates through each importable pool on the system. For each
1150 * importable pool, runs the given function with the given void as the
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
) {
1164 if (nvpair_value_nvlist(elem
, &config
) != 0 ||
1165 func(config
, data
)) {
1175 zjni_vdev_state_to_str(vdev_state_t state
) {
1176 return (find_field(vdev_state_map
, state
));
1180 zjni_vdev_aux_to_str(vdev_aux_t aux
) {
1181 return (find_field(vdev_aux_map
, aux
));
1185 zjni_pool_state_to_str(pool_state_t state
) {
1186 return (find_field(pool_state_map
, state
));
1190 zjni_pool_status_to_str(zpool_status_t status
) {
1191 return (find_field(zpool_status_map
, status
));