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