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 2004 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 <fcntl.h>
30 #include <libdevinfo.h>
31 #include <stdio.h>
32 #include <sys/sunddi.h>
33 #include <sys/types.h>
34 #include <unistd.h>
35 #include <stdlib.h>
36 #include <string.h>
37 
38 #include "libdiskmgt.h"
39 #include "disks_private.h"
40 #include "partition.h"
41 
42 
43 extern dm_desc_type_t drive_assoc_types[];
44 extern dm_desc_type_t bus_assoc_types[];
45 extern dm_desc_type_t controller_assoc_types[];
46 extern dm_desc_type_t media_assoc_types[];
47 extern dm_desc_type_t slice_assoc_types[];
48 extern dm_desc_type_t partition_assoc_types[];
49 extern dm_desc_type_t path_assoc_types[];
50 extern dm_desc_type_t alias_assoc_types[];
51 
52 static dm_descriptor_t *ptr_array_to_desc_array(descriptor_t **ptrs, int *errp);
53 static descriptor_t **desc_array_to_ptr_array(dm_descriptor_t *da, int *errp);
54 
55 void
56 dm_free_descriptor(dm_descriptor_t desc)
57 {
58 	descriptor_t	*dp;
59 
60 	if (desc == NULL) {
61 	    return;
62 	}
63 	dp = (descriptor_t *)desc;
64 
65 	cache_wlock();
66 	cache_free_descriptor(dp);
67 	cache_unlock();
68 }
69 
70 void
71 dm_free_descriptors(dm_descriptor_t *desc_list)
72 {
73 	descriptor_t	**dp;
74 	int		error;
75 
76 	if (desc_list == NULL) {
77 	    return;
78 	}
79 	dp = desc_array_to_ptr_array(desc_list, &error);
80 	if (error != 0) {
81 	    free(desc_list);
82 	    return;
83 	}
84 
85 	cache_wlock();
86 	cache_free_descriptors(dp);
87 	cache_unlock();
88 }
89 
90 /*ARGSUSED*/
91 void
92 dm_free_name(char *name)
93 {
94 	free(name);
95 }
96 
97 dm_descriptor_t *
98 dm_get_associated_descriptors(dm_descriptor_t desc, dm_desc_type_t type,
99     int *errp)
100 {
101 	descriptor_t **descs = NULL;
102 	descriptor_t  *dp;
103 
104 
105 	dp = (descriptor_t *)desc;
106 
107 	cache_wlock();
108 
109 	if (!cache_is_valid_desc(dp)) {
110 	    cache_unlock();
111 	    *errp = EBADF;
112 	    return (NULL);
113 	}
114 
115 	/* verify that the descriptor is still valid */
116 	if (dp->p.generic == NULL) {
117 	    cache_unlock();
118 	    *errp = ENODEV;
119 	    return (NULL);
120 	}
121 
122 	switch (dp->type) {
123 	case DM_DRIVE:
124 	    descs = drive_get_assoc_descriptors(dp, type, errp);
125 	    break;
126 	case DM_BUS:
127 	    descs = bus_get_assoc_descriptors(dp, type, errp);
128 	    break;
129 	case DM_CONTROLLER:
130 	    descs = controller_get_assoc_descriptors(dp, type, errp);
131 	    break;
132 	case DM_MEDIA:
133 	    descs = media_get_assoc_descriptors(dp, type, errp);
134 	    break;
135 	case DM_SLICE:
136 	    descs = slice_get_assoc_descriptors(dp, type, errp);
137 	    break;
138 	case DM_PARTITION:
139 	    descs = partition_get_assoc_descriptors(dp, type, errp);
140 	    break;
141 	case DM_PATH:
142 	    descs = path_get_assoc_descriptors(dp, type, errp);
143 	    break;
144 	case DM_ALIAS:
145 	    descs = alias_get_assoc_descriptors(dp, type, errp);
146 	    break;
147 	default:
148 	    *errp = EINVAL;
149 	    break;
150 	}
151 
152 	cache_unlock();
153 
154 	return (ptr_array_to_desc_array(descs, errp));
155 }
156 
157 dm_desc_type_t *
158 dm_get_associated_types(dm_desc_type_t type)
159 {
160 	switch (type) {
161 	case DM_DRIVE:
162 	    return (drive_assoc_types);
163 	case DM_BUS:
164 	    return (bus_assoc_types);
165 	case DM_CONTROLLER:
166 	    return (controller_assoc_types);
167 	case DM_MEDIA:
168 	    return (media_assoc_types);
169 	case DM_SLICE:
170 	    return (slice_assoc_types);
171 	case DM_PARTITION:
172 	    return (partition_assoc_types);
173 	case DM_PATH:
174 	    return (path_assoc_types);
175 	case DM_ALIAS:
176 	    return (alias_assoc_types);
177 	}
178 
179 	return (NULL);
180 }
181 
182 nvlist_t *
183 dm_get_attributes(dm_descriptor_t desc, int *errp)
184 {
185 	descriptor_t	*dp;
186 	nvlist_t	*attrs = NULL;
187 
188 
189 	dp = (descriptor_t *)desc;
190 
191 	cache_rlock();
192 
193 	if (!cache_is_valid_desc(dp)) {
194 	    cache_unlock();
195 	    *errp = EBADF;
196 	    return (NULL);
197 	}
198 
199 	/* verify that the descriptor is still valid */
200 	if (dp->p.generic == NULL) {
201 	    cache_unlock();
202 	    *errp = ENODEV;
203 	    return (NULL);
204 	}
205 
206 	switch (dp->type) {
207 	case DM_DRIVE:
208 	    attrs = drive_get_attributes(dp, errp);
209 	    break;
210 	case DM_BUS:
211 	    attrs = bus_get_attributes(dp, errp);
212 	    break;
213 	case DM_CONTROLLER:
214 	    attrs = controller_get_attributes(dp, errp);
215 	    break;
216 	case DM_MEDIA:
217 	    attrs = media_get_attributes(dp, errp);
218 	    break;
219 	case DM_SLICE:
220 	    attrs = slice_get_attributes(dp, errp);
221 	    break;
222 	case DM_PARTITION:
223 	    attrs = partition_get_attributes(dp, errp);
224 	    break;
225 	case DM_PATH:
226 	    attrs = path_get_attributes(dp, errp);
227 	    break;
228 	case DM_ALIAS:
229 	    attrs = alias_get_attributes(dp, errp);
230 	    break;
231 	default:
232 	    *errp = EINVAL;
233 	    break;
234 	}
235 
236 	cache_unlock();
237 
238 	return (attrs);
239 }
240 
241 dm_descriptor_t
242 dm_get_descriptor_by_name(dm_desc_type_t desc_type, char *name, int *errp)
243 {
244 	dm_descriptor_t desc = NULL;
245 
246 
247 	cache_wlock();
248 
249 	switch (desc_type) {
250 	case DM_DRIVE:
251 	    desc = (uintptr_t)drive_get_descriptor_by_name(name, errp);
252 	    break;
253 	case DM_BUS:
254 	    desc = (uintptr_t)bus_get_descriptor_by_name(name, errp);
255 	    break;
256 	case DM_CONTROLLER:
257 	    desc = (uintptr_t)controller_get_descriptor_by_name(name,
258 		errp);
259 	    break;
260 	case DM_MEDIA:
261 	    desc = (uintptr_t)media_get_descriptor_by_name(name, errp);
262 	    break;
263 	case DM_SLICE:
264 	    desc = (uintptr_t)slice_get_descriptor_by_name(name, errp);
265 	    break;
266 	case DM_PARTITION:
267 	    desc = (uintptr_t)partition_get_descriptor_by_name(name,
268 		errp);
269 	    break;
270 	case DM_PATH:
271 	    desc = (uintptr_t)path_get_descriptor_by_name(name, errp);
272 	    break;
273 	case DM_ALIAS:
274 	    desc = (uintptr_t)alias_get_descriptor_by_name(name, errp);
275 	    break;
276 	default:
277 	    *errp = EINVAL;
278 	    break;
279 	}
280 
281 	cache_unlock();
282 
283 	return (desc);
284 }
285 
286 dm_descriptor_t *
287 dm_get_descriptors(dm_desc_type_t type, int filter[], int *errp)
288 {
289 	descriptor_t **descs = NULL;
290 
291 
292 	cache_wlock();
293 
294 	switch (type) {
295 	case DM_DRIVE:
296 	    descs = drive_get_descriptors(filter, errp);
297 	    break;
298 	case DM_BUS:
299 	    descs = bus_get_descriptors(filter, errp);
300 	    break;
301 	case DM_CONTROLLER:
302 	    descs = controller_get_descriptors(filter, errp);
303 	    break;
304 	case DM_MEDIA:
305 	    descs = media_get_descriptors(filter, errp);
306 	    break;
307 	case DM_SLICE:
308 	    descs = slice_get_descriptors(filter, errp);
309 	    break;
310 	case DM_PARTITION:
311 	    descs = partition_get_descriptors(filter, errp);
312 	    break;
313 	case DM_PATH:
314 	    descs = path_get_descriptors(filter, errp);
315 	    break;
316 	case DM_ALIAS:
317 	    descs = alias_get_descriptors(filter, errp);
318 	    break;
319 	default:
320 	    *errp = EINVAL;
321 	    break;
322 	}
323 
324 	cache_unlock();
325 
326 	return (ptr_array_to_desc_array(descs, errp));
327 }
328 
329 char *
330 dm_get_name(dm_descriptor_t desc, int *errp)
331 {
332 	descriptor_t	*dp;
333 	char		*nm = NULL;
334 	char		*name = NULL;
335 
336 	dp = (descriptor_t *)desc;
337 
338 	cache_rlock();
339 
340 	if (!cache_is_valid_desc(dp)) {
341 	    cache_unlock();
342 	    *errp = EBADF;
343 	    return (NULL);
344 	}
345 
346 	/* verify that the descriptor is still valid */
347 	if (dp->p.generic == NULL) {
348 	    cache_unlock();
349 	    *errp = ENODEV;
350 	    return (NULL);
351 	}
352 
353 	switch (dp->type) {
354 	case DM_DRIVE:
355 	    nm = (drive_get_name(dp));
356 	    break;
357 	case DM_BUS:
358 	    nm = (bus_get_name(dp));
359 	    break;
360 	case DM_CONTROLLER:
361 	    nm = (controller_get_name(dp));
362 	    break;
363 	case DM_MEDIA:
364 	    nm = (media_get_name(dp));
365 	    break;
366 	case DM_SLICE:
367 	    nm = (slice_get_name(dp));
368 	    break;
369 	case DM_PARTITION:
370 	    nm = (partition_get_name(dp));
371 	    break;
372 	case DM_PATH:
373 	    nm = (path_get_name(dp));
374 	    break;
375 	case DM_ALIAS:
376 	    nm = (alias_get_name(dp));
377 	    break;
378 	}
379 
380 	cache_unlock();
381 
382 	*errp = 0;
383 	if (nm != NULL) {
384 	    name = strdup(nm);
385 	    if (name == NULL) {
386 		*errp = ENOMEM;
387 		return (NULL);
388 	    }
389 	    return (name);
390 	}
391 	return (NULL);
392 }
393 
394 nvlist_t *
395 dm_get_stats(dm_descriptor_t desc, int stat_type, int *errp)
396 {
397 	descriptor_t  *dp;
398 	nvlist_t	*stats = NULL;
399 
400 
401 	dp = (descriptor_t *)desc;
402 
403 	cache_rlock();
404 
405 	if (!cache_is_valid_desc(dp)) {
406 	    cache_unlock();
407 	    *errp = EBADF;
408 	    return (NULL);
409 	}
410 
411 	/* verify that the descriptor is still valid */
412 	if (dp->p.generic == NULL) {
413 	    cache_unlock();
414 	    *errp = ENODEV;
415 	    return (NULL);
416 	}
417 
418 	switch (dp->type) {
419 	case DM_DRIVE:
420 	    stats = drive_get_stats(dp, stat_type, errp);
421 	    break;
422 	case DM_BUS:
423 	    stats = bus_get_stats(dp, stat_type, errp);
424 	    break;
425 	case DM_CONTROLLER:
426 	    stats = controller_get_stats(dp, stat_type, errp);
427 	    break;
428 	case DM_MEDIA:
429 	    stats = media_get_stats(dp, stat_type, errp);
430 	    break;
431 	case DM_SLICE:
432 	    stats = slice_get_stats(dp, stat_type, errp);
433 	    break;
434 	case DM_PARTITION:
435 	    stats = partition_get_stats(dp, stat_type, errp);
436 	    break;
437 	case DM_PATH:
438 	    stats = path_get_stats(dp, stat_type, errp);
439 	    break;
440 	case DM_ALIAS:
441 	    stats = alias_get_stats(dp, stat_type, errp);
442 	    break;
443 	default:
444 	    *errp = EINVAL;
445 	    break;
446 	}
447 
448 	cache_unlock();
449 
450 	return (stats);
451 }
452 
453 dm_desc_type_t
454 dm_get_type(dm_descriptor_t desc)
455 {
456 	descriptor_t  *dp;
457 
458 	dp = (descriptor_t *)desc;
459 
460 	cache_rlock();
461 
462 	if (!cache_is_valid_desc(dp)) {
463 	    cache_unlock();
464 	    return (-1);
465 	}
466 
467 	cache_unlock();
468 
469 	return (dp->type);
470 }
471 
472 void
473 libdiskmgt_add_str(nvlist_t *attrs, char *name, char *val, int *errp)
474 {
475 	if (*errp == 0) {
476 		*errp = nvlist_add_string(attrs, name, val);
477 	}
478 }
479 
480 descriptor_t **
481 libdiskmgt_empty_desc_array(int *errp)
482 {
483 	descriptor_t	**empty;
484 
485 	empty = (descriptor_t **)calloc(1, sizeof (descriptor_t *));
486 	if (empty == NULL) {
487 	    *errp = ENOMEM;
488 	    return (NULL);
489 	}
490 	empty[0] = NULL;
491 
492 	*errp = 0;
493 	return (empty);
494 }
495 
496 void
497 libdiskmgt_init_debug()
498 {
499 	char	*valp;
500 
501 	if ((valp = getenv(DM_DEBUG)) != NULL) {
502 	    dm_debug = atoi(valp);
503 	}
504 }
505 
506 int
507 libdiskmgt_str_eq(char *nm1, char *nm2)
508 {
509 	if (nm1 == NULL) {
510 	    if (dm_debug) {
511 		(void) fprintf(stderr, "WARNING: str_eq nm1 NULL\n");
512 	    }
513 
514 	    if (nm2 == NULL) {
515 		return (1);
516 	    } else {
517 		return (0);
518 	    }
519 	}
520 
521 	/* nm1 != NULL */
522 
523 	if (nm2 == NULL) {
524 	    if (dm_debug) {
525 		(void) fprintf(stderr, "WARNING: str_eq nm2 NULL\n");
526 	    }
527 	    return (0);
528 	}
529 
530 	if (strcmp(nm1, nm2) == 0) {
531 	    return (1);
532 	}
533 
534 	return (0);
535 }
536 
537 /*ARGSUSED*/
538 static descriptor_t **
539 desc_array_to_ptr_array(dm_descriptor_t *descs, int *errp)
540 {
541 #ifdef _LP64
542 	return ((descriptor_t **)descs);
543 #else
544 	/* convert the 64 bit descriptors to 32 bit ptrs */
545 	int	cnt;
546 	int	i;
547 	descriptor_t **da;
548 
549 	for (cnt = 0; descs[cnt]; cnt++);
550 
551 	da = (descriptor_t **)calloc(cnt + 1, sizeof (descriptor_t *));
552 	if (da == NULL) {
553 	    *errp = ENOMEM;
554 	    return (NULL);
555 	}
556 
557 	for (i = 0; descs[i]; i++) {
558 	    da[i] = (descriptor_t *)descs[i];
559 	}
560 	*errp = 0;
561 	free(descs);
562 
563 	return (da);
564 #endif
565 }
566 
567 /*ARGSUSED*/
568 static dm_descriptor_t *
569 ptr_array_to_desc_array(descriptor_t **ptrs, int *errp)
570 {
571 #ifdef _LP64
572 	return ((dm_descriptor_t *)ptrs);
573 #else
574 	/* convert the 32 bit ptrs to the 64 bit descriptors */
575 	int	cnt;
576 	int	i;
577 	dm_descriptor_t *da;
578 
579 	if (*errp != 0 || ptrs == NULL) {
580 	    return (NULL);
581 	}
582 
583 	for (cnt = 0; ptrs[cnt]; cnt++);
584 
585 	da = (dm_descriptor_t *)calloc(cnt + 1, sizeof (dm_descriptor_t));
586 	if (da == NULL) {
587 	    *errp = ENOMEM;
588 	    return (NULL);
589 	}
590 
591 	for (i = 0; ptrs[i]; i++) {
592 	    da[i] = (uintptr_t)ptrs[i];
593 	}
594 	*errp = 0;
595 	free(ptrs);
596 
597 	return (da);
598 #endif
599 }
600