lvcreate.c revision 1.1.1.2 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