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