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