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