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