xref: /illumos-gate/usr/src/lib/libzfs_jni/common/libzfs_jni_pool.c (revision fa9e4066f08beec538e775443c5be79dd423fcab)
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