Print this page
patch tsoome-feedback
6659 nvlist_free(NULL) is a no-op
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/libdiskmgt/common/entry.c
+++ new/usr/src/lib/libdiskmgt/common/entry.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 */
25 25
26 26 #include <fcntl.h>
27 27 #include <libdevinfo.h>
28 28 #include <stdio.h>
29 29 #include <sys/sunddi.h>
30 30 #include <sys/types.h>
31 31 #include <unistd.h>
32 32 #include <stdlib.h>
33 33 #include <string.h>
34 34 #include <libintl.h>
35 35 #include <locale.h>
36 36 #include <sys/debug.h>
37 37 #include <strings.h>
38 38 #include <sys/stat.h>
39 39 #include <sys/swap.h>
40 40
41 41 #include "libdiskmgt.h"
42 42 #include "disks_private.h"
43 43 #include "partition.h"
44 44
45 45 #define ANY_ZPOOL_USE(who) \
46 46 (((who) == DM_WHO_ZPOOL_FORCE) || \
47 47 ((who) == DM_WHO_ZPOOL) || \
48 48 ((who) == DM_WHO_ZPOOL_SPARE))
49 49
50 50 extern char *getfullblkname();
51 51
52 52 extern dm_desc_type_t drive_assoc_types[];
53 53 extern dm_desc_type_t bus_assoc_types[];
54 54 extern dm_desc_type_t controller_assoc_types[];
55 55 extern dm_desc_type_t media_assoc_types[];
56 56 extern dm_desc_type_t slice_assoc_types[];
57 57 extern dm_desc_type_t partition_assoc_types[];
58 58 extern dm_desc_type_t path_assoc_types[];
59 59 extern dm_desc_type_t alias_assoc_types[];
60 60
61 61
62 62 static dm_descriptor_t *ptr_array_to_desc_array(descriptor_t **ptrs, int *errp);
63 63 static descriptor_t **desc_array_to_ptr_array(dm_descriptor_t *da, int *errp);
64 64 static int build_usage_string(char *dname, char *by, char *data, char **use,
65 65 int *found, int *errp);
66 66
67 67 void
68 68 dm_free_descriptor(dm_descriptor_t desc)
69 69 {
70 70 descriptor_t *dp;
71 71
72 72 if (desc == NULL) {
73 73 return;
74 74 }
75 75 dp = (descriptor_t *)(uintptr_t)desc;
76 76
77 77 cache_wlock();
78 78 cache_free_descriptor(dp);
79 79 cache_unlock();
80 80 }
81 81
82 82 void
83 83 dm_free_descriptors(dm_descriptor_t *desc_list)
84 84 {
85 85 descriptor_t **dp;
86 86 int error;
87 87
88 88 if (desc_list == NULL) {
89 89 return;
90 90 }
91 91 dp = desc_array_to_ptr_array(desc_list, &error);
92 92 if (error != 0) {
93 93 free(desc_list);
94 94 return;
95 95 }
96 96
97 97 cache_wlock();
98 98 cache_free_descriptors(dp);
99 99 cache_unlock();
100 100 }
101 101
102 102 /*ARGSUSED*/
103 103 void
104 104 dm_free_name(char *name)
105 105 {
106 106 free(name);
107 107 }
108 108
109 109 dm_descriptor_t *
110 110 dm_get_associated_descriptors(dm_descriptor_t desc, dm_desc_type_t type,
111 111 int *errp)
112 112 {
113 113 descriptor_t **descs = NULL;
114 114 descriptor_t *dp;
115 115
116 116
117 117 dp = (descriptor_t *)(uintptr_t)desc;
118 118
119 119 cache_wlock();
120 120
121 121 if (!cache_is_valid_desc(dp)) {
122 122 cache_unlock();
123 123 *errp = EBADF;
124 124 return (NULL);
125 125 }
126 126
127 127 /* verify that the descriptor is still valid */
128 128 if (dp->p.generic == NULL) {
129 129 cache_unlock();
130 130 *errp = ENODEV;
131 131 return (NULL);
132 132 }
133 133
134 134 switch (dp->type) {
135 135 case DM_DRIVE:
136 136 descs = drive_get_assoc_descriptors(dp, type, errp);
137 137 break;
138 138 case DM_BUS:
139 139 descs = bus_get_assoc_descriptors(dp, type, errp);
140 140 break;
141 141 case DM_CONTROLLER:
142 142 descs = controller_get_assoc_descriptors(dp, type, errp);
143 143 break;
144 144 case DM_MEDIA:
145 145 descs = media_get_assoc_descriptors(dp, type, errp);
146 146 break;
147 147 case DM_SLICE:
148 148 descs = slice_get_assoc_descriptors(dp, type, errp);
149 149 break;
150 150 case DM_PARTITION:
151 151 descs = partition_get_assoc_descriptors(dp, type, errp);
152 152 break;
153 153 case DM_PATH:
154 154 descs = path_get_assoc_descriptors(dp, type, errp);
155 155 break;
156 156 case DM_ALIAS:
157 157 descs = alias_get_assoc_descriptors(dp, type, errp);
158 158 break;
159 159 default:
160 160 *errp = EINVAL;
161 161 break;
162 162 }
163 163
164 164 cache_unlock();
165 165
166 166 return (ptr_array_to_desc_array(descs, errp));
167 167 }
168 168
169 169 dm_desc_type_t *
170 170 dm_get_associated_types(dm_desc_type_t type)
171 171 {
172 172 switch (type) {
173 173 case DM_DRIVE:
174 174 return (drive_assoc_types);
175 175 case DM_BUS:
176 176 return (bus_assoc_types);
177 177 case DM_CONTROLLER:
178 178 return (controller_assoc_types);
179 179 case DM_MEDIA:
180 180 return (media_assoc_types);
181 181 case DM_SLICE:
182 182 return (slice_assoc_types);
183 183 case DM_PARTITION:
184 184 return (partition_assoc_types);
185 185 case DM_PATH:
186 186 return (path_assoc_types);
187 187 case DM_ALIAS:
188 188 return (alias_assoc_types);
189 189 }
190 190
191 191 return (NULL);
192 192 }
193 193
194 194 nvlist_t *
195 195 dm_get_attributes(dm_descriptor_t desc, int *errp)
196 196 {
197 197 descriptor_t *dp;
198 198 nvlist_t *attrs = NULL;
199 199
200 200
201 201 dp = (descriptor_t *)(uintptr_t)desc;
202 202
203 203 cache_rlock();
204 204
205 205 if (!cache_is_valid_desc(dp)) {
206 206 cache_unlock();
207 207 *errp = EBADF;
208 208 return (NULL);
209 209 }
210 210
211 211 /* verify that the descriptor is still valid */
212 212 if (dp->p.generic == NULL) {
213 213 cache_unlock();
214 214 *errp = ENODEV;
215 215 return (NULL);
216 216 }
217 217
218 218 switch (dp->type) {
219 219 case DM_DRIVE:
220 220 attrs = drive_get_attributes(dp, errp);
221 221 break;
222 222 case DM_BUS:
223 223 attrs = bus_get_attributes(dp, errp);
224 224 break;
225 225 case DM_CONTROLLER:
226 226 attrs = controller_get_attributes(dp, errp);
227 227 break;
228 228 case DM_MEDIA:
229 229 attrs = media_get_attributes(dp, errp);
230 230 break;
231 231 case DM_SLICE:
232 232 attrs = slice_get_attributes(dp, errp);
233 233 break;
234 234 case DM_PARTITION:
235 235 attrs = partition_get_attributes(dp, errp);
236 236 break;
237 237 case DM_PATH:
238 238 attrs = path_get_attributes(dp, errp);
239 239 break;
240 240 case DM_ALIAS:
241 241 attrs = alias_get_attributes(dp, errp);
242 242 break;
243 243 default:
244 244 *errp = EINVAL;
245 245 break;
246 246 }
247 247
248 248 cache_unlock();
249 249
250 250 return (attrs);
251 251 }
252 252
253 253 dm_descriptor_t
254 254 dm_get_descriptor_by_name(dm_desc_type_t desc_type, char *name, int *errp)
255 255 {
256 256 dm_descriptor_t desc = NULL;
257 257
258 258
259 259 cache_wlock();
260 260
261 261 switch (desc_type) {
262 262 case DM_DRIVE:
263 263 desc = (uintptr_t)drive_get_descriptor_by_name(name, errp);
264 264 break;
265 265 case DM_BUS:
266 266 desc = (uintptr_t)bus_get_descriptor_by_name(name, errp);
267 267 break;
268 268 case DM_CONTROLLER:
269 269 desc = (uintptr_t)controller_get_descriptor_by_name(name,
270 270 errp);
271 271 break;
272 272 case DM_MEDIA:
273 273 desc = (uintptr_t)media_get_descriptor_by_name(name, errp);
274 274 break;
275 275 case DM_SLICE:
276 276 desc = (uintptr_t)slice_get_descriptor_by_name(name, errp);
277 277 break;
278 278 case DM_PARTITION:
279 279 desc = (uintptr_t)partition_get_descriptor_by_name(name,
280 280 errp);
281 281 break;
282 282 case DM_PATH:
283 283 desc = (uintptr_t)path_get_descriptor_by_name(name, errp);
284 284 break;
285 285 case DM_ALIAS:
286 286 desc = (uintptr_t)alias_get_descriptor_by_name(name, errp);
287 287 break;
288 288 default:
289 289 *errp = EINVAL;
290 290 break;
291 291 }
292 292
293 293 cache_unlock();
294 294
295 295 return (desc);
296 296 }
297 297
298 298 dm_descriptor_t *
299 299 dm_get_descriptors(dm_desc_type_t type, int filter[], int *errp)
300 300 {
301 301 descriptor_t **descs = NULL;
302 302
303 303
304 304 cache_wlock();
305 305
306 306 switch (type) {
307 307 case DM_DRIVE:
308 308 descs = drive_get_descriptors(filter, errp);
309 309 break;
310 310 case DM_BUS:
311 311 descs = bus_get_descriptors(filter, errp);
312 312 break;
313 313 case DM_CONTROLLER:
314 314 descs = controller_get_descriptors(filter, errp);
315 315 break;
316 316 case DM_MEDIA:
317 317 descs = media_get_descriptors(filter, errp);
318 318 break;
319 319 case DM_SLICE:
320 320 descs = slice_get_descriptors(filter, errp);
321 321 break;
322 322 case DM_PARTITION:
323 323 descs = partition_get_descriptors(filter, errp);
324 324 break;
325 325 case DM_PATH:
326 326 descs = path_get_descriptors(filter, errp);
327 327 break;
328 328 case DM_ALIAS:
329 329 descs = alias_get_descriptors(filter, errp);
330 330 break;
331 331 default:
332 332 *errp = EINVAL;
333 333 break;
334 334 }
335 335
336 336 cache_unlock();
337 337
338 338 return (ptr_array_to_desc_array(descs, errp));
339 339 }
340 340
341 341 char *
342 342 dm_get_name(dm_descriptor_t desc, int *errp)
343 343 {
344 344 descriptor_t *dp;
345 345 char *nm = NULL;
346 346 char *name = NULL;
347 347
348 348 dp = (descriptor_t *)(uintptr_t)desc;
349 349
350 350 cache_rlock();
351 351
352 352 if (!cache_is_valid_desc(dp)) {
353 353 cache_unlock();
354 354 *errp = EBADF;
355 355 return (NULL);
356 356 }
357 357
358 358 /* verify that the descriptor is still valid */
359 359 if (dp->p.generic == NULL) {
360 360 cache_unlock();
361 361 *errp = ENODEV;
362 362 return (NULL);
363 363 }
364 364
365 365 switch (dp->type) {
366 366 case DM_DRIVE:
367 367 nm = (drive_get_name(dp));
368 368 break;
369 369 case DM_BUS:
370 370 nm = (bus_get_name(dp));
371 371 break;
372 372 case DM_CONTROLLER:
373 373 nm = (controller_get_name(dp));
374 374 break;
375 375 case DM_MEDIA:
376 376 nm = (media_get_name(dp));
377 377 break;
378 378 case DM_SLICE:
379 379 nm = (slice_get_name(dp));
380 380 break;
381 381 case DM_PARTITION:
382 382 nm = (partition_get_name(dp));
383 383 break;
384 384 case DM_PATH:
385 385 nm = (path_get_name(dp));
386 386 break;
387 387 case DM_ALIAS:
388 388 nm = (alias_get_name(dp));
389 389 break;
390 390 }
391 391
392 392 cache_unlock();
393 393
394 394 *errp = 0;
395 395 if (nm != NULL) {
396 396 name = strdup(nm);
397 397 if (name == NULL) {
398 398 *errp = ENOMEM;
399 399 return (NULL);
400 400 }
401 401 return (name);
402 402 }
403 403 return (NULL);
404 404 }
405 405
406 406 nvlist_t *
407 407 dm_get_stats(dm_descriptor_t desc, int stat_type, int *errp)
408 408 {
409 409 descriptor_t *dp;
410 410 nvlist_t *stats = NULL;
411 411
412 412
413 413 dp = (descriptor_t *)(uintptr_t)desc;
414 414
415 415 cache_rlock();
416 416
417 417 if (!cache_is_valid_desc(dp)) {
418 418 cache_unlock();
419 419 *errp = EBADF;
420 420 return (NULL);
421 421 }
422 422
423 423 /* verify that the descriptor is still valid */
424 424 if (dp->p.generic == NULL) {
425 425 cache_unlock();
426 426 *errp = ENODEV;
427 427 return (NULL);
428 428 }
429 429
430 430 switch (dp->type) {
431 431 case DM_DRIVE:
432 432 stats = drive_get_stats(dp, stat_type, errp);
433 433 break;
434 434 case DM_BUS:
435 435 stats = bus_get_stats(dp, stat_type, errp);
436 436 break;
437 437 case DM_CONTROLLER:
438 438 stats = controller_get_stats(dp, stat_type, errp);
439 439 break;
440 440 case DM_MEDIA:
441 441 stats = media_get_stats(dp, stat_type, errp);
442 442 break;
443 443 case DM_SLICE:
444 444 if (stat_type == DM_SLICE_STAT_USE) {
445 445 /*
446 446 * If NOINUSE_CHECK is set, we do not perform
447 447 * the in use checking if the user has set stat_type
448 448 * DM_SLICE_STAT_USE
449 449 */
450 450 if (NOINUSE_SET) {
451 451 stats = NULL;
452 452 break;
453 453 }
454 454 }
455 455 stats = slice_get_stats(dp, stat_type, errp);
456 456 break;
457 457 case DM_PARTITION:
458 458 stats = partition_get_stats(dp, stat_type, errp);
459 459 break;
460 460 case DM_PATH:
461 461 stats = path_get_stats(dp, stat_type, errp);
462 462 break;
463 463 case DM_ALIAS:
464 464 stats = alias_get_stats(dp, stat_type, errp);
465 465 break;
466 466 default:
467 467 *errp = EINVAL;
468 468 break;
469 469 }
470 470
471 471 cache_unlock();
472 472
473 473 return (stats);
474 474 }
475 475
476 476 dm_desc_type_t
477 477 dm_get_type(dm_descriptor_t desc)
478 478 {
479 479 descriptor_t *dp;
480 480
481 481 dp = (descriptor_t *)(uintptr_t)desc;
482 482
483 483 cache_rlock();
484 484
485 485 if (!cache_is_valid_desc(dp)) {
486 486 cache_unlock();
487 487 return (-1);
488 488 }
489 489
490 490 cache_unlock();
491 491
492 492 return (dp->type);
493 493 }
494 494 /*
495 495 * Returns, via slices paramater, a dm_descriptor_t list of
496 496 * slices for the named disk drive.
497 497 */
498 498 void
499 499 dm_get_slices(char *drive, dm_descriptor_t **slices, int *errp)
500 500 {
501 501 dm_descriptor_t alias;
502 502 dm_descriptor_t *media;
503 503 dm_descriptor_t *disk;
504 504
505 505 *slices = NULL;
506 506 *errp = 0;
507 507
508 508 if (drive == NULL) {
509 509 return;
510 510 }
511 511
512 512 alias = dm_get_descriptor_by_name(DM_ALIAS, drive, errp);
513 513
514 514 /*
515 515 * Errors must be handled by the caller. The dm_descriptor_t *
516 516 * values will be NULL if an error occured in these calls.
517 517 */
518 518
519 519 if (alias != NULL) {
520 520 disk = dm_get_associated_descriptors(alias, DM_DRIVE, errp);
521 521 dm_free_descriptor(alias);
522 522 if (disk != NULL) {
523 523 media = dm_get_associated_descriptors(*disk,
524 524 DM_MEDIA, errp);
525 525 dm_free_descriptors(disk);
526 526 if (media != NULL) {
527 527 *slices = dm_get_associated_descriptors(*media,
528 528 DM_SLICE, errp);
529 529 dm_free_descriptors(media);
530 530 }
531 531 }
532 532 }
533 533 }
534 534 /*
535 535 * Convenience function to get slice stats
536 536 */
537 537 void
538 538 dm_get_slice_stats(char *slice, nvlist_t **dev_stats, int *errp)
539 539 {
540 540 dm_descriptor_t devp;
541 541
542 542 *dev_stats = NULL;
543 543 *errp = 0;
544 544
545 545 if (slice == NULL) {
546 546 return;
547 547 }
548 548
549 549 /*
550 550 * Errors must be handled by the caller. The dm_descriptor_t *
551 551 * values will be NULL if an error occured in these calls.
552 552 */
553 553 devp = dm_get_descriptor_by_name(DM_SLICE, slice, errp);
554 554 if (devp != NULL) {
555 555 *dev_stats = dm_get_stats(devp, DM_SLICE_STAT_USE,
556 556 errp);
557 557 dm_free_descriptor(devp);
558 558 }
559 559 }
560 560
561 561 /*
562 562 * Checks for overlapping slices. If the given device is a slice, and it
563 563 * overlaps with any non-backup slice on the disk, return true with a detailed
564 564 * description similar to dm_inuse().
565 565 */
566 566 int
567 567 dm_isoverlapping(char *slicename, char **overlaps_with, int *errp)
568 568 {
569 569 dm_descriptor_t slice = NULL;
570 570 dm_descriptor_t *media = NULL;
571 571 dm_descriptor_t *slices = NULL;
572 572 int i = 0;
573 573 uint32_t in_snum;
574 574 uint64_t start_block = 0;
575 575 uint64_t end_block = 0;
576 576 uint64_t media_size = 0;
577 577 uint64_t size = 0;
578 578 nvlist_t *media_attrs = NULL;
579 579 nvlist_t *slice_attrs = NULL;
580 580 int ret = 0;
581 581
582 582 slice = dm_get_descriptor_by_name(DM_SLICE, slicename, errp);
583 583 if (slice == NULL)
584 584 goto out;
585 585
586 586 /*
587 587 * Get the list of slices be fetching the associated media, and then all
588 588 * associated slices.
589 589 */
590 590 media = dm_get_associated_descriptors(slice, DM_MEDIA, errp);
591 591 if (media == NULL || *media == NULL || *errp != 0)
592 592 goto out;
593 593
594 594 slices = dm_get_associated_descriptors(*media, DM_SLICE, errp);
595 595 if (slices == NULL || *slices == NULL || *errp != 0)
596 596 goto out;
597 597
598 598 media_attrs = dm_get_attributes(*media, errp);
599 599 if (media_attrs == NULL || *errp)
600 600 goto out;
601 601
602 602 *errp = nvlist_lookup_uint64(media_attrs, DM_NACCESSIBLE, &media_size);
603 603 if (*errp != 0)
604 604 goto out;
605 605
606 606 slice_attrs = dm_get_attributes(slice, errp);
607 607 if (slice_attrs == NULL || *errp != 0)
608 608 goto out;
609 609
610 610 *errp = nvlist_lookup_uint64(slice_attrs, DM_START, &start_block);
611 611 if (*errp != 0)
612 612 goto out;
613 613
614 614 *errp = nvlist_lookup_uint64(slice_attrs, DM_SIZE, &size);
615 615 if (*errp != 0)
616 616 goto out;
617 617
618 618 *errp = nvlist_lookup_uint32(slice_attrs, DM_INDEX, &in_snum);
619 619 if (*errp != 0)
620 620 goto out;
621 621
622 622 end_block = (start_block + size) - 1;
623 623
624 624 for (i = 0; slices[i]; i ++) {
625 625 uint64_t other_start;
626 626 uint64_t other_end;
627 627 uint64_t other_size;
628 628 uint32_t snum;
629 629
630 630 nvlist_t *other_attrs = dm_get_attributes(slices[i], errp);
631 631
632 632 if (other_attrs == NULL)
633 633 continue;
634 634
635 635 if (*errp != 0)
636 636 goto out;
637 637
638 638 *errp = nvlist_lookup_uint64(other_attrs, DM_START,
639 639 &other_start);
640 640 if (*errp) {
641 641 nvlist_free(other_attrs);
642 642 goto out;
643 643 }
644 644
645 645 *errp = nvlist_lookup_uint64(other_attrs, DM_SIZE,
646 646 &other_size);
647 647
648 648 if (*errp) {
649 649 nvlist_free(other_attrs);
650 650 ret = -1;
651 651 goto out;
652 652 }
653 653
654 654 other_end = (other_size + other_start) - 1;
655 655
656 656 *errp = nvlist_lookup_uint32(other_attrs, DM_INDEX,
657 657 &snum);
658 658
659 659 if (*errp) {
660 660 nvlist_free(other_attrs);
661 661 ret = -1;
662 662 goto out;
663 663 }
664 664
665 665 /*
666 666 * Check to see if there are > 2 overlapping regions
667 667 * on this media in the same region as this slice.
668 668 * This is done by assuming the following:
669 669 * Slice 2 is the backup slice if it is the size
670 670 * of the whole disk
671 671 * If slice 2 is the overlap and slice 2 is the size of
672 672 * the whole disk, continue. If another slice is found
673 673 * that overlaps with our slice, return it.
674 674 * There is the potential that there is more than one slice
675 675 * that our slice overlaps with, however, we only return
676 676 * the first overlapping slice we find.
677 677 *
678 678 */
679 679 if (start_block >= other_start && start_block <= other_end) {
680 680 if ((snum == 2 && (other_size == media_size)) ||
681 681 snum == in_snum) {
682 682 continue;
683 683 } else {
684 684 char *str = dm_get_name(slices[i], errp);
685 685 if (*errp != 0) {
686 686 nvlist_free(other_attrs);
687 687 ret = -1;
688 688 goto out;
689 689 }
690 690 *overlaps_with = strdup(str);
691 691 dm_free_name(str);
692 692 nvlist_free(other_attrs);
693 693 ret = 1;
694 694 goto out;
695 695 }
696 696 } else if (other_start >= start_block &&
697 697 other_start <= end_block) {
698 698 if ((snum == 2 && (other_size == media_size)) ||
699 699 snum == in_snum) {
700 700 continue;
701 701 } else {
702 702 char *str = dm_get_name(slices[i], errp);
703 703 if (*errp != 0) {
704 704 nvlist_free(other_attrs);
705 705 ret = -1;
706 706 goto out;
707 707 }
708 708 *overlaps_with = strdup(str);
↓ open down ↓ |
708 lines elided |
↑ open up ↑ |
709 709 dm_free_name(str);
710 710 nvlist_free(other_attrs);
711 711 ret = 1;
712 712 goto out;
713 713 }
714 714 }
715 715 nvlist_free(other_attrs);
716 716 }
717 717
718 718 out:
719 - if (media_attrs)
720 - nvlist_free(media_attrs);
721 - if (slice_attrs)
722 - nvlist_free(slice_attrs);
719 + nvlist_free(media_attrs);
720 + nvlist_free(slice_attrs);
723 721
724 722 if (slices)
725 723 dm_free_descriptors(slices);
726 724 if (media)
727 725 dm_free_descriptors(media);
728 726 if (slice)
729 727 dm_free_descriptor(slice);
730 728
731 729 return (ret);
732 730 }
733 731
734 732 /*
735 733 * Get the full list of swap entries. Returns -1 on error, or >= 0 to
736 734 * indicate the number of entries in the list. Callers are responsible
737 735 * for calling dm_free_swapentries() to deallocate memory. If this
738 736 * returns 0, the swaptbl_t still needs to be freed.
739 737 */
740 738 int
741 739 dm_get_swapentries(swaptbl_t **stp, int *errp)
742 740 {
743 741 int count, i;
744 742 swaptbl_t *tbl;
745 743 char *ptr;
746 744
747 745 *stp = NULL;
748 746
749 747 /* get number of swap entries */
750 748 if ((count = swapctl(SC_GETNSWP, NULL)) < 0) {
751 749 *errp = errno;
752 750 return (-1);
753 751 }
754 752
755 753 if (count == 0) {
756 754 return (0);
757 755 }
758 756
759 757 /* allocate space */
760 758 tbl = calloc(1, sizeof (int) + count * sizeof (swapent_t));
761 759 if (tbl == NULL) {
762 760 *errp = ENOMEM;
763 761 return (-1);
764 762 }
765 763
766 764 ptr = calloc(1, count * MAXPATHLEN);
767 765 if (ptr == NULL) {
768 766 *errp = ENOMEM;
769 767 free(tbl);
770 768 return (-1);
771 769 }
772 770
773 771 /* set up pointers to the pathnames */
774 772 tbl->swt_n = count;
775 773 for (i = 0; i < count; i++) {
776 774 tbl->swt_ent[i].ste_path = ptr;
777 775 ptr += MAXPATHLEN;
778 776 }
779 777
780 778 /* get list of swap paths */
781 779 count = swapctl(SC_LIST, tbl);
782 780 if (count < 0) {
783 781 *errp = errno;
784 782 free(ptr);
785 783 free(tbl);
786 784 return (-1);
787 785 }
788 786
789 787 *stp = tbl;
790 788 return (count);
791 789 }
792 790
793 791 /* ARGSUSED */
794 792 void
795 793 dm_free_swapentries(swaptbl_t *stp)
796 794 {
797 795 ASSERT(stp != NULL);
798 796
799 797 free(stp->swt_ent[0].ste_path);
800 798 free(stp);
801 799 }
802 800
803 801 /*
804 802 * Check a slice to see if it's being used by swap.
805 803 */
806 804 int
807 805 dm_inuse_swap(const char *dev_name, int *errp)
808 806 {
809 807 int count;
810 808 int found;
811 809 swaptbl_t *tbl = NULL;
812 810
813 811 *errp = 0;
814 812
815 813 count = dm_get_swapentries(&tbl, errp);
816 814 if (count < 0 || *errp) {
817 815 if (tbl)
818 816 dm_free_swapentries(tbl);
819 817 return (-1);
820 818 }
821 819
822 820 /* if there are no swap entries, we're done */
823 821 if (!count) {
824 822 return (0);
825 823 }
826 824
827 825 ASSERT(tbl != NULL);
828 826
829 827 found = 0;
830 828 while (count--) {
831 829 if (strcmp(dev_name, tbl->swt_ent[count].ste_path) == 0) {
832 830 found = 1;
833 831 break;
834 832 }
835 833 }
836 834
837 835 dm_free_swapentries(tbl);
838 836 return (found);
839 837 }
840 838
841 839 /*
842 840 * Returns 'in use' details, if found, about a specific dev_name,
843 841 * based on the caller(who). It is important to note that it is possible
844 842 * for there to be more than one 'in use' statistic regarding a dev_name.
845 843 * The **msg parameter returns a list of 'in use' details. This message
846 844 * is formatted via gettext().
847 845 */
848 846 int
849 847 dm_inuse(char *dev_name, char **msg, dm_who_type_t who, int *errp)
850 848 {
851 849 nvlist_t *dev_stats = NULL;
852 850 char *by, *data;
853 851 nvpair_t *nvwhat = NULL;
854 852 nvpair_t *nvdesc = NULL;
855 853 int found = 0;
856 854 int err;
857 855 char *dname = NULL;
858 856
859 857 *errp = 0;
860 858 *msg = NULL;
861 859
862 860 /*
863 861 * If the user doesn't want to do in use checking, return.
864 862 */
865 863
866 864 if (NOINUSE_SET)
867 865 return (0);
868 866
869 867 dname = getfullblkname(dev_name);
870 868 /*
871 869 * If we cannot find the block name, we cannot check the device
872 870 * for in use statistics. So, return found, which is == 0.
873 871 */
874 872 if (dname == NULL || *dname == '\0') {
875 873 return (found);
876 874 }
877 875
878 876 /*
879 877 * Slice stats for swap devices are only returned if mounted
880 878 * (e.g. /tmp). Other devices or files being used for swap
881 879 * are ignored, so we add a special check here to use swapctl(2)
882 880 * to perform in-use checking.
883 881 */
884 882 if (ANY_ZPOOL_USE(who) && (err = dm_inuse_swap(dname, errp))) {
885 883
886 884 /* on error, dm_inuse_swap sets errp */
887 885 if (err < 0) {
888 886 free(dname);
889 887 return (err);
890 888 }
891 889
892 890 /* simulate a mounted swap device */
893 891 (void) build_usage_string(dname, DM_USE_MOUNT, "swap", msg,
894 892 &found, errp);
895 893
896 894 /* if this fails, dm_get_usage_string changed */
897 895 ASSERT(found == 1);
898 896
899 897 free(dname);
900 898 return (found);
901 899 }
902 900
903 901 dm_get_slice_stats(dname, &dev_stats, errp);
904 902 if (dev_stats == NULL) {
905 903 /*
906 904 * If there is an error, but it isn't a no device found error
907 905 * return the error as recorded. Otherwise, with a full
908 906 * block name, we might not be able to get the slice
909 907 * associated, and will get an ENODEV error. For example,
910 908 * an SVM metadevice will return a value from getfullblkname()
911 909 * but libdiskmgt won't be able to find this device for
912 910 * statistics gathering. This is expected and we should not
913 911 * report errnoneous errors.
914 912 */
915 913 if (*errp) {
916 914 if (*errp == ENODEV) {
917 915 *errp = 0;
918 916 }
919 917 }
920 918 free(dname);
921 919 return (found);
922 920 }
923 921
924 922 for (;;) {
925 923
926 924 nvwhat = nvlist_next_nvpair(dev_stats, nvdesc);
927 925 nvdesc = nvlist_next_nvpair(dev_stats, nvwhat);
928 926
929 927 /*
930 928 * End of the list found.
931 929 */
932 930 if (nvwhat == NULL || nvdesc == NULL) {
933 931 break;
934 932 }
935 933 /*
936 934 * Otherwise, we check to see if this client(who) cares
937 935 * about this in use scenario
938 936 */
939 937
940 938 ASSERT(strcmp(nvpair_name(nvwhat), DM_USED_BY) == 0);
941 939 ASSERT(strcmp(nvpair_name(nvdesc), DM_USED_NAME) == 0);
942 940 /*
943 941 * If we error getting the string value continue on
944 942 * to the next pair(if there is one)
945 943 */
946 944 if (nvpair_value_string(nvwhat, &by)) {
947 945 continue;
948 946 }
949 947 if (nvpair_value_string(nvdesc, &data)) {
950 948 continue;
951 949 }
952 950
953 951 switch (who) {
954 952 case DM_WHO_MKFS:
955 953 /*
956 954 * mkfs is not in use for these cases.
957 955 * All others are in use.
958 956 */
959 957 if (strcmp(by, DM_USE_LU) == 0 ||
960 958 strcmp(by, DM_USE_FS) == 0 ||
961 959 strcmp(by, DM_USE_EXPORTED_ZPOOL) == 0) {
962 960 break;
963 961 }
964 962 if (build_usage_string(dname,
965 963 by, data, msg, &found, errp) != 0) {
966 964 if (*errp) {
967 965 goto out;
968 966 }
969 967 }
970 968 break;
971 969 case DM_WHO_SWAP:
972 970 /*
973 971 * Not in use for this.
974 972 */
975 973 if (strcmp(by, DM_USE_DUMP) == 0 ||
976 974 strcmp(by, DM_USE_FS) == 0 ||
977 975 strcmp(by, DM_USE_EXPORTED_ZPOOL) == 0) {
978 976 break;
979 977 }
980 978 if (strcmp(by, DM_USE_LU) == 0 &&
981 979 strcmp(data, "-") == 0) {
982 980 break;
983 981 }
984 982 if (strcmp(by, DM_USE_VFSTAB) == 0 &&
985 983 strcmp(data, "") == 0) {
986 984 break;
987 985 }
988 986 if (build_usage_string(dname,
989 987 by, data, msg, &found, errp) != 0) {
990 988 if (*errp) {
991 989 goto out;
992 990 }
993 991 }
994 992 break;
995 993 case DM_WHO_DUMP:
996 994 /*
997 995 * Not in use for this.
998 996 */
999 997 if ((strcmp(by, DM_USE_MOUNT) == 0 &&
1000 998 strcmp(data, "swap") == 0) ||
1001 999 strcmp(by, DM_USE_DUMP) == 0 ||
1002 1000 strcmp(by, DM_USE_FS) == 0 ||
1003 1001 strcmp(by, DM_USE_EXPORTED_ZPOOL) == 0) {
1004 1002 break;
1005 1003 }
1006 1004 if (build_usage_string(dname,
1007 1005 by, data, msg, &found, errp)) {
1008 1006 if (*errp) {
1009 1007 goto out;
1010 1008 }
1011 1009 }
1012 1010 break;
1013 1011
1014 1012 case DM_WHO_FORMAT:
1015 1013 if (strcmp(by, DM_USE_FS) == 0 ||
1016 1014 strcmp(by, DM_USE_EXPORTED_ZPOOL) == 0)
1017 1015 break;
1018 1016 if (build_usage_string(dname,
1019 1017 by, data, msg, &found, errp) != 0) {
1020 1018 if (*errp) {
1021 1019 goto out;
1022 1020 }
1023 1021 }
1024 1022 break;
1025 1023
1026 1024 case DM_WHO_ZPOOL_FORCE:
1027 1025 if (strcmp(by, DM_USE_FS) == 0 ||
1028 1026 strcmp(by, DM_USE_EXPORTED_ZPOOL) == 0)
1029 1027 break;
1030 1028 /* FALLTHROUGH */
1031 1029 case DM_WHO_ZPOOL:
1032 1030 if (build_usage_string(dname,
1033 1031 by, data, msg, &found, errp) != 0) {
1034 1032 if (*errp)
1035 1033 goto out;
1036 1034 }
1037 1035 break;
1038 1036
1039 1037 case DM_WHO_ZPOOL_SPARE:
1040 1038 if (strcmp(by, DM_USE_SPARE_ZPOOL) != 0) {
1041 1039 if (build_usage_string(dname, by,
1042 1040 data, msg, &found, errp) != 0) {
1043 1041 if (*errp)
1044 1042 goto out;
1045 1043 }
1046 1044 }
1047 1045 break;
1048 1046
1049 1047 default:
↓ open down ↓ |
317 lines elided |
↑ open up ↑ |
1050 1048 /*
1051 1049 * nothing found in use for this client
1052 1050 * of libdiskmgt. Default is 'not in use'.
1053 1051 */
1054 1052 break;
1055 1053 }
1056 1054 }
1057 1055 out:
1058 1056 if (dname != NULL)
1059 1057 free(dname);
1060 - if (dev_stats != NULL)
1061 - nvlist_free(dev_stats);
1058 + nvlist_free(dev_stats);
1062 1059
1063 1060 return (found);
1064 1061 }
1065 1062
1066 1063 void
1067 1064 dm_get_usage_string(char *what, char *how, char **usage_string)
1068 1065 {
1069 1066
1070 1067
1071 1068 if (usage_string == NULL || what == NULL) {
1072 1069 return;
1073 1070 }
1074 1071 *usage_string = NULL;
1075 1072
1076 1073 if (strcmp(what, DM_USE_MOUNT) == 0) {
1077 1074 if (strcmp(how, "swap") == 0) {
1078 1075 *usage_string = dgettext(TEXT_DOMAIN,
1079 1076 "%s is currently used by swap. Please see swap(1M)."
1080 1077 "\n");
1081 1078 } else {
1082 1079 *usage_string = dgettext(TEXT_DOMAIN,
1083 1080 "%s is currently mounted on %s."
1084 1081 " Please see umount(1M).\n");
1085 1082 }
1086 1083 } else if (strcmp(what, DM_USE_VFSTAB) == 0) {
1087 1084 *usage_string = dgettext(TEXT_DOMAIN,
1088 1085 "%s is normally mounted on %s according to /etc/vfstab. "
1089 1086 "Please remove this entry to use this device.\n");
1090 1087 } else if (strcmp(what, DM_USE_FS) == 0) {
1091 1088 *usage_string = dgettext(TEXT_DOMAIN,
1092 1089 "%s contains a %s filesystem.\n");
1093 1090 } else if (strcmp(what, DM_USE_SVM) == 0) {
1094 1091 if (strcmp(how, "mdb") == 0) {
1095 1092 *usage_string = dgettext(TEXT_DOMAIN,
1096 1093 "%s contains an SVM %s. Please see "
1097 1094 "metadb(1M).\n");
1098 1095 } else {
1099 1096 *usage_string = dgettext(TEXT_DOMAIN,
1100 1097 "%s is part of SVM volume %s. "
1101 1098 "Please see metaclear(1M).\n");
1102 1099 }
1103 1100 } else if (strcmp(what, DM_USE_VXVM) == 0) {
1104 1101 *usage_string = dgettext(TEXT_DOMAIN,
1105 1102 "%s is part of VxVM volume %s.\n");
1106 1103 } else if (strcmp(what, DM_USE_LU) == 0) {
1107 1104 *usage_string = dgettext(TEXT_DOMAIN,
1108 1105 "%s is in use for live upgrade %s. Please see ludelete(1M)."
1109 1106 "\n");
1110 1107 } else if (strcmp(what, DM_USE_DUMP) == 0) {
1111 1108 *usage_string = dgettext(TEXT_DOMAIN,
1112 1109 "%s is in use by %s. Please see dumpadm(1M)."
1113 1110 "\n");
1114 1111 } else if (strcmp(what, DM_USE_EXPORTED_ZPOOL) == 0) {
1115 1112 *usage_string = dgettext(TEXT_DOMAIN,
1116 1113 "%s is part of exported or potentially active ZFS pool %s. "
1117 1114 "Please see zpool(1M).\n");
1118 1115 } else if (strcmp(what, DM_USE_ACTIVE_ZPOOL) == 0) {
1119 1116 *usage_string = dgettext(TEXT_DOMAIN,
1120 1117 "%s is part of active ZFS pool %s. Please see zpool(1M)."
1121 1118 "\n");
1122 1119 } else if (strcmp(what, DM_USE_SPARE_ZPOOL) == 0) {
1123 1120 *usage_string = dgettext(TEXT_DOMAIN,
1124 1121 "%s is reserved as a hot spare for ZFS pool %s. Please "
1125 1122 "see zpool(1M).\n");
1126 1123 } else if (strcmp(what, DM_USE_L2CACHE_ZPOOL) == 0) {
1127 1124 *usage_string = dgettext(TEXT_DOMAIN,
1128 1125 "%s is in use as a cache device for ZFS pool %s. "
1129 1126 "Please see zpool(1M).\n");
1130 1127 }
1131 1128 }
1132 1129 void
1133 1130 libdiskmgt_add_str(nvlist_t *attrs, char *name, char *val, int *errp)
1134 1131 {
1135 1132 if (*errp == 0) {
1136 1133 *errp = nvlist_add_string(attrs, name, val);
1137 1134 }
1138 1135 }
1139 1136
1140 1137 descriptor_t **
1141 1138 libdiskmgt_empty_desc_array(int *errp)
1142 1139 {
1143 1140 descriptor_t **empty;
1144 1141
1145 1142 empty = (descriptor_t **)calloc(1, sizeof (descriptor_t *));
1146 1143 if (empty == NULL) {
1147 1144 *errp = ENOMEM;
1148 1145 return (NULL);
1149 1146 }
1150 1147 empty[0] = NULL;
1151 1148
1152 1149 *errp = 0;
1153 1150 return (empty);
1154 1151 }
1155 1152
1156 1153 void
1157 1154 libdiskmgt_init_debug()
1158 1155 {
1159 1156 char *valp;
1160 1157
1161 1158 if ((valp = getenv(DM_DEBUG)) != NULL) {
1162 1159 dm_debug = atoi(valp);
1163 1160 }
1164 1161 }
1165 1162
1166 1163 int
1167 1164 libdiskmgt_str_eq(char *nm1, char *nm2)
1168 1165 {
1169 1166 if (nm1 == NULL) {
1170 1167 if (dm_debug) {
1171 1168 (void) fprintf(stderr, "WARNING: str_eq nm1 NULL\n");
1172 1169 }
1173 1170
1174 1171 if (nm2 == NULL) {
1175 1172 return (1);
1176 1173 } else {
1177 1174 return (0);
1178 1175 }
1179 1176 }
1180 1177
1181 1178 /* nm1 != NULL */
1182 1179
1183 1180 if (nm2 == NULL) {
1184 1181 if (dm_debug) {
1185 1182 (void) fprintf(stderr, "WARNING: str_eq nm2 NULL\n");
1186 1183 }
1187 1184 return (0);
1188 1185 }
1189 1186
1190 1187 if (strcmp(nm1, nm2) == 0) {
1191 1188 return (1);
1192 1189 }
1193 1190
1194 1191 return (0);
1195 1192 }
1196 1193
1197 1194 /*ARGSUSED*/
1198 1195 static descriptor_t **
1199 1196 desc_array_to_ptr_array(dm_descriptor_t *descs, int *errp)
1200 1197 {
1201 1198 #ifdef _LP64
1202 1199 return ((descriptor_t **)descs);
1203 1200 #else
1204 1201 /* convert the 64 bit descriptors to 32 bit ptrs */
1205 1202 int cnt;
1206 1203 int i;
1207 1204 descriptor_t **da;
1208 1205
1209 1206 for (cnt = 0; descs[cnt]; cnt++)
1210 1207 ;
1211 1208
1212 1209 da = (descriptor_t **)calloc(cnt + 1, sizeof (descriptor_t *));
1213 1210 if (da == NULL) {
1214 1211 *errp = ENOMEM;
1215 1212 return (NULL);
1216 1213 }
1217 1214
1218 1215 for (i = 0; descs[i]; i++) {
1219 1216 da[i] = (descriptor_t *)(uintptr_t)descs[i];
1220 1217 }
1221 1218 *errp = 0;
1222 1219 free(descs);
1223 1220
1224 1221 return (da);
1225 1222 #endif
1226 1223 }
1227 1224
1228 1225 /*ARGSUSED*/
1229 1226 static dm_descriptor_t *
1230 1227 ptr_array_to_desc_array(descriptor_t **ptrs, int *errp)
1231 1228 {
1232 1229 #ifdef _LP64
1233 1230 return ((dm_descriptor_t *)ptrs);
1234 1231 #else
1235 1232 /* convert the 32 bit ptrs to the 64 bit descriptors */
1236 1233 int cnt;
1237 1234 int i;
1238 1235 dm_descriptor_t *da;
1239 1236
1240 1237 if (*errp != 0 || ptrs == NULL) {
1241 1238 return (NULL);
1242 1239 }
1243 1240
1244 1241 for (cnt = 0; ptrs[cnt]; cnt++)
1245 1242 ;
1246 1243
1247 1244 da = (dm_descriptor_t *)calloc(cnt + 1, sizeof (dm_descriptor_t));
1248 1245 if (da == NULL) {
1249 1246 *errp = ENOMEM;
1250 1247 return (NULL);
1251 1248 }
1252 1249
1253 1250 for (i = 0; ptrs[i]; i++) {
1254 1251 da[i] = (uintptr_t)ptrs[i];
1255 1252 }
1256 1253 *errp = 0;
1257 1254 free(ptrs);
1258 1255
1259 1256 return (da);
1260 1257 #endif
1261 1258 }
1262 1259 /*
1263 1260 * Build the usage string for the in use data. Return the build string in
1264 1261 * the msg parameter. This function takes care of reallocing all the memory
1265 1262 * for this usage string. Usage string is returned already formatted for
1266 1263 * localization.
1267 1264 */
1268 1265 static int
1269 1266 build_usage_string(char *dname, char *by, char *data, char **msg,
1270 1267 int *found, int *errp)
1271 1268 {
1272 1269 int len0;
1273 1270 int len1;
1274 1271 char *use;
1275 1272 char *p;
1276 1273
1277 1274 *errp = 0;
1278 1275
1279 1276 dm_get_usage_string(by, data, &use);
1280 1277 if (!use) {
1281 1278 return (-1);
1282 1279 }
1283 1280
1284 1281 if (*msg)
1285 1282 len0 = strlen(*msg);
1286 1283 else
1287 1284 len0 = 0;
1288 1285 /* LINTED */
1289 1286 len1 = snprintf(NULL, 0, use, dname, data);
1290 1287
1291 1288 /*
1292 1289 * If multiple in use details they
1293 1290 * are listed 1 per line for ease of
1294 1291 * reading. dm_find_usage_string
1295 1292 * formats these appropriately.
1296 1293 */
1297 1294 if ((p = realloc(*msg, len0 + len1 + 1)) == NULL) {
1298 1295 *errp = errno;
1299 1296 free(*msg);
1300 1297 return (-1);
1301 1298 }
1302 1299 *msg = p;
1303 1300
1304 1301 /* LINTED */
1305 1302 (void) snprintf(*msg + len0, len1 + 1, use, dname, data);
1306 1303 (*found)++;
1307 1304 return (0);
1308 1305 }
↓ open down ↓ |
237 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX