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 <string.h> 30 31 #include <libintl.h> 32 33 #include "metassist.h" 34 #include "volume_dlist.h" 35 #include "volume_error.h" 36 #include "volume_string.h" 37 #include "volume_output.h" 38 39 #define _LAYOUT_VALIDATE_C 40 41 #include "layout_discovery.h" 42 #include "layout_dlist_util.h" 43 #include "layout_device_cache.h" 44 #include "layout_device_util.h" 45 #include "layout_request.h" 46 #include "layout_slice.h" 47 #include "layout_svm_util.h" 48 #include "layout_validate.h" 49 50 /* 51 * This module contains the majority of the validation code which 52 * layout applies to input requests. The assumption/agreement with 53 * the controller implementation is that requests passed into layout 54 * have undergone syntactic validation and that layout is responsible 55 * for semantic validation. 56 * 57 * The semantic validation that is handled: 58 * 59 * 1. For a toplevel diskset request, validate: 60 * 61 * - the number of disksets is not exceeded 62 * - the number of devices is not exceeded 63 * 64 * (These items are not directly validated within this module, 65 * but it is useful to document that they are handled somewhere). 66 * 67 * 2. For any devconfig_t representing a volume request, verify that: 68 * 69 * - all HSP names are semantically valid. The name should conform 70 * to the HSP naming convention: hspXXX. 71 * 72 * - all concat, stripe, mirror, and volume names refer to 73 * unused, semantically valid metadevice names. Examples of 74 * bad data: 75 * 76 * - a valid volume name that is already in use (d0, d10) 77 * 78 * - a valid volume name that is used two or more times to 79 * refer to new elements in the request. 80 * 81 * - a valid volume name that is out of range (d99877, 82 * d44356) or exceeds the maximum number of possible 83 * volumes given the current SVM configuration. 84 * 85 * - all available and unavailable device specifications refer 86 * to existing controllers, disks, or slices on the system. 87 * Examples of bad data: 88 * 89 * - a valid but non-existent controller (c23, c2) 90 * - a valid but non-existent disk (c0t0d8, c1t0d0) 91 * - a valid slice on a non-existent disk or controller 92 * (c0t0d8s7, c1t0d05) 93 * - a valid slice on an existing disk (c0t0d0s12, 94 * c0t0d0s9) 95 * 96 * - any typed volume request that explicitly specifies components 97 * requires additional validation to detect syntactically valid 98 * expressions that are semantically ambiguous: 99 * 100 * a concat request that: 101 * - specifies size and components is invalid 102 * 103 * a stripe request that: 104 * - specifies size and components is invalid 105 * - specifies mincomp and components but not enough 106 * components is invalid 107 * - specifies maxcomp and components but too many 108 * components is invalid 109 * 110 * a HSP request that: 111 * - specifies components that are not appropriate for 112 * the volumes the HSP serves is invalid (?) 113 * 114 * a stripe, concat or HSP request that: 115 * - specifies a component that was used in a prior 116 * request is invalid 117 * - specifies a component that does not exist in the 118 * diskset is invalid (e.g., c0t0d0s0, but c0t0d0 is 119 * not yet in the diskset) 120 * 121 * a mirror request that: 122 * - specifies nsubs and components but not enough 123 * components is invalid 124 * - specifies components and the components specify 125 * different sizes results in a WARNING since the total 126 * usable capacity of the mirror is determined by the 127 * smallest of its submirrors. 128 * - specifies components and the components specify 129 * components results in a WARNING since the submirrors 130 * may end up with different sizes 131 */ 132 static int validate_request_name( 133 devconfig_t *req, 134 component_type_t type); 135 136 static int validate_request_size( 137 devconfig_t *req, 138 component_type_t type); 139 140 static int validate_minimum_size( 141 uint64_t nbytes); 142 143 static uint64_t apply_layout_overhead_factor( 144 uint64_t req_size); 145 146 static int get_space_available_for_request( 147 devconfig_t *request, 148 dlist_t *usable_slices, 149 uint64_t *avail_space); 150 151 static int do_available_space_check( 152 uint64_t req_size, 153 uint64_t raw_avail_space, 154 devconfig_t *request, 155 dlist_t *usable_slices); 156 157 static int validate_request_redundancy_level( 158 devconfig_t *req); 159 160 static int validate_request_npaths( 161 devconfig_t *req); 162 163 static int validate_request_submirrors( 164 devconfig_t *req); 165 166 static int validate_submirror_types( 167 dlist_t *submirrors); 168 169 static int validate_submirror_number( 170 devconfig_t *req, 171 dlist_t *submirrors); 172 173 static int validate_submirror_sizes( 174 devconfig_t *req, 175 dlist_t *submirrors); 176 177 static int validate_submirror_size_and_components( 178 devconfig_t *submir, 179 uint64_t mirror_size, 180 uint64_t *assumed_size, 181 dlist_t **submirs_with_size, 182 dlist_t **submirs_with_comps, 183 dlist_t **submirs_no_size_or_comps); 184 185 static int validate_slice_components( 186 devconfig_t *req, 187 component_type_t type); 188 189 static char *get_device_aliases_string( 190 dm_descriptor_t desc); 191 192 static int validate_device_array( 193 char **array, 194 char *which, 195 dlist_t **list); 196 197 static int add_reserved_name(char *name); 198 static boolean_t is_rsvd_name(char *name); 199 static dlist_t *_rsvd_names = NULL; 200 201 /* 202 * FUNCTION: release_validatation_caches() 203 * 204 * RETURNS: int - 0 205 * 206 * PURPOSE: Cleanup function. 207 * 208 * Purges list of reserved volume names. Should be called 209 * after all layout requests have been processed. 210 */ 211 int 212 release_validation_caches() 213 { 214 dlist_free_items(_rsvd_names, NULL); 215 _rsvd_names = NULL; 216 217 return (0); 218 } 219 220 /* 221 * FUNCTION: validate_basic_svm_config() 222 * 223 * RETURNS: int - 0 on success 224 * !0 on failure 225 * 226 * PURPOSE: Check to see if the local set metadb replicas have been created. 227 * 228 * Makes sure at least 1 metadb replica exists for the local set. 229 */ 230 int 231 validate_basic_svm_config() 232 { 233 int error = 0; 234 int nreplicas = 0; 235 236 if ((error = get_n_metadb_replicas(&nreplicas)) == 0) { 237 if (nreplicas == 0) { 238 volume_set_error( 239 gettext("Failed: State database replicas must " 240 "exist before using %s.\n" 241 "See metadb(1M) and %s(1M)."), 242 progname, progname); 243 error = -1; 244 } else { 245 oprintf(OUTPUT_DEBUG, 246 gettext("%d metadb replicas found.\n"), 247 nreplicas); 248 } 249 } 250 251 return (error); 252 } 253 254 /* 255 * FUNCTION: validate_request_sizes(devconfig_t *req) 256 * 257 * INPUT: req: a devconfig_t pointer to the toplevel request 258 * 259 * RETURNS: int - 0 on success 260 * !0 on failure 261 * 262 * PURPOSE: Check to see if the any of the individual volume request 263 * sizes exceeds the raw available space on the system or 264 * the space available to that specific request. 265 * 266 * Check to see if the total space for all requests exceeds 267 * the raw available space. 268 * 269 * If any check fails, stop checking, emit an error and 270 * return -1. 271 * 272 * Note: this function must be called after the slice 273 * usages have been determined and the list of usable 274 * slices has been generated. 275 */ 276 int 277 validate_request_sizes( 278 devconfig_t *request) 279 { 280 int error = 0; 281 dlist_t *usable_slices; 282 dlist_t *iter; 283 char bad_rqst_info[BUFSIZ]; 284 uint64_t bad_rqst_space = 0; 285 uint64_t total_rqst_space = 0; 286 uint64_t raw_space = 0; 287 288 (void) get_usable_slices(&usable_slices); 289 290 /* 291 * calculate raw available space: space on slices that are 292 * "available" based on the diskset defaults or global defaults 293 */ 294 if ((error = get_space_available_for_request(request, 295 usable_slices, &raw_space)) != 0) { 296 return (error); 297 } 298 299 if (raw_space == 0) { 300 volume_set_error( 301 gettext("Failed: there is no available space.\n")); 302 return (-1); 303 } 304 305 /* deduct sizes of reserved components */ 306 (void) get_reserved_slices(&iter); 307 for (; (iter != NULL) && (raw_space != 0) && (error == 0); 308 iter = iter->next) { 309 dm_descriptor_t slice = (uintptr_t)iter->obj; 310 uint64_t nbytes; 311 if ((error = slice_get_size(slice, &nbytes)) == 0) { 312 if (raw_space >= nbytes) { 313 raw_space -= nbytes; 314 } else { 315 raw_space = 0; 316 } 317 } 318 } 319 320 /* 321 * check each volume request's size against raw_space, 322 * if that looks ok, do a closer check with the request's 323 * available devices 324 */ 325 iter = devconfig_get_components(request); 326 for (; (iter != NULL) && (error == 0); iter = iter->next) { 327 328 devconfig_t *req = (devconfig_t *)iter->obj; 329 component_type_t type = TYPE_UNKNOWN; 330 char *typestr = NULL; 331 uint64_t nbytes = 0; 332 333 (void) devconfig_get_type(req, &type); 334 if (type == TYPE_HSP) { 335 continue; 336 } 337 338 typestr = devconfig_type_to_str(type); 339 340 if ((error = devconfig_get_size(req, &nbytes)) == 0) { 341 342 /* check specified size */ 343 344 if (type == TYPE_CONCAT || type == TYPE_STRIPE) { 345 if ((error = do_available_space_check( 346 apply_layout_overhead_factor(nbytes), 347 raw_space, req, usable_slices)) == 0) { 348 total_rqst_space += nbytes; 349 } else if (error == ENOSPC || error == E2BIG) { 350 (void) snprintf(bad_rqst_info, BUFSIZ-1, 351 "%s", typestr); 352 bad_rqst_space = nbytes; 353 } 354 } else if (type == TYPE_MIRROR) { 355 uint16_t nsubs = 0; 356 if ((error = get_mirror_nsubs(req, &nsubs)) == 0) { 357 if ((error = do_available_space_check( 358 apply_layout_overhead_factor(nbytes * nsubs), 359 raw_space, req, usable_slices)) == 0) { 360 total_rqst_space += (nsubs * nbytes); 361 } else { 362 (void) snprintf(bad_rqst_info, BUFSIZ-1, 363 gettext("%s with %d submirrors"), 364 typestr, nsubs); 365 bad_rqst_space = nbytes; 366 } 367 } 368 } 369 370 } else if ((error == ERR_ATTR_UNSET) && (type == TYPE_MIRROR)) { 371 372 /* mirror specified no size: find submirror that does */ 373 374 dlist_t *subs = devconfig_get_components(req); 375 376 error = 0; 377 if (subs != NULL) { 378 dlist_t *iter2; 379 int nsubs = dlist_length(subs); 380 for (iter2 = subs; 381 (iter2 != NULL) && (error == 0); 382 iter2 = iter2->next) { 383 devconfig_t *sub = (devconfig_t *)iter2->obj; 384 if ((error = devconfig_get_size(sub, &nbytes)) == 0) { 385 if ((error = do_available_space_check( 386 apply_layout_overhead_factor(nbytes * nsubs), 387 raw_space, req, usable_slices)) == 0) { 388 total_rqst_space += (nbytes * nsubs); 389 } else { 390 (void) snprintf(bad_rqst_info, BUFSIZ-1, 391 gettext("%s with %d submirrors"), 392 typestr, nsubs); 393 bad_rqst_space = nbytes; 394 } 395 break; 396 } else if (error == ERR_ATTR_UNSET) { 397 error = 0; 398 } 399 } 400 } 401 } 402 } 403 404 /* 405 * do_available_space_check may return ENOSPC or E2BIG 406 */ 407 if (error == ENOSPC) { 408 char *sizestr = NULL; 409 (void) bytes_to_sizestr(bad_rqst_space, 410 &sizestr, universal_units, B_FALSE); 411 412 volume_set_error( 413 gettext("Failed: the request for a %s %s " 414 "exceeds the available space.\n"), 415 sizestr, bad_rqst_info); 416 417 free(sizestr); 418 error = -1; 419 420 } else if (error == E2BIG) { 421 char *sizestr = NULL; 422 (void) bytes_to_sizestr(bad_rqst_space, 423 &sizestr, universal_units, B_FALSE); 424 425 volume_set_error( 426 gettext("Failed: the request for a %s %s " 427 "exceeds the usable space on the device(s) " 428 "specified as available.\n"), 429 sizestr, bad_rqst_info); 430 431 free(sizestr); 432 error = -1; 433 434 } else if (apply_layout_overhead_factor(total_rqst_space) > raw_space) { 435 char *sizestr = NULL; 436 (void) bytes_to_sizestr( 437 total_rqst_space, &sizestr, universal_units, B_FALSE); 438 439 volume_set_error( 440 gettext("Failed: the total space requested for the " 441 "volumes (about %s) exceeds the available " 442 "space.\n"), 443 sizestr); 444 445 free(sizestr); 446 error = -1; 447 } 448 449 return (error); 450 } 451 452 /* 453 * FUNCTION: apply_layout_overhead_factor(uint64_t req_size) 454 * 455 * INPUT: req_size: a requested volume size 456 * 457 * RETURNS: the requested volume size with an overhead factor applied 458 * 459 * PURPOSE: The input size size is inflated by a "fudge" factor 460 * to account for some of the expected overhead required for 461 * volumes such as block and cylinder boundary alignment. 462 */ 463 static uint64_t 464 apply_layout_overhead_factor( 465 uint64_t req_size) 466 { 467 double overhead = 1.15; 468 double d_size = req_size; 469 uint64_t result = (uint64_t)(d_size * overhead); 470 471 return (result); 472 } 473 474 /* 475 * FUNCTION: get_space_available_for_request(devconfig_t *request, 476 * dlist_t *usable_slices, uint64_t *avail_space) 477 * 478 * INPUT: request: a devconfig_t volume request 479 * usable_slices: a list of usable slice dm_descriptor_t handles 480 * 481 * OUTPUT: avail_space: the total space on slices in the usable_slice 482 * list that is available for use by the input 483 * request. 484 * 485 * RETURNS: int - 0 on success 486 * !0 on failure 487 * 488 * PURPOSE: Iterate the input list of usable slices, determine which are 489 * available to the input request and accumulate the total space 490 * they represent. 491 * 492 * The slices in the usable_slice list are those with no apparent 493 * usage detected. The slice_is_available() check determines 494 * whether the slice passes the available/unavailable device 495 * specification associated with the input request. 496 */ 497 static int 498 get_space_available_for_request( 499 devconfig_t *request, 500 dlist_t *usable_slices, 501 uint64_t *avail_space) 502 { 503 dlist_t *iter; 504 int error = 0; 505 506 *avail_space = 0; 507 508 for (iter = usable_slices; 509 (iter != NULL) && (error == 0); 510 iter = iter->next) { 511 dm_descriptor_t slice = (uintptr_t)iter->obj; 512 char *sname; 513 uint64_t nbytes; 514 boolean_t avail = B_FALSE; 515 if ((error = get_display_name(slice, &sname)) == 0) { 516 if ((error = slice_is_available(sname, request, &avail)) == 0) { 517 if (avail == B_TRUE) { 518 if ((error = slice_get_size(slice, &nbytes)) == 0) { 519 *avail_space += nbytes; 520 } 521 } 522 } 523 } 524 } 525 526 return (error); 527 } 528 529 /* 530 * FUNCTION: do_available_space_check(uint64_t req_size, 531 * uint64_t raw_avail_space, devconfig_t *request, 532 * dlist_t *usable_slices) 533 * 534 * INPUT: req_size: the requested size of a volume 535 * raw_avail_space:the total available space for all volumes 536 * request: a devconfig_t volume request 537 * usable_slices: a list of usable slice dm_descriptor_t handles 538 * 539 * RETURNS: int - ENOSPC if the requested size exceeds the raw 540 * available space. 541 * 542 * E2BIG if the requested size exceeds the space 543 * available specifically to the input request, 544 * taking into account its available and 545 * unavailable device specifications. 546 * 547 * 0 otherwise 548 * 549 * PURPOSE: Check the input request size against different forms of 550 * available space. 551 * 552 * If the requested size is less than the raw_avail_space, do the 553 * more expensive check against the space specifically available 554 * to the input request. 555 */ 556 static int 557 do_available_space_check( 558 uint64_t req_size, 559 uint64_t raw_avail_space, 560 devconfig_t *request, 561 dlist_t *usable_slices) 562 { 563 int error = 0; 564 565 if (req_size > raw_avail_space) { 566 error = ENOSPC; 567 } else { 568 uint64_t avail_space = 0; 569 if ((error = get_space_available_for_request(request, 570 usable_slices, &avail_space)) == 0) { 571 if (req_size > avail_space) { 572 error = E2BIG; 573 } 574 } 575 } 576 577 return (error); 578 } 579 580 /* 581 * FUNCTION: validate_request(devconfig_t *req) 582 * 583 * INPUT: req - a devconfig_t representing a volume layout request. 584 * 585 * RETURNS: int - 0 if the request passes validation 586 * !0 otherwise. 587 * 588 * PURPOSE: Main entry point into the layout request semantic 589 * validatation. 590 * 591 * Determines the type of volume requested and invokes the 592 * appropriate validation functions. 593 */ 594 int 595 validate_request( 596 devconfig_t *req) 597 { 598 int error = 0; 599 component_type_t type = TYPE_UNKNOWN; 600 601 ((error = validate_request_avail_unavail(req)) != 0) || 602 (error = devconfig_get_type(req, &type)); 603 if (error != 0) { 604 return (error); 605 } 606 607 if (type == TYPE_MIRROR) { 608 609 ((error = validate_request_name(req, type)) != 0) || 610 (error = validate_request_size(req, type)) || 611 (error = validate_request_submirrors(req)); 612 613 } else if (type == TYPE_CONCAT || type == TYPE_STRIPE) { 614 615 ((error = validate_request_name(req, type)) != 0) || 616 (error = validate_request_size(req, type)) || 617 (error = validate_slice_components(req, type)); 618 619 } else if (type == TYPE_HSP) { 620 621 ((error = validate_request_name(req, type)) != 0) || 622 (error = validate_slice_components(req, type)); 623 624 } else if (type == TYPE_VOLUME) { 625 626 ((error = validate_request_name(req, type)) != 0) || 627 (error = validate_request_redundancy_level(req)) || 628 (error = validate_request_npaths(req)); 629 630 } 631 632 return (error); 633 } 634 635 /* 636 * FUNCTION: validate_reserved_slices() 637 * 638 * RETURNS: int - 0 if all reserved slices are usable in 639 * new devices. 640 * !0 otherwise. 641 * 642 * PURPOSE: Ensures that each reserved slice is actually usable 643 * as a volume component. 644 * 645 * Retrieves list of reserved slices and list of usable 646 * slices. Ensures that each reserved slice is in the 647 * usable list, generates an error if it is not. 648 * 649 * This is broken out as a separate function because 650 * initial validation is using the lists of all known 651 * devices. Device "usability" is only determined after 652 * the initial validation has completed successfully. 653 */ 654 int 655 validate_reserved_slices() 656 { 657 dlist_t *reserved_slices; 658 dlist_t *usable_slices; 659 int error = 0; 660 661 ((error = get_reserved_slices(&reserved_slices)) != 0) || 662 (error = get_usable_slices(&usable_slices)); 663 if (error == 0) { 664 665 dlist_t *iter; 666 for (iter = reserved_slices; 667 (iter != NULL) && (error == 0); 668 iter = iter->next) { 669 670 if (dlist_contains(usable_slices, iter->obj, 671 compare_descriptor_names) != B_TRUE) { 672 673 dm_descriptor_t slice = (uintptr_t)iter->obj; 674 char *name = NULL; 675 676 error = get_display_name(slice, &name); 677 if (error == 0) { 678 char *aliases = get_device_aliases_string(slice); 679 if (aliases[0] != NULL) { 680 volume_set_error( 681 gettext("A requested volume component " 682 "is currently in use: \"%s\" " 683 "(aliases: %s).\n"), 684 name, aliases); 685 } else { 686 volume_set_error( 687 gettext("A requested volume component " 688 "is currently in use: \"%s\"\n"), 689 name); 690 } 691 error = -1; 692 } 693 } 694 } 695 } 696 697 return (error); 698 } 699 700 /* 701 * FUNCTION: validate_request_avail_unavail(devconfig_t *req) 702 * 703 * INPUT: req - a devconfig_t representing a volume layout request. 704 * 705 * RETURNS: int - 0 if the request passes validation 706 * !0 otherwise. 707 * 708 * PURPOSE: validation function for a request's lists of available 709 * and unavailable devices. 710 * 711 * validates that both lists contain names of known devices. 712 * 713 * validates that the same name does not appear in both lists. 714 */ 715 int 716 validate_request_avail_unavail( 717 devconfig_t *req) 718 { 719 dlist_t *avail = NULL; 720 dlist_t *unavail = NULL; 721 int error = 0; 722 723 /* check that each array contains valid devices */ 724 ((error = validate_device_array(devconfig_get_available(req), 725 gettext("available"), &avail)) != 0) || 726 (error = validate_device_array(devconfig_get_unavailable(req), 727 gettext("unavailable"), &unavail)); 728 729 /* check that the arrays don't both contain the same device(s) */ 730 if (error == 0) { 731 dlist_t *iter; 732 for (iter = avail; iter != NULL; iter = iter->next) { 733 if (dlist_contains(unavail, iter->obj, 734 compare_descriptor_names) == B_TRUE) { 735 char *name; 736 char *aliases = 737 get_device_aliases_string((uintptr_t)iter->obj); 738 739 (void) get_display_name((uintptr_t)iter->obj, &name); 740 if (aliases[0] != NULL) { 741 volume_set_error( 742 gettext("\"%s\" specified as both available " 743 "and unavailable.\n" 744 "It has these aliases: %s\n"), 745 name, aliases); 746 } else { 747 volume_set_error( 748 gettext("\"%s\" specified as both available " 749 "and unavailable.\n"), 750 name); 751 } 752 error = -1; 753 break; 754 } 755 } 756 } 757 758 dlist_free_items(avail, NULL); 759 dlist_free_items(unavail, NULL); 760 761 return (error); 762 } 763 764 /* 765 * FUNCTION: validate_device_array(char **array, char *which, dlist_t **list) 766 * 767 * INPUT: array - an array of char * device names 768 * which - either "available" or "unavailable" 769 * indicating the array name to use in 770 * error strings. 771 * OUTPUT: list - a list of device descriptors corresponding the each 772 * of the input names. 773 * 774 * RETURNS: int - 0 if the array passes validation 775 * !0 otherwise. 776 * 777 * PURPOSE: validation function for a request's list of available 778 * or unavailable devices. 779 * 780 * DID names are converted to CTD names. 781 * 782 * The CTD name must be of an available slice, disk or 783 * HBA, or a known used slice, disk or HBA that was 784 * discovered when the system's devices were probed. 785 * 786 * Any other name is assumed to refer to a device not 787 * attached to the system and results in a validation 788 * failure. 789 * 790 * Descriptors for validated devices are added to the input 791 * list. 792 */ 793 int 794 validate_device_array( 795 char **array, 796 char *which, 797 dlist_t **list) 798 { 799 int error = 0; 800 int i = 0; 801 802 if (array == NULL || *array == NULL) { 803 return (0); 804 } 805 806 for (i = 0; (array[i] != NULL) && (error == 0); i++) { 807 808 dm_descriptor_t slice = (dm_descriptor_t)0; 809 dm_descriptor_t disk = (dm_descriptor_t)0; 810 dm_descriptor_t hba = (dm_descriptor_t)0; 811 char *name = array[i]; 812 813 /* name must correspond to a known HBA, disk, or slice */ 814 if ((error = hba_get_by_name(name, &hba)) == 0) { 815 if (hba == (dm_descriptor_t)0) { 816 if ((error = disk_get_by_name(name, &disk)) == 0) { 817 if (disk == (dm_descriptor_t)0) { 818 error = slice_get_by_name(name, &slice); 819 } 820 } 821 } 822 } 823 824 if (error != 0) { 825 break; 826 } 827 828 /* 0 sized slices cannot be used as-is, pretend non-existant */ 829 if (slice != (dm_descriptor_t)0) { 830 uint64_t size = 0; 831 if ((error = slice_get_size(slice, &size)) == 0) { 832 if (size == 0) { 833 slice = (dm_descriptor_t)0; 834 } 835 } 836 } 837 838 oprintf(OUTPUT_DEBUG, 839 gettext(" validate %s (%s): s=%llu, d=%llu, c=%llu\n"), 840 which, array[i], slice, disk, hba); 841 842 if ((error == 0) && ((slice != 0) || (disk != 0) || (hba != 0))) { 843 844 /* name represents an individual "device", add it to the list */ 845 dm_descriptor_t desc = (dm_descriptor_t)0; 846 dlist_t *item; 847 848 if (slice != 0) { 849 desc = slice; 850 } else if (disk != 0) { 851 desc = disk; 852 } else if (hba != 0) { 853 desc = hba; 854 } 855 856 if ((item = dlist_new_item((void *)(uintptr_t)desc)) == NULL) { 857 error = ENOMEM; 858 } else { 859 *list = dlist_append(item, *list, AT_HEAD); 860 } 861 862 } else if (is_ctd_target_name(name) == B_TRUE) { 863 864 /* expand target to all of its disks */ 865 dlist_t *disks = NULL; 866 if ((error = get_disks_for_target(name, &disks)) == 0) { 867 if ((disks == NULL) || (dlist_length(disks) == 0)) { 868 volume_set_error( 869 gettext("nonexistent device specified " 870 "as %s: \"%s\"."), 871 which, array[i]); 872 error = -1; 873 } else { 874 dlist_t *iter; 875 for (iter = disks; 876 (iter != NULL) && (error == 0); 877 iter = iter->next) { 878 879 dlist_t *item; 880 if ((item = dlist_new_item(iter->obj)) == NULL) { 881 error = ENOMEM; 882 } else { 883 *list = dlist_append(item, *list, AT_HEAD); 884 } 885 } 886 } 887 } 888 889 } else { 890 891 /* not a slice, disk, target or ctrl */ 892 volume_set_error( 893 gettext("nonexistent device specified " 894 "as %s: \"%s\"."), 895 which, array[i]); 896 error = -1; 897 } 898 } 899 900 return (error); 901 } 902 903 /* 904 * FUNCTION: validate_request_name(devconfig_t *req, component_type_t type) 905 * 906 * INPUT: req - a devconfig_t volume request 907 * type - the volume type being requested 908 * 909 * SIDEEFFECT: if the request specifies a name and the name is valid and 910 * not currently in use an attempt is made to reserve it. 911 * if the name has already been reserved by a prior volume 912 * request, validation fails. 913 * 914 * RETURNS: int - 0 if the requested name passes validation 915 * (or there is no name request) 916 * !0 otherwise. 917 * 918 * PURPOSE: Validation function for a request's volume name. 919 * 920 * a HSP name must be valid and reservable. 921 * 922 * a volume name must be valid and reservable. 923 */ 924 static int 925 validate_request_name( 926 devconfig_t *req, 927 component_type_t type) 928 { 929 char *name = NULL; 930 char *typestr = devconfig_type_to_str(type); 931 int error = 0; 932 933 if ((error = devconfig_get_name(req, &name)) != 0) { 934 if (error != ERR_ATTR_UNSET) { 935 volume_set_error( 936 gettext("error getting requested name.\n")); 937 return (error); 938 } 939 /* no name specified */ 940 return (0); 941 } 942 943 if (type == TYPE_HSP) { 944 if (is_hsp_name_valid(name) == 0) { 945 volume_set_error( 946 gettext("requested %s name \"%s\" is not valid.\n"), 947 typestr, name); 948 error = -1; 949 } else if (reserve_hsp_name(name) != 0) { 950 if (is_rsvd_name(name) == B_TRUE) { 951 volume_set_error( 952 gettext("requested %s name \"%s\" used " 953 "previously in this request.\n"), 954 typestr, name); 955 } else { 956 volume_set_error( 957 gettext("requested %s name \"%s\" is not " 958 "available.\n"), 959 typestr, name); 960 } 961 error = -1; 962 } else { 963 error = add_reserved_name(name); 964 } 965 } else { 966 if (is_volume_name_valid(name) == 0) { 967 volume_set_error( 968 gettext("requested %s name \"%s\" is not valid.\n"), 969 typestr, name); 970 error = -1; 971 } else if (is_volume_name_in_range(name) != B_TRUE) { 972 int max = 0; 973 (void) get_max_number_of_devices(&max); 974 volume_set_error( 975 gettext("requested %s name \"%s\" is not legal.\n" 976 "Use a name less than d%d.\n"), 977 typestr, name, max); 978 error = -1; 979 } else if (reserve_volume_name(name) != 0) { 980 if (is_rsvd_name(name) == B_TRUE) { 981 volume_set_error( 982 gettext("requested %s name \"%s\" used " 983 "previously in this request.\n"), 984 typestr, name); 985 } else { 986 volume_set_error( 987 gettext("requested %s name \"%s\" is not " 988 "available, a volume with that name " 989 "already exists.\n"), 990 typestr, name); 991 } 992 error = -1; 993 } else { 994 error = add_reserved_name(name); 995 } 996 } 997 998 return (error); 999 } 1000 1001 /* 1002 * FUNCTION: add_reserved_name(char *name) 1003 * 1004 * INPUT: name - a char * volume name 1005 * 1006 * RETURNS: int - 0 on success 1007 * !0 otherwise. 1008 * 1009 * PURPOSE: Helper which remembers specfically requested names 1010 * in a private list to ensure that the same name isn't 1011 * requested more than once. 1012 */ 1013 static int 1014 add_reserved_name( 1015 char *name) 1016 { 1017 dlist_t *item = NULL; 1018 1019 if ((item = dlist_new_item(name)) == NULL) { 1020 return (ENOMEM); 1021 } 1022 1023 _rsvd_names = dlist_append(item, _rsvd_names, AT_TAIL); 1024 1025 return (0); 1026 } 1027 1028 /* 1029 * FUNCTION: is_rsvd_name(char *name) 1030 * 1031 * INPUT: name - a char * volume name 1032 * 1033 * RETURNS: boolean_t - B_TRUE if the requested name is currently 1034 * reserved, B_FALSE otherwise. 1035 * 1036 * PURPOSE: Helper which checks to see if the input volume 1037 * name was previously reserved. 1038 */ 1039 static boolean_t 1040 is_rsvd_name( 1041 char *name) 1042 { 1043 dlist_t *iter = NULL; 1044 1045 for (iter = _rsvd_names; iter != NULL; iter = iter->next) { 1046 if ((string_case_compare(name, (char *)iter->obj)) == 0) { 1047 return (B_TRUE); 1048 } 1049 } 1050 1051 return (B_FALSE); 1052 } 1053 1054 /* 1055 * FUNCTION: validate_request_size(devconfig_t *req, component_type_t type) 1056 * 1057 * INPUT: req - a devconfig_t volume request 1058 * type - the volume type being requested 1059 * 1060 * RETURNS: int - 0 if the requested size passes validation 1061 * (or there is no size request) 1062 * !0 otherwise. 1063 * 1064 * PURPOSE: Validation function for a request's volume size. 1065 * 1066 * a HSP request can have no size. 1067 * 1068 * a concat, stripe or mirror request may have a size. 1069 * if size is specified, the request cannot also specify 1070 * components. Conversely, if the request does not specify 1071 * a size, it must specify components. 1072 */ 1073 static int 1074 validate_request_size( 1075 devconfig_t *req, 1076 component_type_t type) 1077 { 1078 uint64_t nbytes = 0; 1079 int error = 0; 1080 1081 if (type == TYPE_HSP) { 1082 return (0); 1083 } 1084 1085 if ((error = devconfig_get_size(req, &nbytes)) != 0) { 1086 if (error == ERR_ATTR_UNSET) { 1087 /* nbytes not specified, request must have subcomponents */ 1088 dlist_t *list = devconfig_get_components(req); 1089 if (list != NULL && dlist_length(list) > 0) { 1090 error = 0; 1091 } else { 1092 volume_set_error( 1093 gettext("%s request specifies no size or " 1094 "subcomponents.\n"), 1095 devconfig_type_to_str(type)); 1096 error = -1; 1097 } 1098 } 1099 return (error); 1100 } 1101 1102 return (error); 1103 } 1104 1105 /* 1106 * FUNCTION: validate_minimum_size(uint64_t nbytes) 1107 * 1108 * INPUT: nbytes - requested volume size in bytes 1109 * 1110 * RETURNS: int - 0 if the requested size passes validation 1111 * (or there is no size request) 1112 * !0 otherwise. 1113 * 1114 * PURPOSE: Validation function for a request's volume size. 1115 * 1116 * an error is issued if the requested size <= 512K. 1117 */ 1118 static int 1119 validate_minimum_size( 1120 uint64_t nbytes) 1121 { 1122 static uint64_t min = (512 * 1024) - 1; 1123 int error = 0; 1124 1125 if (nbytes <= min) { 1126 char *sizestr = NULL; 1127 char *minstr = NULL; 1128 1129 (void) bytes_to_sizestr( 1130 nbytes, &sizestr, universal_units, B_FALSE); 1131 (void) bytes_to_sizestr( 1132 min, &minstr, universal_units, B_FALSE); 1133 1134 volume_set_error( 1135 gettext("requested volume size (%s) must be " 1136 "greater than %s.\n"), 1137 sizestr, minstr); 1138 1139 free(sizestr); 1140 free(minstr); 1141 1142 error = -1; 1143 } 1144 1145 return (error); 1146 } 1147 1148 /* 1149 * FUNCTION: validate_request_redundancy_level(devconfig_t *req) 1150 * 1151 * INPUT: req - a devconfig_t volume request 1152 * 1153 * RETURNS: int - 0 if the requested redundancy level 1154 * passes validation (or none was requested) 1155 * !0 otherwise. 1156 * 1157 * PURPOSE: Validation function for a redundant volume request's 1158 * redundancy level. 1159 * 1160 * If the request specifies redundancy, the value must be 1161 * between 1 and 4. 1162 */ 1163 static int 1164 validate_request_redundancy_level( 1165 devconfig_t *req) 1166 { 1167 uint16_t rlevel = 0; 1168 int error = 0; 1169 1170 if ((error = devconfig_get_volume_redundancy_level( 1171 req, &rlevel)) != 0) { 1172 if (error == ERR_ATTR_UNSET) { 1173 error = 0; 1174 } 1175 return (error); 1176 } 1177 1178 if (rlevel > 4) { 1179 volume_set_error(gettext( 1180 "requested redundancy level must be between 0 and 4.\n")); 1181 error = -1; 1182 } 1183 1184 return (error); 1185 } 1186 1187 /* 1188 * FUNCTION: validate_request_npaths(devconfig_t *req) 1189 * 1190 * INPUT: req - a devconfig_t volume request 1191 * 1192 * RETURNS: int - 0 if the requested # of redundant data paths 1193 * passes validation (or none was requested) 1194 * !0 otherwise. 1195 * 1196 * PURPOSE: Validation function for a volume request's number of 1197 * redundant data paths. This value controls the number 1198 * of independent data paths slices components selected 1199 * for the volume should have. 1200 * 1201 * If the request specifies npaths, the value must be 1202 * between 1 and 4 (4 is an arbitrary upper limit, there 1203 * is no known physical limit). 1204 */ 1205 static int 1206 validate_request_npaths( 1207 devconfig_t *req) 1208 { 1209 uint16_t npaths = 0; 1210 uint16_t minpaths = 1; 1211 uint16_t maxpaths = 4; 1212 1213 int error = 0; 1214 1215 if ((error = devconfig_get_volume_npaths(req, &npaths)) != 0) { 1216 if (error == ERR_ATTR_UNSET) { 1217 error = 0; 1218 } 1219 return (error); 1220 } 1221 1222 if (npaths < minpaths || npaths > maxpaths) { 1223 volume_set_error( 1224 gettext("requested number of redundant paths must be " 1225 "between %d and %d.\n"), minpaths, maxpaths); 1226 error = -1; 1227 } 1228 1229 1230 if ((npaths > 1) && (is_mpxio_enabled() != B_TRUE)) { 1231 volume_set_error( 1232 gettext("requested number of redundant paths (%d) cannot " 1233 "be provided, MPXIO is not enabled on this " 1234 "system."), 1235 npaths); 1236 error = -1; 1237 } 1238 1239 return (error); 1240 } 1241 1242 /* 1243 * FUNCTION: validate_request_submirrors(devconfig_t *req) 1244 * 1245 * INPUT: req - a devconfig_t volume request 1246 * 1247 * RETURNS: int - 0 if the requested mirror's submirrors 1248 * pass validation 1249 * !0 otherwise. 1250 * 1251 * PURPOSE: Validation function for a mirror volume request's 1252 * explicitly specified submirror components. 1253 * 1254 * Items to check: 1255 * a. submirror types 1256 * b. submirror number 1257 * c. submirror sizes 1258 */ 1259 static int 1260 validate_request_submirrors( 1261 devconfig_t *req) 1262 { 1263 dlist_t *submirrors = NULL; 1264 int error = 0; 1265 1266 submirrors = devconfig_get_components(req); 1267 1268 ((error = validate_submirror_types(submirrors)) != 0) || 1269 (error = validate_submirror_number(req, submirrors)) || 1270 (error = validate_submirror_sizes(req, submirrors)); 1271 1272 return (error); 1273 } 1274 1275 /* 1276 * FUNCTION: validate_submirror_types(dlist_t *subs) 1277 * 1278 * INPUT: subs - a list of submirror requests 1279 * 1280 * RETURNS: int - 0 if the requested submirrors 1281 * pass validation 1282 * !0 otherwise. 1283 * 1284 * PURPOSE: Validation function for a mirror volume request's 1285 * explicitly specified submirror components. 1286 * 1287 * Checks that each requested submirror request 1288 * is for a concat or stripe. 1289 */ 1290 static int 1291 validate_submirror_types( 1292 dlist_t *submirrors) 1293 { 1294 dlist_t *iter; 1295 int error = 0; 1296 1297 /* specified submirrors must be stripes or concats */ 1298 for (iter = submirrors; 1299 (iter != NULL) && (error == 0); 1300 iter = iter->next) { 1301 1302 devconfig_t *submir = (devconfig_t *)iter->obj; 1303 component_type_t submirtype = TYPE_UNKNOWN; 1304 1305 if ((error = devconfig_get_type(submir, &submirtype)) != 0) { 1306 volume_set_error( 1307 gettext("failed to get requested component type.\n")); 1308 break; 1309 } 1310 1311 if (submirtype != TYPE_CONCAT && submirtype != TYPE_STRIPE) { 1312 volume_set_error( 1313 gettext("requested submirror type \"%s\" " 1314 "is not valid.\n"), 1315 devconfig_type_to_str(submirtype)); 1316 error = -1; 1317 break; 1318 } 1319 } 1320 1321 return (error); 1322 } 1323 1324 /* 1325 * FUNCTION: validate_submirror_number(devconfig_t *req, dlist_t *subs) 1326 * 1327 * INPUT: req - the mirror request 1328 * subs - the list of requested submirrors 1329 * 1330 * RETURNS: int - 0 if the requested submirrors 1331 * pass validation 1332 * !0 otherwise. 1333 * 1334 * PURPOSE: Validation function for a mirror volume request's 1335 * explicitly specified submirror components. 1336 * 1337 * Checks that the number of submirror components 1338 * that have been specified matches the number of 1339 * submirrors specified. 1340 */ 1341 static int 1342 validate_submirror_number( 1343 devconfig_t *req, 1344 dlist_t *submirrors) 1345 { 1346 uint16_t nsubs = 0; 1347 int error = 0; 1348 1349 if ((error = devconfig_get_mirror_nsubs(req, &nsubs)) != 0) { 1350 if (error == ERR_ATTR_UNSET) { 1351 /* not specified */ 1352 error = 0; 1353 } 1354 } else if ((submirrors != NULL) && 1355 (dlist_length(submirrors) != nsubs)) { 1356 volume_set_error( 1357 gettext("the requested number of submirrors (%d) differs " 1358 "from the number of specified submirrors (%d).\n"), 1359 nsubs, dlist_length(submirrors)); 1360 error = -1; 1361 } 1362 1363 return (error); 1364 } 1365 1366 /* 1367 * FUNCTION: validate_submirror_sizes(devconfig_t *req, 1368 * dlist_t *submirrors) 1369 * 1370 * INPUT: req - the mirror request 1371 * submirrors - the list of requested submirrors 1372 * 1373 * RETURNS: int - 0 if the requested submirrors 1374 * pass validation 1375 * !0 otherwise. 1376 * 1377 * PURPOSE: Validation function for a mirror volume request's 1378 * explicitly specified size. Assumes that the mirror's size 1379 * has been validated by validate_request_size(). 1380 * 1381 * Compares explicitly requested mirror size against specified 1382 * component sizes and checks: 1383 * 1384 * - any submirror request that specifies both size and 1385 * components is invalid 1386 * - any submirror request specifying a size different 1387 * than that explictly requested for the mirror is 1388 * invalid 1389 * - a submirror request specifying a size < 512K is invalid. 1390 * 1391 * Other validation/warnings: 1392 * 1393 * - submirrors that specify components may end up with 1394 * usable capacity that differs from what was specified 1395 * for the mirror. 1396 * 1397 * - submirrors which specify neither size nor components are 1398 * assumed to be the size requested for the mirror. If the 1399 * mirror size is not specified, the first explicit size for 1400 * a submirror is assumed as the size for the mirror. 1401 */ 1402 static int 1403 validate_submirror_sizes( 1404 devconfig_t *req, 1405 dlist_t *submirrors) 1406 { 1407 dlist_t *submirs_with_size = NULL; 1408 dlist_t *submirs_with_comps = NULL; 1409 dlist_t *submirs_with_nothing = NULL; 1410 1411 dlist_t *iter = NULL; 1412 uint64_t mirror_size = 0; 1413 uint64_t assumed_size = 0; 1414 int error = 0; 1415 1416 if (submirrors == NULL || dlist_length(submirrors) == 0) { 1417 return (0); 1418 } 1419 1420 if ((error = devconfig_get_size(req, &mirror_size)) != 0) { 1421 if (error == ERR_ATTR_UNSET) { 1422 error = 0; 1423 } else { 1424 return (error); 1425 } 1426 } 1427 1428 /* 1429 * check size and component for each submirror, 1430 * collect those that specify size, components or neither 1431 * into separate lists. 1432 */ 1433 for (iter = submirrors; 1434 (iter != NULL) && (error == 0); 1435 iter = iter->next) { 1436 1437 devconfig_t *submir = (devconfig_t *)iter->obj; 1438 1439 error = validate_submirror_size_and_components(submir, 1440 mirror_size, &assumed_size, &submirs_with_size, 1441 &submirs_with_comps, &submirs_with_nothing); 1442 1443 } 1444 1445 if (error == 0) { 1446 1447 int n_size = dlist_length(submirs_with_size); 1448 int n_comp = dlist_length(submirs_with_comps); 1449 int n_none = dlist_length(submirs_with_nothing); 1450 1451 if ((n_size != 0) && (n_comp != 0)) { 1452 /* some submirrors specified size, some components */ 1453 oprintf(OUTPUT_TERSE, 1454 gettext(" *** warning: %d submirrors are specified " 1455 "by size, %d specified by components.\n" 1456 " The resulting mirror capacity will be " 1457 "that of the smallest submirror.\n"), 1458 n_size, n_comp); 1459 } 1460 1461 if (n_none != 0) { 1462 if (assumed_size != 0) { 1463 /* some submirrors specified neither size or components */ 1464 char *sizestr = NULL; 1465 1466 (void) bytes_to_sizestr( 1467 assumed_size, &sizestr, universal_units, B_FALSE); 1468 1469 oprintf(OUTPUT_TERSE, 1470 gettext(" *** warning: %d submirrors specified " 1471 "neither size or components,\n" 1472 " the assumed size is %s.\n"), 1473 n_none, sizestr); 1474 1475 free(sizestr); 1476 1477 } else if (mirror_size == 0) { 1478 volume_set_error( 1479 gettext("no size specified for requested " 1480 "mirror and no sizes/components " 1481 "specified for its submirrors.")); 1482 1483 error = -1; 1484 } 1485 } 1486 1487 dlist_free_items(submirs_with_size, NULL); 1488 dlist_free_items(submirs_with_comps, NULL); 1489 dlist_free_items(submirs_with_nothing, NULL); 1490 1491 } 1492 1493 return (error); 1494 } 1495 1496 /* 1497 * FUNCTION: validate_submirror_size_and_components( 1498 * devconfig_t *submir, 1499 * uint64_t mirror_size, 1500 * uint64_t *assumed_size, 1501 * dlist_t **submirs_with_size, 1502 * dlist_t **submirs_with_comps, 1503 * dlist_t **submirs_no_size_or_comps) 1504 * 1505 * INPUT: submir - a specific submirror request 1506 * mirror_size, - the size specified for the mirror 1507 * 1508 * OUTPUT: assumed_size - the assumed size of the mirror, 1509 * if none specified. 1510 * submirs_with_size - pointer to a list of submirror 1511 * requests that specify a size 1512 * submirs_with_comps - pointer to a list of submirror 1513 * requests that specify components 1514 * submirs_no_size_or_comps - pointer to a list of 1515 * submirror requests that specify neither 1516 * a size or components 1517 * 1518 * RETURNS: int - 0 if the requested submirrors 1519 * pass validation 1520 * !0 otherwise. 1521 * 1522 * PURPOSE: Validation function which checks a specific submirror 1523 * request's size and components against the parent mirror's 1524 * size. 1525 * 1526 * - any submirror request that specifies both size and 1527 * components is invalid 1528 * - any submirror request specifying a size different 1529 * than that explictly requested for the mirror is 1530 * invalid 1531 * - a submirror request specifying a size < 512K is invalid. 1532 * - any components specified for a submirror are validated. 1533 * 1534 * If the submirror passes the validation checks, it is added 1535 * to the appropriate output list. 1536 * 1537 * If the input mirror_size is 0 and the submirror specifies 1538 * a valid size, the submirror size is returned as the 1539 * assumed_size for the mirror. 1540 */ 1541 static int 1542 validate_submirror_size_and_components( 1543 devconfig_t *submir, 1544 uint64_t mirror_size, 1545 uint64_t *assumed_size, 1546 dlist_t **submirs_with_size, 1547 dlist_t **submirs_with_comps, 1548 dlist_t **submirs_no_size_or_comps) 1549 { 1550 uint64_t submir_size = 0; 1551 component_type_t submir_type = TYPE_UNKNOWN; 1552 char *submir_typestr = NULL; 1553 dlist_t *submir_comps = NULL; 1554 dlist_t *item = NULL; 1555 int n_submir_comps = 0; 1556 int error = 0; 1557 1558 submir_comps = devconfig_get_components(submir); 1559 if (submir_comps != NULL) { 1560 n_submir_comps = dlist_length(submir_comps); 1561 } 1562 1563 if ((error = devconfig_get_size(submir, &submir_size)) != 0) { 1564 if (error == ERR_ATTR_UNSET) { 1565 /* submirror size not specified */ 1566 error = 0; 1567 submir_size = 0; 1568 } 1569 } 1570 1571 if (error != 0) { 1572 return (error); 1573 } 1574 1575 /* submirror type previously validated */ 1576 (void) devconfig_get_type(submir, &submir_type); 1577 submir_typestr = devconfig_type_to_str(submir_type); 1578 1579 if (submir_size == 0) { 1580 1581 /* submirror has no size, components? */ 1582 if (n_submir_comps > 0) { 1583 1584 /* validate components */ 1585 error = validate_slice_components(submir, submir_type); 1586 1587 item = dlist_new_item((void *)submir); 1588 if (item == NULL) { 1589 error = ENOMEM; 1590 } else { 1591 *submirs_with_comps = 1592 dlist_append(item, *submirs_with_comps, AT_TAIL); 1593 } 1594 1595 } else { 1596 1597 /* no size or components */ 1598 item = dlist_new_item((void *)submir); 1599 if (item == NULL) { 1600 error = ENOMEM; 1601 } else { 1602 *submirs_no_size_or_comps = 1603 dlist_append(item, *submirs_no_size_or_comps, AT_TAIL); 1604 } 1605 1606 } 1607 1608 } else { 1609 1610 /* submirror has size, check it */ 1611 if (error == 0) { 1612 error = validate_minimum_size(submir_size); 1613 } 1614 1615 /* check size against mirror's size */ 1616 if ((error == 0) && (submir_size != mirror_size)) { 1617 1618 if (mirror_size != 0) { 1619 1620 /* sizes differ */ 1621 char *sizestr = NULL; 1622 char *mstr = NULL; 1623 1624 (void) bytes_to_sizestr( 1625 submir_size, &sizestr, universal_units, B_FALSE); 1626 (void) bytes_to_sizestr( 1627 mirror_size, &mstr, universal_units, B_FALSE); 1628 1629 volume_set_error( 1630 gettext("the requested submirror size (%s) " 1631 "differs from the requested mirror " 1632 "size (%s).\n"), 1633 sizestr, mstr); 1634 1635 error = -1; 1636 1637 free(sizestr); 1638 free(mstr); 1639 1640 } else if (*assumed_size == 0) { 1641 1642 /* first size assumed as mirror size */ 1643 char *sizestr = NULL; 1644 1645 (void) bytes_to_sizestr( 1646 submir_size, &sizestr, universal_units, B_FALSE); 1647 1648 oprintf(OUTPUT_TERSE, 1649 gettext(" *** warning, using first " 1650 "explicit submirror size (%s)\n" 1651 " as the mirror size\n"), 1652 sizestr); 1653 1654 *assumed_size = submir_size; 1655 1656 free(sizestr); 1657 1658 } else if (submir_size != *assumed_size) { 1659 1660 /* submirror sizes differ */ 1661 char *sizestr1 = NULL; 1662 char *sizestr2 = NULL; 1663 1664 (void) bytes_to_sizestr( 1665 submir_size, &sizestr1, universal_units, B_FALSE); 1666 (void) bytes_to_sizestr( 1667 *assumed_size, &sizestr2, universal_units, B_FALSE); 1668 1669 volume_set_error( 1670 gettext("submirror specifies different " 1671 "size (%s) than a previous " 1672 "submirror (%s)\n"), 1673 sizestr1, sizestr2); 1674 1675 free(sizestr1); 1676 free(sizestr2); 1677 1678 error = -1; 1679 } 1680 } 1681 1682 if ((error == 0) && (n_submir_comps > 0)) { 1683 1684 /* size and subcomponents specified */ 1685 char *sizestr = NULL; 1686 1687 (void) bytes_to_sizestr( 1688 submir_size, &sizestr, universal_units, B_FALSE); 1689 1690 volume_set_error( 1691 gettext("%s submirror specifies both an " 1692 "explicit size (%s) and components.\n"), 1693 submir_typestr, sizestr); 1694 1695 free(sizestr); 1696 error = -1; 1697 1698 } 1699 1700 if (error == 0) { 1701 item = dlist_new_item((void *)submir); 1702 if (item == NULL) { 1703 error = ENOMEM; 1704 } else { 1705 *submirs_with_size = 1706 dlist_append(item, *submirs_with_size, AT_TAIL); 1707 } 1708 } 1709 } 1710 1711 return (error); 1712 } 1713 1714 1715 /* 1716 * FUNCTION: validate_slice_components(devconfig_t *req, 1717 * component_type_t type) 1718 * 1719 * INPUT: req - the request 1720 * type - the type of volume being requested 1721 * 1722 * SIDEEFFECT: if the slice component is otherwise valid, an attempt is made 1723 * to reserve it. 1724 * 1725 * RETURNS: int - 0 if the request passes slice component validation 1726 * !0 otherwise. 1727 * 1728 * PURPOSE: Validation function for a concat, stripe or HSP request's 1729 * explicitly specified slice components. 1730 * 1731 * Is the component slice a known device 1732 * Is the component slice available 1733 * Is the component slice already reserved 1734 * 1735 * If the request is for a stripe or concat and the 1736 * request specifies an explicit size, it cannot also 1737 * specify component slices. This is a validation failure. 1738 * 1739 * If the request is for a stripe, the number of specified 1740 * slice components must agree with any expilcit specification 1741 * of the minimum or maximum number of components the stripe 1742 * should have. 1743 */ 1744 static int 1745 validate_slice_components( 1746 devconfig_t *req, 1747 component_type_t type) 1748 { 1749 dlist_t *list = NULL; 1750 dlist_t *iter = NULL; 1751 int error = 0; 1752 int ncomp = 0; 1753 1754 char *dsname = get_request_diskset(); 1755 char *voltype = devconfig_type_to_str(type); 1756 1757 list = devconfig_get_components(req); 1758 1759 for (iter = list; (iter != NULL) && (error == 0); iter = iter->next) { 1760 1761 devconfig_t *comp = (devconfig_t *)iter->obj; 1762 component_type_t ctype = TYPE_UNKNOWN; 1763 char *cname = NULL; 1764 dm_descriptor_t slice = (dm_descriptor_t)0; 1765 1766 if ((error = devconfig_get_type(comp, &ctype)) != 0) { 1767 volume_set_error( 1768 gettext("error getting requested component type."), 1769 voltype); 1770 1771 continue; 1772 } 1773 1774 if ((error = devconfig_get_name(comp, &cname)) != 0) { 1775 volume_set_error( 1776 gettext("error getting requested component name.")); 1777 1778 continue; 1779 } 1780 1781 if (cname == NULL || cname[0] == '\0') { 1782 volume_set_error( 1783 gettext("%s requested component has no name."), 1784 voltype); 1785 1786 error = -1; 1787 continue; 1788 } 1789 1790 if (ctype == TYPE_SLICE) { 1791 1792 boolean_t in_set = B_FALSE; 1793 boolean_t is_avail = B_FALSE; 1794 boolean_t is_rsvd = B_FALSE; 1795 dm_descriptor_t disk = (dm_descriptor_t)0; 1796 1797 /* is the slice known and explicitly available? */ 1798 if ((error = slice_is_available(cname, req, 1799 &is_avail)) != 0) { 1800 1801 if (error == ENODEV) { 1802 volume_set_error( 1803 gettext("%s requested component does not " 1804 "exist: \"%s\"."), 1805 voltype, cname); 1806 error = -1; 1807 } 1808 continue; 1809 } 1810 1811 if (is_avail != B_TRUE) { 1812 volume_set_error( 1813 gettext("%s requested component is " 1814 "unavailable: \"%s\"."), 1815 voltype, cname); 1816 1817 error = -1; 1818 continue; 1819 } 1820 1821 /* get slice and its disk */ 1822 ((error = slice_get_by_name(cname, &slice)) != 0) || 1823 (error = slice_get_disk(slice, &disk)) || 1824 (error = is_reserved_slice(slice, &is_rsvd)) || 1825 (error = is_disk_in_diskset(disk, dsname, &in_set)); 1826 if (error != 0) { 1827 continue; 1828 } 1829 1830 /* is disk in the set? */ 1831 if (in_set != B_TRUE) { 1832 volume_set_error( 1833 gettext("%s specifies a component not in " 1834 "disk set \"%s\": \"%s\"."), 1835 voltype, dsname, cname); 1836 1837 error = -1; 1838 continue; 1839 } 1840 1841 /* was slice specified in some other request? */ 1842 if (is_rsvd == B_TRUE) { 1843 /* include aliases in the error */ 1844 char *aliases = 1845 get_device_aliases_string((dm_descriptor_t)slice); 1846 1847 if (aliases[0] != NULL) { 1848 volume_set_error( 1849 gettext("%s specifies a previously used " 1850 "component: \"%s\" " 1851 "(aliases: %s).\n"), 1852 voltype, cname, aliases); 1853 } else { 1854 volume_set_error( 1855 gettext("%s specifies a previously used " 1856 "component: \"%s\"\n"), 1857 voltype, cname); 1858 } 1859 1860 error = -1; 1861 continue; 1862 } 1863 1864 /* component is ok, reserve it */ 1865 error = add_reserved_slice(slice); 1866 1867 /* 1868 * the reserved slice component still needs to be 1869 * checked against slices in use by SVM, but that 1870 * information isn't available yet: the usable 1871 * slice derivation happens after validation. 1872 * 1873 * validate_reserved_slices() can be used to check 1874 * them once the usable slices are determined. 1875 */ 1876 1877 } else { 1878 volume_set_error( 1879 gettext("%s requested component has illegal type."), 1880 voltype); 1881 1882 error = -1; 1883 continue; 1884 } 1885 } 1886 1887 if (error != 0) { 1888 return (error); 1889 } 1890 1891 ncomp = dlist_length(list); 1892 if ((ncomp > 0) && (type == TYPE_CONCAT || type == TYPE_STRIPE)) { 1893 /* explicit size requested for the stripe/concat? */ 1894 uint64_t size = 0; 1895 if ((error = devconfig_get_size(req, &size)) != 0) { 1896 if (error == ERR_ATTR_UNSET) { 1897 error = 0; 1898 } 1899 } else { 1900 /* size and components both specified */ 1901 char *sizestr = NULL; 1902 1903 (void) bytes_to_sizestr( 1904 size, &sizestr, universal_units, B_FALSE); 1905 1906 volume_set_error( 1907 gettext("%s specifies both an explicit size (%s) " 1908 "and components."), 1909 voltype, sizestr); 1910 1911 free(sizestr); 1912 error = -1; 1913 } 1914 } 1915 1916 if (error != 0) { 1917 return (error); 1918 } 1919 1920 if ((ncomp > 0) && (type == TYPE_STRIPE)) { 1921 /* does # of components agree with min & max comps? */ 1922 uint16_t min = 0; 1923 uint16_t max = 0; 1924 if ((error = devconfig_get_stripe_mincomp(req, &min)) != 0) { 1925 if (error == ERR_ATTR_UNSET) { 1926 /* min comp not requested */ 1927 error = 0; 1928 } else { 1929 /* error getting requested mincomp */ 1930 return (error); 1931 } 1932 1933 } else if (ncomp < min) { 1934 /* specified comps < requested mincomp */ 1935 volume_set_error( 1936 gettext("%s specifies fewer components (%d) than the " 1937 "minimum number requested (%d).\n"), 1938 voltype, ncomp, min); 1939 1940 error = -1; 1941 return (error); 1942 } 1943 1944 if ((error = devconfig_get_stripe_maxcomp(req, &max)) != 0) { 1945 if (error == ERR_ATTR_UNSET) { 1946 /* max comp not requested */ 1947 error = 0; 1948 } else { 1949 /* error getting request maxcomp */ 1950 return (error); 1951 } 1952 } else if (ncomp > max) { 1953 /* specified comps > requested maxcomp */ 1954 volume_set_error( 1955 gettext("%s specifies more components (%d) than the " 1956 "maximum number requested (%d).\n"), 1957 voltype, ncomp, max); 1958 error = -1; 1959 return (error); 1960 } 1961 } 1962 1963 return (error); 1964 } 1965 1966 /* 1967 * Generate a list of known aliases for the input descriptor. 1968 * 1969 * The returned string buffer is in the form: "alias1", "alias2"... 1970 */ 1971 static char * 1972 get_device_aliases_string( 1973 dm_descriptor_t desc) 1974 { 1975 static char buf[BUFSIZ]; 1976 dlist_t *aliases = NULL; 1977 dlist_t *iter = NULL; 1978 1979 buf[0] = '\0'; 1980 (void) get_aliases(desc, &aliases); 1981 for (iter = aliases; iter != NULL; iter = iter->next) { 1982 if (*buf == '\0') { 1983 (void) snprintf(buf, BUFSIZ-1, "\"%s\"", (char *)iter->obj); 1984 } else { 1985 char tmp[BUFSIZ]; 1986 (void) strcpy(buf, tmp); 1987 (void) snprintf(buf, BUFSIZ-1, "%s, \"%s\"", 1988 tmp, (char *)iter->obj); 1989 } 1990 } 1991 dlist_free_items(aliases, free); 1992 1993 return (buf); 1994 } 1995