1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 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 "libzfs_jni_util.h" 31 #include <strings.h> 32 33 /* 34 * Types 35 */ 36 37 typedef struct VirtualDeviceBean { 38 zjni_Object_t super; 39 40 jmethodID method_setPoolName; 41 jmethodID method_setIndex; 42 jmethodID method_setSize; 43 jmethodID method_setUsed; 44 } VirtualDeviceBean_t; 45 46 typedef struct DiskVirtualDeviceBean { 47 VirtualDeviceBean_t super; 48 49 jmethodID method_setDiskName; 50 } DiskVirtualDeviceBean_t; 51 52 typedef struct FileVirtualDeviceBean { 53 VirtualDeviceBean_t super; 54 55 jmethodID method_setFileName; 56 } FileVirtualDeviceBean_t; 57 58 typedef struct RAIDVirtualDeviceBean { 59 VirtualDeviceBean_t super; 60 } RAIDVirtualDeviceBean_t; 61 62 typedef struct MirrorVirtualDeviceBean { 63 VirtualDeviceBean_t super; 64 } MirrorVirtualDeviceBean_t; 65 66 /* 67 * Function prototypes 68 */ 69 70 static void new_VirtualDevice(JNIEnv *, VirtualDeviceBean_t *); 71 static void new_DiskVirtualDeviceBean(JNIEnv *, DiskVirtualDeviceBean_t *); 72 static void new_FileVirtualDeviceBean(JNIEnv *, FileVirtualDeviceBean_t *); 73 static void new_RAIDVirtualDeviceBean(JNIEnv *, RAIDVirtualDeviceBean_t *); 74 static void new_MirrorVirtualDeviceBean(JNIEnv *, MirrorVirtualDeviceBean_t *); 75 static int populate_VirtualDeviceBean( 76 JNIEnv *, zpool_handle_t *, nvlist_t *, VirtualDeviceBean_t *); 77 static int populate_DiskVirtualDeviceBean( 78 JNIEnv *, zpool_handle_t *, nvlist_t *, DiskVirtualDeviceBean_t *); 79 static int populate_FileVirtualDeviceBean( 80 JNIEnv *, zpool_handle_t *, nvlist_t *, FileVirtualDeviceBean_t *); 81 static int populate_RAIDVirtualDeviceBean( 82 JNIEnv *, zpool_handle_t *, nvlist_t *, RAIDVirtualDeviceBean_t *); 83 static int populate_MirrorVirtualDeviceBean( 84 JNIEnv *, zpool_handle_t *, nvlist_t *, MirrorVirtualDeviceBean_t *); 85 static jobject create_DiskVirtualDeviceBean( 86 JNIEnv *, zpool_handle_t *, nvlist_t *); 87 static jobject create_FileVirtualDeviceBean( 88 JNIEnv *, zpool_handle_t *, nvlist_t *); 89 static jobject create_RAIDVirtualDeviceBean( 90 JNIEnv *, zpool_handle_t *, nvlist_t *); 91 static jobject create_MirrorVirtualDeviceBean( 92 JNIEnv *, zpool_handle_t *, nvlist_t *); 93 94 /* 95 * Static functions 96 */ 97 98 /* Create a VirtualDeviceBean */ 99 static void 100 new_VirtualDevice(JNIEnv *env, VirtualDeviceBean_t *bean) 101 { 102 zjni_Object_t *object = (zjni_Object_t *)bean; 103 104 if (object->object == NULL) { 105 object->class = 106 (*env)->FindClass(env, 107 ZFSJNI_PACKAGE_DATA "VirtualDeviceBean"); 108 109 object->constructor = 110 (*env)->GetMethodID(env, object->class, "<init>", "()V"); 111 112 object->object = 113 (*env)->NewObject(env, object->class, object->constructor); 114 } 115 116 bean->method_setPoolName = (*env)->GetMethodID( 117 env, object->class, "setPoolName", "(Ljava/lang/String;)V"); 118 119 bean->method_setIndex = (*env)->GetMethodID( 120 env, object->class, "setIndex", "(J)V"); 121 122 bean->method_setSize = (*env)->GetMethodID( 123 env, object->class, "setSize", "(J)V"); 124 125 bean->method_setUsed = (*env)->GetMethodID( 126 env, object->class, "setUsed", "(J)V"); 127 } 128 129 /* Create a DiskVirtualDeviceBean */ 130 static void 131 new_DiskVirtualDeviceBean(JNIEnv *env, DiskVirtualDeviceBean_t *bean) 132 { 133 zjni_Object_t *object = (zjni_Object_t *)bean; 134 135 if (object->object == NULL) { 136 object->class = (*env)->FindClass( 137 env, ZFSJNI_PACKAGE_DATA "DiskVirtualDeviceBean"); 138 139 object->constructor = 140 (*env)->GetMethodID(env, object->class, "<init>", "()V"); 141 142 object->object = 143 (*env)->NewObject(env, object->class, object->constructor); 144 } 145 146 new_VirtualDevice(env, (VirtualDeviceBean_t *)bean); 147 148 bean->method_setDiskName = (*env)->GetMethodID( 149 env, object->class, "setDiskName", "(Ljava/lang/String;)V"); 150 151 } 152 153 /* Create a FileVirtualDeviceBean */ 154 static void 155 new_FileVirtualDeviceBean(JNIEnv *env, FileVirtualDeviceBean_t *bean) 156 { 157 zjni_Object_t *object = (zjni_Object_t *)bean; 158 159 if (object->object == NULL) { 160 object->class = (*env)->FindClass( 161 env, ZFSJNI_PACKAGE_DATA "FileVirtualDeviceBean"); 162 163 object->constructor = 164 (*env)->GetMethodID(env, object->class, "<init>", "()V"); 165 166 object->object = 167 (*env)->NewObject(env, object->class, object->constructor); 168 } 169 170 new_VirtualDevice(env, (VirtualDeviceBean_t *)bean); 171 172 bean->method_setFileName = (*env)->GetMethodID( 173 env, object->class, "setFileName", "(Ljava/lang/String;)V"); 174 } 175 176 /* Create a RAIDVirtualDeviceBean */ 177 static void 178 new_RAIDVirtualDeviceBean(JNIEnv *env, RAIDVirtualDeviceBean_t *bean) 179 { 180 zjni_Object_t *object = (zjni_Object_t *)bean; 181 182 if (object->object == NULL) { 183 184 object->class = (*env)->FindClass( 185 env, ZFSJNI_PACKAGE_DATA "RAIDVirtualDeviceBean"); 186 187 object->constructor = 188 (*env)->GetMethodID(env, object->class, "<init>", "()V"); 189 190 object->object = 191 (*env)->NewObject(env, object->class, object->constructor); 192 } 193 194 new_VirtualDevice(env, (VirtualDeviceBean_t *)bean); 195 } 196 197 /* Create a MirrorVirtualDeviceBean */ 198 static void 199 new_MirrorVirtualDeviceBean(JNIEnv *env, MirrorVirtualDeviceBean_t *bean) 200 { 201 zjni_Object_t *object = (zjni_Object_t *)bean; 202 203 if (object->object == NULL) { 204 object->class = (*env)->FindClass( 205 env, ZFSJNI_PACKAGE_DATA "MirrorVirtualDeviceBean"); 206 207 object->constructor = 208 (*env)->GetMethodID(env, object->class, "<init>", "()V"); 209 210 object->object = 211 (*env)->NewObject(env, object->class, object->constructor); 212 } 213 214 new_VirtualDevice(env, (VirtualDeviceBean_t *)bean); 215 } 216 217 static int 218 populate_VirtualDeviceBean(JNIEnv *env, zpool_handle_t *zhp, 219 nvlist_t *vdev, VirtualDeviceBean_t *bean) 220 { 221 int result; 222 uint64_t vdev_id; 223 zjni_Object_t *object = (zjni_Object_t *)bean; 224 225 /* Set pool name */ 226 jstring poolUTF = (*env)->NewStringUTF(env, zpool_get_name(zhp)); 227 (*env)->CallVoidMethod( 228 env, object->object, bean->method_setPoolName, poolUTF); 229 230 /* Get index */ 231 result = nvlist_lookup_uint64(vdev, ZPOOL_CONFIG_GUID, &vdev_id); 232 if (result != 0) { 233 zjni_throw_exception(env, 234 "could not retrieve virtual device ID (pool %s)", 235 zpool_get_name(zhp)); 236 } else { 237 238 uint64_t used; 239 uint64_t total; 240 241 (*env)->CallVoidMethod( 242 env, object->object, bean->method_setIndex, (jlong)vdev_id); 243 244 /* Set used space */ 245 used = zpool_get_space_used(zhp); 246 247 (*env)->CallVoidMethod( 248 env, object->object, bean->method_setUsed, (jlong)used); 249 250 /* Set available space */ 251 total = zpool_get_space_total(zhp); 252 253 (*env)->CallVoidMethod( 254 env, object->object, bean->method_setSize, (jlong)total); 255 } 256 257 return (result != 0); 258 } 259 260 static int 261 populate_DiskVirtualDeviceBean(JNIEnv *env, zpool_handle_t *zhp, 262 nvlist_t *vdev, DiskVirtualDeviceBean_t *bean) 263 { 264 char *path; 265 int result = populate_VirtualDeviceBean( 266 env, zhp, vdev, (VirtualDeviceBean_t *)bean); 267 268 if (result) { 269 /* Must not call any more Java methods to preserve exception */ 270 return (-1); 271 } 272 273 /* Set path */ 274 result = nvlist_lookup_string(vdev, ZPOOL_CONFIG_PATH, &path); 275 if (result != 0) { 276 zjni_throw_exception(env, 277 "could not retrive path from disk virtual device (pool %s)", 278 zpool_get_name(zhp)); 279 } else { 280 281 jstring pathUTF = (*env)->NewStringUTF(env, path); 282 (*env)->CallVoidMethod(env, ((zjni_Object_t *)bean)->object, 283 bean->method_setDiskName, pathUTF); 284 } 285 286 return (result != 0); 287 } 288 289 static int 290 populate_FileVirtualDeviceBean(JNIEnv *env, zpool_handle_t *zhp, 291 nvlist_t *vdev, FileVirtualDeviceBean_t *bean) 292 { 293 char *path; 294 int result = populate_VirtualDeviceBean( 295 env, zhp, vdev, (VirtualDeviceBean_t *)bean); 296 297 if (result) { 298 /* Must not call any more Java methods to preserve exception */ 299 return (-1); 300 } 301 302 /* Set path */ 303 result = nvlist_lookup_string(vdev, ZPOOL_CONFIG_PATH, &path); 304 if (result != 0) { 305 zjni_throw_exception(env, 306 "could not retrive path from disk virtual device (pool %s)", 307 zpool_get_name(zhp)); 308 } else { 309 310 jstring pathUTF = (*env)->NewStringUTF(env, path); 311 (*env)->CallVoidMethod(env, ((zjni_Object_t *)bean)->object, 312 bean->method_setFileName, pathUTF); 313 } 314 315 return (result != 0); 316 } 317 318 static int 319 populate_RAIDVirtualDeviceBean(JNIEnv *env, zpool_handle_t *zhp, 320 nvlist_t *vdev, RAIDVirtualDeviceBean_t *bean) 321 { 322 return (populate_VirtualDeviceBean(env, zhp, vdev, 323 (VirtualDeviceBean_t *)bean)); 324 } 325 326 static int 327 populate_MirrorVirtualDeviceBean(JNIEnv *env, zpool_handle_t *zhp, 328 nvlist_t *vdev, MirrorVirtualDeviceBean_t *bean) 329 { 330 return (populate_VirtualDeviceBean(env, zhp, vdev, 331 (VirtualDeviceBean_t *)bean)); 332 } 333 334 static jobject 335 create_DiskVirtualDeviceBean(JNIEnv *env, zpool_handle_t *zhp, nvlist_t *vdev) 336 { 337 int result; 338 DiskVirtualDeviceBean_t bean_obj = {0}; 339 DiskVirtualDeviceBean_t *bean = &bean_obj; 340 341 /* Construct DiskVirtualDeviceBean */ 342 new_DiskVirtualDeviceBean(env, bean); 343 344 result = populate_DiskVirtualDeviceBean(env, zhp, vdev, bean); 345 if (result) { 346 /* Must not call any more Java methods to preserve exception */ 347 return (NULL); 348 } 349 350 return (((zjni_Object_t *)bean)->object); 351 } 352 353 static jobject 354 create_FileVirtualDeviceBean(JNIEnv *env, zpool_handle_t *zhp, nvlist_t *vdev) 355 { 356 int result; 357 FileVirtualDeviceBean_t bean_obj = {0}; 358 FileVirtualDeviceBean_t *bean = &bean_obj; 359 360 /* Construct FileVirtualDeviceBean */ 361 new_FileVirtualDeviceBean(env, bean); 362 363 result = populate_FileVirtualDeviceBean(env, zhp, vdev, bean); 364 if (result) { 365 /* Must not call any more Java methods to preserve exception */ 366 return (NULL); 367 } 368 369 return (((zjni_Object_t *)bean)->object); 370 } 371 372 static jobject 373 create_RAIDVirtualDeviceBean(JNIEnv *env, zpool_handle_t *zhp, nvlist_t *vdev) 374 { 375 int result; 376 RAIDVirtualDeviceBean_t bean_obj = {0}; 377 RAIDVirtualDeviceBean_t *bean = &bean_obj; 378 379 ((zjni_Object_t *)bean)->object = NULL; 380 381 /* Construct RAIDVirtualDeviceBean */ 382 new_RAIDVirtualDeviceBean(env, bean); 383 384 result = populate_RAIDVirtualDeviceBean(env, zhp, vdev, bean); 385 if (result) { 386 /* Must not call any more Java methods to preserve exception */ 387 return (NULL); 388 } 389 390 return (((zjni_Object_t *)bean)->object); 391 } 392 393 static jobject 394 create_MirrorVirtualDeviceBean(JNIEnv *env, zpool_handle_t *zhp, nvlist_t *vdev) 395 { 396 int result; 397 MirrorVirtualDeviceBean_t bean_obj = {0}; 398 MirrorVirtualDeviceBean_t *bean = &bean_obj; 399 400 /* Construct MirrorVirtualDeviceBean */ 401 new_MirrorVirtualDeviceBean(env, bean); 402 403 result = populate_MirrorVirtualDeviceBean(env, zhp, vdev, bean); 404 if (result) { 405 /* Must not call any more Java methods to preserve exception */ 406 return (NULL); 407 } 408 409 return (((zjni_Object_t *)bean)->object); 410 } 411 412 /* 413 * Package-private functions 414 */ 415 416 /* 417 * Gets the root vdev (an nvlist_t *) for the given pool. 418 */ 419 nvlist_t * 420 zjni_get_root_vdev(zpool_handle_t *zhp) 421 { 422 nvlist_t *root = NULL; 423 424 if (zhp != NULL) { 425 nvlist_t *attrs = zpool_get_config(zhp); 426 427 if (attrs != NULL) { 428 int result = nvlist_lookup_nvlist( 429 attrs, ZPOOL_CONFIG_VDEV_TREE, &root); 430 if (result != 0) { 431 root = NULL; 432 } 433 /* nvlist_print(stderr, vdev_parent); */ 434 } 435 } 436 437 return (root); 438 } 439 440 /* 441 * Gets the vdev (an nvlist_t *) with the given vdev_id, below the 442 * given vdev. If the given vdev is NULL, all vdevs within the given 443 * pool are searched. 444 */ 445 nvlist_t * 446 zjni_get_vdev(zpool_handle_t *zhp, nvlist_t *vdev_parent, 447 uint64_t vdev_id_to_find) 448 { 449 int result; 450 451 /* Was a vdev specified? */ 452 if (vdev_parent == NULL) { 453 /* No -- retrieve the top-level pool vdev */ 454 vdev_parent = zjni_get_root_vdev(zhp); 455 } else { 456 /* Get index of this vdev and compare with vdev_id_to_find */ 457 uint64_t id; 458 result = nvlist_lookup_uint64( 459 vdev_parent, ZPOOL_CONFIG_GUID, &id); 460 if (result == 0 && id == vdev_id_to_find) { 461 return (vdev_parent); 462 } 463 } 464 465 if (vdev_parent != NULL) { 466 467 nvlist_t **children; 468 uint_t nelem = 0; 469 470 /* Get the vdevs under this vdev */ 471 result = nvlist_lookup_nvlist_array( 472 vdev_parent, ZPOOL_CONFIG_CHILDREN, &children, &nelem); 473 474 if (result == 0) { 475 476 int i; 477 nvlist_t *child; 478 479 /* For each vdev child... */ 480 for (i = 0; i < nelem; i++) { 481 child = zjni_get_vdev(zhp, children[i], 482 vdev_id_to_find); 483 if (child != NULL) { 484 return (child); 485 } 486 } 487 } 488 } 489 490 return (NULL); 491 } 492 493 jobject 494 zjni_get_VirtualDevice_from_vdev(JNIEnv *env, zpool_handle_t *zhp, 495 nvlist_t *vdev) 496 { 497 jobject obj = NULL; 498 char *type = NULL; 499 int result = nvlist_lookup_string(vdev, ZPOOL_CONFIG_TYPE, &type); 500 501 if (result == 0) { 502 if (strcmp(type, VDEV_TYPE_DISK) == 0) { 503 obj = create_DiskVirtualDeviceBean(env, zhp, vdev); 504 } else if (strcmp(type, VDEV_TYPE_FILE) == 0) { 505 obj = create_FileVirtualDeviceBean(env, zhp, 506 vdev); 507 } else if (strcmp(type, VDEV_TYPE_RAIDZ) == 0) { 508 obj = create_RAIDVirtualDeviceBean(env, 509 zhp, vdev); 510 } else if (strcmp(type, VDEV_TYPE_MIRROR) == 0) { 511 obj = create_MirrorVirtualDeviceBean(env, zhp, vdev); 512 } 513 } 514 515 return (obj); 516 } 517 518 jobject 519 zjni_get_VirtualDevices_from_vdev(JNIEnv *env, zpool_handle_t *zhp, 520 nvlist_t *vdev_parent) 521 { 522 /* Create an array list for the vdevs */ 523 zjni_ArrayList_t list_class = {0}; 524 zjni_ArrayList_t *list_class_p = &list_class; 525 zjni_new_ArrayList(env, list_class_p); 526 527 /* Was a vdev specified? */ 528 if (vdev_parent == NULL) { 529 /* No -- retrieve the top-level pool vdev */ 530 vdev_parent = zjni_get_root_vdev(zhp); 531 } 532 533 /* nvlist_print(stderr, vdev_parent); */ 534 535 if (vdev_parent != NULL) { 536 537 /* Get the vdevs under this vdev */ 538 nvlist_t **children; 539 uint_t nelem = 0; 540 int result = nvlist_lookup_nvlist_array( 541 vdev_parent, ZPOOL_CONFIG_CHILDREN, &children, &nelem); 542 543 if (result == 0) { 544 545 /* For each vdev child... */ 546 int i; 547 for (i = 0; i < nelem; i++) { 548 nvlist_t *child = children[i]; 549 550 /* Create a Java object from this vdev */ 551 jobject obj = 552 zjni_get_VirtualDevice_from_vdev(env, 553 zhp, child); 554 555 if (obj == NULL) { 556 /* 557 * Must not call any more Java methods 558 * to preserve exception 559 */ 560 return (NULL); 561 } 562 563 /* Add child to child vdev list */ 564 (*env)->CallBooleanMethod(env, 565 ((zjni_Object_t *)list_class_p)->object, 566 ((zjni_Collection_t *)list_class_p)-> 567 method_add, obj); 568 } 569 } 570 } 571 572 return (zjni_Collection_to_array( 573 env, (zjni_Collection_t *)list_class_p, 574 ZFSJNI_PACKAGE_DATA "VirtualDevice")); 575 } 576