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