Sync usage with man page.
[netbsd-mini2440.git] / external / gpl2 / lvm2 / dist / tools / lvcreate.c
blob62e7bebd0a17a9e800fa12350fafeabf55c30597
1 /* $NetBSD$ */
3 /*
4 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
5 * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
7 * This file is part of LVM2.
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.
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
18 #include "tools.h"
19 #include "lv_alloc.h"
21 #include <fcntl.h>
23 struct lvcreate_cmdline_params {
24 percent_t percent;
25 uint64_t size;
26 char **pvs;
27 int pv_count;
30 static int _lvcreate_name_params(struct lvcreate_params *lp,
31 struct cmd_context *cmd,
32 int *pargc, char ***pargv)
34 int argc = *pargc;
35 char **argv = *pargv, *ptr;
36 char *vg_name;
38 lp->lv_name = arg_str_value(cmd, name_ARG, NULL);
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;
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;
55 /* Strip the volume group from the origin */
56 if ((ptr = strrchr(lp->origin, (int) '/')))
57 lp->origin = ptr + 1;
59 } else {
61 * If VG not on command line, try -n arg and then
62 * environment.
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;
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;
79 * Ensure lv_name doesn't contain a
80 * different VG.
82 if (lp->lv_name && strchr(lp->lv_name, '/')) {
83 if (!(lp->vg_name =
84 extract_vgname(cmd, lp->lv_name)))
85 return 0;
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;
96 lp->vg_name = vg_name;
97 (*pargv)++, (*pargc)--;
101 if (!validate_name(lp->vg_name)) {
102 log_error("Volume group name %s has invalid characters",
103 lp->vg_name);
104 return 0;
107 if (lp->lv_name) {
108 if ((ptr = strrchr(lp->lv_name, '/')))
109 lp->lv_name = ptr + 1;
111 if (!apply_lvname_restrictions(lp->lv_name))
112 return_0;
114 if (!validate_name(lp->lv_name)) {
115 log_error("Logical volume name \"%s\" is invalid",
116 lp->lv_name);
117 return 0;
121 return 1;
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.
130 static int _update_extents_params(struct volume_group *vg,
131 struct lvcreate_params *lp,
132 struct lvcreate_cmdline_params *lcp)
134 uint32_t pv_extent_count;
136 if (lcp->size &&
137 !(lp->extents = extents_from_size(vg->cmd, lcp->size,
138 vg->extent_size)))
139 return_0;
141 if (lp->voriginsize &&
142 !(lp->voriginextents = extents_from_size(vg->cmd, lp->voriginsize,
143 vg->extent_size)))
144 return_0;
147 * Create the pv list before we parse lcp->percent - might be
148 * PERCENT_PVSs
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;
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;
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;
179 return 1;
182 static int _read_size_params(struct lvcreate_params *lp,
183 struct lvcreate_cmdline_params *lcp,
184 struct cmd_context *cmd)
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;
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;
196 lp->extents = arg_uint_value(cmd, extents_ARG, 0);
197 lcp->percent = arg_percent_value(cmd, extents_ARG, PERCENT_NONE);
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;
206 lcp->size = arg_uint64_value(cmd, size_ARG, UINT64_C(0));
207 lcp->percent = PERCENT_NONE;
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;
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;
224 return 1;
228 * Generic stripe parameter checks.
229 * FIXME: Should eventually be moved into lvm library.
231 static int _validate_stripe_params(struct cmd_context *cmd,
232 struct lvcreate_params *lp)
234 if (lp->stripes == 1 && lp->stripe_size) {
235 log_print("Ignoring stripesize argument with single stripe");
236 lp->stripe_size = 0;
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));
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;
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;
261 return 1;
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)
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;
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;
282 lp->stripe_size = arg_uint_value(cmd, stripesize_ARG, 0);
286 if (!_validate_stripe_params(cmd, lp))
287 return 0;
289 return 1;
293 * Generic mirror parameter checks.
294 * FIXME: Should eventually be moved into lvm library.
296 static int _validate_mirror_params(const struct cmd_context *cmd __attribute((unused)),
297 const struct lvcreate_params *lp)
299 int pagesize = lvm_getpagesize();
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;
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;
314 if (!lp->region_size) {
315 log_error("Non-zero region size must be supplied.");
316 return 0;
319 return 1;
322 static int _read_mirror_params(struct lvcreate_params *lp,
323 struct cmd_context *cmd)
325 int region_size;
326 const char *mirrorlog;
328 if (arg_count(cmd, corelog_ARG))
329 lp->corelog = 1;
331 mirrorlog = arg_str_value(cmd, mirrorlog_ARG,
332 lp->corelog ? "core" : DEFAULT_MIRRORLOG);
334 if (!strcmp("disk", mirrorlog)) {
335 if (lp->corelog) {
336 log_error("--mirrorlog disk and --corelog "
337 "are incompatible");
338 return 0;
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;
348 log_verbose("Setting logging type to %s", mirrorlog);
350 lp->nosync = arg_is_set(cmd, nosync_ARG);
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;
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;
367 lp->region_size = region_size;
370 if (!_validate_mirror_params(cmd, lp))
371 return 0;
373 return 1;
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)
381 int contiguous;
382 unsigned pagesize;
384 memset(lp, 0, sizeof(*lp));
385 memset(lcp, 0, sizeof(*lcp));
388 * Check selected options are compatible and determine segtype
390 lp->segtype = (const struct segment_type *)
391 arg_ptr_value(cmd, type_ARG,
392 get_segtype_from_string(cmd, "striped"));
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");
398 if (arg_count(cmd, snapshot_ARG) || seg_is_snapshot(lp) ||
399 arg_count(cmd, virtualsize_ARG))
400 lp->snapshot = 1;
402 lp->mirrors = 1;
404 /* Default to 2 mirrored areas if --type mirror */
405 if (seg_is_mirrored(lp))
406 lp->mirrors = 2;
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;
418 if (lp->snapshot) {
419 if (arg_count(cmd, zero_ARG)) {
420 log_error("-Z is incompatible with snapshots");
421 return 0;
423 if (arg_sign_value(cmd, chunksize_ARG, 0) == SIGN_MINUS) {
424 log_error("Negative chunk size is invalid");
425 return 0;
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;
434 log_verbose("Setting chunksize to %d sectors.", lp->chunk_size);
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;
445 if (lp->mirrors > 1) {
446 if (lp->snapshot) {
447 log_error("mirrors and snapshots are currently "
448 "incompatible");
449 return 0;
452 if (lp->stripes > 1) {
453 log_error("mirrors and stripes are currently "
454 "incompatible");
455 return 0;
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;
466 if (arg_count(cmd, nosync_ARG)) {
467 log_error("--nosync is only available with mirrors");
468 return 0;
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;
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;
486 * Should we zero the lv.
488 lp->zero = strcmp(arg_str_value(cmd, zero_ARG,
489 (lp->segtype->flags & SEG_CANNOT_BE_ZEROED) ? "n" : "y"), "n");
492 * Alloc policy
494 contiguous = strcmp(arg_str_value(cmd, contiguous_ARG, "n"), "n");
496 lp->alloc = contiguous ? ALLOC_CONTIGUOUS : ALLOC_INHERIT;
498 lp->alloc = arg_uint_value(cmd, alloc_ARG, lp->alloc);
500 if (contiguous && (lp->alloc != ALLOC_CONTIGUOUS)) {
501 log_error("Conflicting contiguous and alloc arguments");
502 return 0;
506 * Read ahead.
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);
522 * Permissions.
524 lp->permission = arg_uint_value(cmd, permission_ARG,
525 LVM_READ | LVM_WRITE);
527 /* Must not zero read only volume */
528 if (!(lp->permission & LVM_WRITE))
529 lp->zero = 0;
531 lp->minor = arg_int_value(cmd, minor_ARG, -1);
532 lp->major = arg_int_value(cmd, major_ARG, -1);
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;
542 if (lp->major == -1) {
543 log_error("Please specify major number with "
544 "--major when using -My");
545 return 0;
547 } else {
548 if ((lp->minor != -1) || (lp->major != -1)) {
549 log_error("--major and --minor incompatible "
550 "with -Mn");
551 return 0;
554 } else if (arg_count(cmd, minor_ARG) || arg_count(cmd, major_ARG)) {
555 log_error("--major and --minor require -My");
556 return 0;
559 lp->tag = arg_str_value(cmd, addtag_ARG, NULL);
561 lcp->pv_count = argc;
562 lcp->pvs = argv;
564 return 1;
567 int lvcreate(struct cmd_context *cmd, int argc, char **argv)
569 int r = ECMD_PROCESSED;
570 struct lvcreate_params lp;
571 struct lvcreate_cmdline_params lcp;
572 struct volume_group *vg;
574 memset(&lp, 0, sizeof(lp));
576 if (!_lvcreate_params(&lp, &lcp, cmd, argc, argv))
577 return EINVALID_CMD_LINE;
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;
587 if (!_update_extents_params(vg, &lp, &lcp)) {
588 r = ECMD_FAILED;
589 goto_out;
592 if (!lv_create_single(vg, &lp)) {
593 stack;
594 r = ECMD_FAILED;
596 out:
597 unlock_and_release_vg(cmd, vg, lp.vg_name);
598 return r;