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