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