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