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