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