1 /* $NetBSD: lvcreate.c,v 1.1.1.2 2009/12/02 00:25:50 haad Exp $ */ 2 3 /* 4 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. 5 * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved. 6 * 7 * This file is part of LVM2. 8 * 9 * This copyrighted material is made available to anyone wishing to use, 10 * modify, copy, or redistribute it subject to the terms and conditions 11 * of the GNU Lesser General Public License v.2.1. 12 * 13 * You should have received a copy of the GNU Lesser General Public License 14 * along with this program; if not, write to the Free Software Foundation, 15 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 */ 17 18 #include "tools.h" 19 #include "lv_alloc.h" 20 21 #include <fcntl.h> 22 23 struct lvcreate_cmdline_params { 24 percent_t percent; 25 uint64_t size; 26 char **pvs; 27 int pv_count; 28 }; 29 30 static int _lvcreate_name_params(struct lvcreate_params *lp, 31 struct cmd_context *cmd, 32 int *pargc, char ***pargv) 33 { 34 int argc = *pargc; 35 char **argv = *pargv, *ptr; 36 char *vg_name; 37 38 lp->lv_name = arg_str_value(cmd, name_ARG, NULL); 39 40 if (lp->snapshot && !arg_count(cmd, virtualsize_ARG)) { 41 if (!argc) { 42 log_error("Please specify a logical volume to act as " 43 "the snapshot origin."); 44 return 0; 45 } 46 47 lp->origin = argv[0]; 48 (*pargv)++, (*pargc)--; 49 if (!(lp->vg_name = extract_vgname(cmd, lp->origin))) { 50 log_error("The origin name should include the " 51 "volume group."); 52 return 0; 53 } 54 55 /* Strip the volume group from the origin */ 56 if ((ptr = strrchr(lp->origin, (int) '/'))) 57 lp->origin = ptr + 1; 58 59 } else { 60 /* 61 * If VG not on command line, try -n arg and then 62 * environment. 63 */ 64 if (!argc) { 65 if (!(lp->vg_name = extract_vgname(cmd, lp->lv_name))) { 66 log_error("Please provide a volume group name"); 67 return 0; 68 } 69 70 } else { 71 vg_name = skip_dev_dir(cmd, argv[0], NULL); 72 if (strrchr(vg_name, '/')) { 73 log_error("Volume group name expected " 74 "(no slash)"); 75 return 0; 76 } 77 78 /* 79 * Ensure lv_name doesn't contain a 80 * different VG. 81 */ 82 if (lp->lv_name && strchr(lp->lv_name, '/')) { 83 if (!(lp->vg_name = 84 extract_vgname(cmd, lp->lv_name))) 85 return 0; 86 87 if (strcmp(lp->vg_name, vg_name)) { 88 log_error("Inconsistent volume group " 89 "names " 90 "given: \"%s\" and \"%s\"", 91 lp->vg_name, vg_name); 92 return 0; 93 } 94 } 95 96 lp->vg_name = vg_name; 97 (*pargv)++, (*pargc)--; 98 } 99 } 100 101 if (!validate_name(lp->vg_name)) { 102 log_error("Volume group name %s has invalid characters", 103 lp->vg_name); 104 return 0; 105 } 106 107 if (lp->lv_name) { 108 if ((ptr = strrchr(lp->lv_name, '/'))) 109 lp->lv_name = ptr + 1; 110 111 if (!apply_lvname_restrictions(lp->lv_name)) 112 return_0; 113 114 if (!validate_name(lp->lv_name)) { 115 log_error("Logical volume name \"%s\" is invalid", 116 lp->lv_name); 117 return 0; 118 } 119 } 120 121 return 1; 122 } 123 124 /* 125 * Update extents parameters based on other parameters which affect the size 126 * calcuation. 127 * NOTE: We must do this here because of the percent_t typedef and because we 128 * need the vg. 129 */ 130 static int _update_extents_params(struct volume_group *vg, 131 struct lvcreate_params *lp, 132 struct lvcreate_cmdline_params *lcp) 133 { 134 uint32_t pv_extent_count; 135 136 if (lcp->size && 137 !(lp->extents = extents_from_size(vg->cmd, lcp->size, 138 vg->extent_size))) 139 return_0; 140 141 if (lp->voriginsize && 142 !(lp->voriginextents = extents_from_size(vg->cmd, lp->voriginsize, 143 vg->extent_size))) 144 return_0; 145 146 /* 147 * Create the pv list before we parse lcp->percent - might be 148 * PERCENT_PVSs 149 */ 150 if (lcp->pv_count) { 151 if (!(lp->pvh = create_pv_list(vg->cmd->mem, vg, 152 lcp->pv_count, lcp->pvs, 1))) 153 return_0; 154 } else 155 lp->pvh = &vg->pvs; 156 157 switch(lcp->percent) { 158 case PERCENT_VG: 159 lp->extents = lp->extents * vg->extent_count / 100; 160 break; 161 case PERCENT_FREE: 162 lp->extents = lp->extents * vg->free_count / 100; 163 break; 164 case PERCENT_PVS: 165 if (!lcp->pv_count) 166 lp->extents = lp->extents * vg->extent_count / 100; 167 else { 168 pv_extent_count = pv_list_extents_free(lp->pvh); 169 lp->extents = lp->extents * pv_extent_count / 100; 170 } 171 break; 172 case PERCENT_LV: 173 log_error("Please express size as %%VG, %%PVS, or " 174 "%%FREE."); 175 return 0; 176 case PERCENT_NONE: 177 break; 178 } 179 return 1; 180 } 181 182 static int _read_size_params(struct lvcreate_params *lp, 183 struct lvcreate_cmdline_params *lcp, 184 struct cmd_context *cmd) 185 { 186 if (arg_count(cmd, extents_ARG) + arg_count(cmd, size_ARG) != 1) { 187 log_error("Please specify either size or extents (not both)"); 188 return 0; 189 } 190 191 if (arg_count(cmd, extents_ARG)) { 192 if (arg_sign_value(cmd, extents_ARG, 0) == SIGN_MINUS) { 193 log_error("Negative number of extents is invalid"); 194 return 0; 195 } 196 lp->extents = arg_uint_value(cmd, extents_ARG, 0); 197 lcp->percent = arg_percent_value(cmd, extents_ARG, PERCENT_NONE); 198 } 199 200 /* Size returned in kilobyte units; held in sectors */ 201 if (arg_count(cmd, size_ARG)) { 202 if (arg_sign_value(cmd, size_ARG, 0) == SIGN_MINUS) { 203 log_error("Negative size is invalid"); 204 return 0; 205 } 206 lcp->size = arg_uint64_value(cmd, size_ARG, UINT64_C(0)); 207 lcp->percent = PERCENT_NONE; 208 } 209 210 /* Size returned in kilobyte units; held in sectors */ 211 if (arg_count(cmd, virtualsize_ARG)) { 212 if (arg_sign_value(cmd, virtualsize_ARG, 0) == SIGN_MINUS) { 213 log_error("Negative virtual origin size is invalid"); 214 return 0; 215 } 216 lp->voriginsize = arg_uint64_value(cmd, virtualsize_ARG, 217 UINT64_C(0)); 218 if (!lp->voriginsize) { 219 log_error("Virtual origin size may not be zero"); 220 return 0; 221 } 222 } 223 224 return 1; 225 } 226 227 /* 228 * Generic stripe parameter checks. 229 * FIXME: Should eventually be moved into lvm library. 230 */ 231 static int _validate_stripe_params(struct cmd_context *cmd, 232 struct lvcreate_params *lp) 233 { 234 if (lp->stripes == 1 && lp->stripe_size) { 235 log_print("Ignoring stripesize argument with single stripe"); 236 lp->stripe_size = 0; 237 } 238 239 if (lp->stripes > 1 && !lp->stripe_size) { 240 lp->stripe_size = find_config_tree_int(cmd, 241 "metadata/stripesize", 242 DEFAULT_STRIPESIZE) * 2; 243 log_print("Using default stripesize %s", 244 display_size(cmd, (uint64_t) lp->stripe_size)); 245 } 246 247 if (lp->stripes < 1 || lp->stripes > MAX_STRIPES) { 248 log_error("Number of stripes (%d) must be between %d and %d", 249 lp->stripes, 1, MAX_STRIPES); 250 return 0; 251 } 252 253 /* MAX size check is in _lvcreate */ 254 if (lp->stripes > 1 && (lp->stripe_size < STRIPE_SIZE_MIN || 255 lp->stripe_size & (lp->stripe_size - 1))) { 256 log_error("Invalid stripe size %s", 257 display_size(cmd, (uint64_t) lp->stripe_size)); 258 return 0; 259 } 260 261 return 1; 262 } 263 264 /* The stripe size is limited by the size of a uint32_t, but since the 265 * value given by the user is doubled, and the final result must be a 266 * power of 2, we must divide UINT_MAX by four and add 1 (to round it 267 * up to the power of 2) */ 268 static int _read_stripe_params(struct lvcreate_params *lp, 269 struct cmd_context *cmd) 270 { 271 if (arg_count(cmd, stripesize_ARG)) { 272 if (arg_sign_value(cmd, stripesize_ARG, 0) == SIGN_MINUS) { 273 log_error("Negative stripesize is invalid"); 274 return 0; 275 } 276 /* Check to make sure we won't overflow lp->stripe_size */ 277 if(arg_uint_value(cmd, stripesize_ARG, 0) > STRIPE_SIZE_LIMIT * 2) { 278 log_error("Stripe size cannot be larger than %s", 279 display_size(cmd, (uint64_t) STRIPE_SIZE_LIMIT)); 280 return 0; 281 } 282 lp->stripe_size = arg_uint_value(cmd, stripesize_ARG, 0); 283 } 284 285 286 if (!_validate_stripe_params(cmd, lp)) 287 return 0; 288 289 return 1; 290 } 291 292 /* 293 * Generic mirror parameter checks. 294 * FIXME: Should eventually be moved into lvm library. 295 */ 296 static int _validate_mirror_params(const struct cmd_context *cmd __attribute((unused)), 297 const struct lvcreate_params *lp) 298 { 299 int pagesize = lvm_getpagesize(); 300 301 if (lp->region_size & (lp->region_size - 1)) { 302 log_error("Region size (%" PRIu32 ") must be a power of 2", 303 lp->region_size); 304 return 0; 305 } 306 307 if (lp->region_size % (pagesize >> SECTOR_SHIFT)) { 308 log_error("Region size (%" PRIu32 ") must be a multiple of " 309 "machine memory page size (%d)", 310 lp->region_size, pagesize >> SECTOR_SHIFT); 311 return 0; 312 } 313 314 if (!lp->region_size) { 315 log_error("Non-zero region size must be supplied."); 316 return 0; 317 } 318 319 return 1; 320 } 321 322 static int _read_mirror_params(struct lvcreate_params *lp, 323 struct cmd_context *cmd) 324 { 325 int region_size; 326 const char *mirrorlog; 327 328 if (arg_count(cmd, corelog_ARG)) 329 lp->corelog = 1; 330 331 mirrorlog = arg_str_value(cmd, mirrorlog_ARG, 332 lp->corelog ? "core" : DEFAULT_MIRRORLOG); 333 334 if (!strcmp("disk", mirrorlog)) { 335 if (lp->corelog) { 336 log_error("--mirrorlog disk and --corelog " 337 "are incompatible"); 338 return 0; 339 } 340 lp->corelog = 0; 341 } else if (!strcmp("core", mirrorlog)) 342 lp->corelog = 1; 343 else { 344 log_error("Unknown mirrorlog type: %s", mirrorlog); 345 return 0; 346 } 347 348 log_verbose("Setting logging type to %s", mirrorlog); 349 350 lp->nosync = arg_is_set(cmd, nosync_ARG); 351 352 if (arg_count(cmd, regionsize_ARG)) { 353 if (arg_sign_value(cmd, regionsize_ARG, 0) == SIGN_MINUS) { 354 log_error("Negative regionsize is invalid"); 355 return 0; 356 } 357 lp->region_size = arg_uint_value(cmd, regionsize_ARG, 0); 358 } else { 359 region_size = 2 * find_config_tree_int(cmd, 360 "activation/mirror_region_size", 361 DEFAULT_MIRROR_REGION_SIZE); 362 if (region_size < 0) { 363 log_error("Negative regionsize in configuration file " 364 "is invalid"); 365 return 0; 366 } 367 lp->region_size = region_size; 368 } 369 370 if (!_validate_mirror_params(cmd, lp)) 371 return 0; 372 373 return 1; 374 } 375 376 static int _lvcreate_params(struct lvcreate_params *lp, 377 struct lvcreate_cmdline_params *lcp, 378 struct cmd_context *cmd, 379 int argc, char **argv) 380 { 381 int contiguous; 382 unsigned pagesize; 383 384 memset(lp, 0, sizeof(*lp)); 385 memset(lcp, 0, sizeof(*lcp)); 386 387 /* 388 * Check selected options are compatible and determine segtype 389 */ 390 lp->segtype = (const struct segment_type *) 391 arg_ptr_value(cmd, type_ARG, 392 get_segtype_from_string(cmd, "striped")); 393 394 lp->stripes = arg_uint_value(cmd, stripes_ARG, 1); 395 if (arg_count(cmd, stripes_ARG) && lp->stripes == 1) 396 log_print("Redundant stripes argument: default is 1"); 397 398 if (arg_count(cmd, snapshot_ARG) || seg_is_snapshot(lp) || 399 arg_count(cmd, virtualsize_ARG)) 400 lp->snapshot = 1; 401 402 lp->mirrors = 1; 403 404 /* Default to 2 mirrored areas if --type mirror */ 405 if (seg_is_mirrored(lp)) 406 lp->mirrors = 2; 407 408 if (arg_count(cmd, mirrors_ARG)) { 409 lp->mirrors = arg_uint_value(cmd, mirrors_ARG, 0) + 1; 410 if (lp->mirrors == 1) 411 log_print("Redundant mirrors argument: default is 0"); 412 if (arg_sign_value(cmd, mirrors_ARG, 0) == SIGN_MINUS) { 413 log_error("Mirrors argument may not be negative"); 414 return 0; 415 } 416 } 417 418 if (lp->snapshot) { 419 if (arg_count(cmd, zero_ARG)) { 420 log_error("-Z is incompatible with snapshots"); 421 return 0; 422 } 423 if (arg_sign_value(cmd, chunksize_ARG, 0) == SIGN_MINUS) { 424 log_error("Negative chunk size is invalid"); 425 return 0; 426 } 427 lp->chunk_size = arg_uint_value(cmd, chunksize_ARG, 8); 428 if (lp->chunk_size < 8 || lp->chunk_size > 1024 || 429 (lp->chunk_size & (lp->chunk_size - 1))) { 430 log_error("Chunk size must be a power of 2 in the " 431 "range 4K to 512K"); 432 return 0; 433 } 434 log_verbose("Setting chunksize to %d sectors.", lp->chunk_size); 435 436 if (!(lp->segtype = get_segtype_from_string(cmd, "snapshot"))) 437 return_0; 438 } else { 439 if (arg_count(cmd, chunksize_ARG)) { 440 log_error("-c is only available with snapshots"); 441 return 0; 442 } 443 } 444 445 if (lp->mirrors > 1) { 446 if (lp->snapshot) { 447 log_error("mirrors and snapshots are currently " 448 "incompatible"); 449 return 0; 450 } 451 452 if (lp->stripes > 1) { 453 log_error("mirrors and stripes are currently " 454 "incompatible"); 455 return 0; 456 } 457 458 if (!(lp->segtype = get_segtype_from_string(cmd, "striped"))) 459 return_0; 460 } else { 461 if (arg_count(cmd, corelog_ARG)) { 462 log_error("--corelog is only available with mirrors"); 463 return 0; 464 } 465 466 if (arg_count(cmd, nosync_ARG)) { 467 log_error("--nosync is only available with mirrors"); 468 return 0; 469 } 470 } 471 472 if (activation() && lp->segtype->ops->target_present && 473 !lp->segtype->ops->target_present(cmd, NULL, NULL)) { 474 log_error("%s: Required device-mapper target(s) not " 475 "detected in your kernel", lp->segtype->name); 476 return 0; 477 } 478 479 if (!_lvcreate_name_params(lp, cmd, &argc, &argv) || 480 !_read_size_params(lp, lcp, cmd) || 481 !_read_stripe_params(lp, cmd) || 482 !_read_mirror_params(lp, cmd)) 483 return_0; 484 485 /* 486 * Should we zero the lv. 487 */ 488 lp->zero = strcmp(arg_str_value(cmd, zero_ARG, 489 (lp->segtype->flags & SEG_CANNOT_BE_ZEROED) ? "n" : "y"), "n"); 490 491 /* 492 * Alloc policy 493 */ 494 contiguous = strcmp(arg_str_value(cmd, contiguous_ARG, "n"), "n"); 495 496 lp->alloc = contiguous ? ALLOC_CONTIGUOUS : ALLOC_INHERIT; 497 498 lp->alloc = arg_uint_value(cmd, alloc_ARG, lp->alloc); 499 500 if (contiguous && (lp->alloc != ALLOC_CONTIGUOUS)) { 501 log_error("Conflicting contiguous and alloc arguments"); 502 return 0; 503 } 504 505 /* 506 * Read ahead. 507 */ 508 lp->read_ahead = arg_uint_value(cmd, readahead_ARG, DM_READ_AHEAD_NONE); 509 pagesize = lvm_getpagesize() >> SECTOR_SHIFT; 510 if (lp->read_ahead != DM_READ_AHEAD_AUTO && 511 lp->read_ahead != DM_READ_AHEAD_NONE && 512 lp->read_ahead % pagesize) { 513 if (lp->read_ahead < pagesize) 514 lp->read_ahead = pagesize; 515 else 516 lp->read_ahead = (lp->read_ahead / pagesize) * pagesize; 517 log_warn("WARNING: Overriding readahead to %u sectors, a multiple " 518 "of %uK page size.", lp->read_ahead, pagesize >> 1); 519 } 520 521 /* 522 * Permissions. 523 */ 524 lp->permission = arg_uint_value(cmd, permission_ARG, 525 LVM_READ | LVM_WRITE); 526 527 /* Must not zero read only volume */ 528 if (!(lp->permission & LVM_WRITE)) 529 lp->zero = 0; 530 531 lp->minor = arg_int_value(cmd, minor_ARG, -1); 532 lp->major = arg_int_value(cmd, major_ARG, -1); 533 534 /* Persistent minor */ 535 if (arg_count(cmd, persistent_ARG)) { 536 if (!strcmp(arg_str_value(cmd, persistent_ARG, "n"), "y")) { 537 if (lp->minor == -1) { 538 log_error("Please specify minor number with " 539 "--minor when using -My"); 540 return 0; 541 } 542 if (lp->major == -1) { 543 log_error("Please specify major number with " 544 "--major when using -My"); 545 return 0; 546 } 547 } else { 548 if ((lp->minor != -1) || (lp->major != -1)) { 549 log_error("--major and --minor incompatible " 550 "with -Mn"); 551 return 0; 552 } 553 } 554 } else if (arg_count(cmd, minor_ARG) || arg_count(cmd, major_ARG)) { 555 log_error("--major and --minor require -My"); 556 return 0; 557 } 558 559 lp->tag = arg_str_value(cmd, addtag_ARG, NULL); 560 561 lcp->pv_count = argc; 562 lcp->pvs = argv; 563 564 return 1; 565 } 566 567 int lvcreate(struct cmd_context *cmd, int argc, char **argv) 568 { 569 int r = ECMD_PROCESSED; 570 struct lvcreate_params lp; 571 struct lvcreate_cmdline_params lcp; 572 struct volume_group *vg; 573 574 memset(&lp, 0, sizeof(lp)); 575 576 if (!_lvcreate_params(&lp, &lcp, cmd, argc, argv)) 577 return EINVALID_CMD_LINE; 578 579 log_verbose("Finding volume group \"%s\"", lp.vg_name); 580 vg = vg_read_for_update(cmd, lp.vg_name, NULL, 0); 581 if (vg_read_error(vg)) { 582 vg_release(vg); 583 stack; 584 return ECMD_FAILED; 585 } 586 587 if (!_update_extents_params(vg, &lp, &lcp)) { 588 r = ECMD_FAILED; 589 goto_out; 590 } 591 592 if (!lv_create_single(vg, &lp)) { 593 stack; 594 r = ECMD_FAILED; 595 } 596 out: 597 unlock_and_release_vg(cmd, vg, lp.vg_name); 598 return r; 599 } 600