xref: /dragonfly/contrib/lvm2/dist/tools/lvresize.c (revision 86d7f5d3)
1*86d7f5d3SJohn Marino /*	$NetBSD: lvresize.c,v 1.1.1.3 2009/12/02 00:25:53 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-2009 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 
20*86d7f5d3SJohn Marino #define SIZE_BUF 128
21*86d7f5d3SJohn Marino 
22*86d7f5d3SJohn Marino struct lvresize_params {
23*86d7f5d3SJohn Marino 	const char *vg_name;
24*86d7f5d3SJohn Marino 	const char *lv_name;
25*86d7f5d3SJohn Marino 
26*86d7f5d3SJohn Marino 	uint32_t stripes;
27*86d7f5d3SJohn Marino 	uint32_t stripe_size;
28*86d7f5d3SJohn Marino 	uint32_t mirrors;
29*86d7f5d3SJohn Marino 
30*86d7f5d3SJohn Marino 	const struct segment_type *segtype;
31*86d7f5d3SJohn Marino 
32*86d7f5d3SJohn Marino 	/* size */
33*86d7f5d3SJohn Marino 	uint32_t extents;
34*86d7f5d3SJohn Marino 	uint64_t size;
35*86d7f5d3SJohn Marino 	sign_t sign;
36*86d7f5d3SJohn Marino 	percent_t percent;
37*86d7f5d3SJohn Marino 
38*86d7f5d3SJohn Marino 	enum {
39*86d7f5d3SJohn Marino 		LV_ANY = 0,
40*86d7f5d3SJohn Marino 		LV_REDUCE = 1,
41*86d7f5d3SJohn Marino 		LV_EXTEND = 2
42*86d7f5d3SJohn Marino 	} resize;
43*86d7f5d3SJohn Marino 
44*86d7f5d3SJohn Marino 	int resizefs;
45*86d7f5d3SJohn Marino 	int nofsck;
46*86d7f5d3SJohn Marino 
47*86d7f5d3SJohn Marino 	int argc;
48*86d7f5d3SJohn Marino 	char **argv;
49*86d7f5d3SJohn Marino };
50*86d7f5d3SJohn Marino 
_validate_stripesize(struct cmd_context * cmd,const struct volume_group * vg,struct lvresize_params * lp)51*86d7f5d3SJohn Marino static int _validate_stripesize(struct cmd_context *cmd,
52*86d7f5d3SJohn Marino 				const struct volume_group *vg,
53*86d7f5d3SJohn Marino 				struct lvresize_params *lp)
54*86d7f5d3SJohn Marino {
55*86d7f5d3SJohn Marino 	if (arg_sign_value(cmd, stripesize_ARG, 0) == SIGN_MINUS) {
56*86d7f5d3SJohn Marino 		log_error("Stripesize may not be negative.");
57*86d7f5d3SJohn Marino 		return 0;
58*86d7f5d3SJohn Marino 	}
59*86d7f5d3SJohn Marino 
60*86d7f5d3SJohn Marino 	if (arg_uint_value(cmd, stripesize_ARG, 0) > STRIPE_SIZE_LIMIT * 2) {
61*86d7f5d3SJohn Marino 		log_error("Stripe size cannot be larger than %s",
62*86d7f5d3SJohn Marino 			  display_size(cmd, (uint64_t) STRIPE_SIZE_LIMIT));
63*86d7f5d3SJohn Marino 		return 0;
64*86d7f5d3SJohn Marino 	}
65*86d7f5d3SJohn Marino 
66*86d7f5d3SJohn Marino 	if (!(vg->fid->fmt->features & FMT_SEGMENTS))
67*86d7f5d3SJohn Marino 		log_warn("Varied stripesize not supported. Ignoring.");
68*86d7f5d3SJohn Marino 	else if (arg_uint_value(cmd, stripesize_ARG, 0) > vg->extent_size * 2) {
69*86d7f5d3SJohn Marino 		log_error("Reducing stripe size %s to maximum, "
70*86d7f5d3SJohn Marino 			  "physical extent size %s",
71*86d7f5d3SJohn Marino 			  display_size(cmd,
72*86d7f5d3SJohn Marino 				       (uint64_t) arg_uint_value(cmd, stripesize_ARG, 0)),
73*86d7f5d3SJohn Marino 			  display_size(cmd, (uint64_t) vg->extent_size));
74*86d7f5d3SJohn Marino 		lp->stripe_size = vg->extent_size;
75*86d7f5d3SJohn Marino 	} else
76*86d7f5d3SJohn Marino 		lp->stripe_size = arg_uint_value(cmd, stripesize_ARG, 0);
77*86d7f5d3SJohn Marino 
78*86d7f5d3SJohn Marino 	if (lp->mirrors) {
79*86d7f5d3SJohn Marino 		log_error("Mirrors and striping cannot be combined yet.");
80*86d7f5d3SJohn Marino 		return 0;
81*86d7f5d3SJohn Marino 	}
82*86d7f5d3SJohn Marino 	if (lp->stripe_size & (lp->stripe_size - 1)) {
83*86d7f5d3SJohn Marino 		log_error("Stripe size must be power of 2");
84*86d7f5d3SJohn Marino 		return 0;
85*86d7f5d3SJohn Marino 	}
86*86d7f5d3SJohn Marino 
87*86d7f5d3SJohn Marino 	return 1;
88*86d7f5d3SJohn Marino }
89*86d7f5d3SJohn Marino 
_request_confirmation(struct cmd_context * cmd,const struct volume_group * vg,const struct logical_volume * lv,const struct lvresize_params * lp)90*86d7f5d3SJohn Marino static int _request_confirmation(struct cmd_context *cmd,
91*86d7f5d3SJohn Marino 				 const struct volume_group *vg,
92*86d7f5d3SJohn Marino 				 const struct logical_volume *lv,
93*86d7f5d3SJohn Marino 				 const struct lvresize_params *lp)
94*86d7f5d3SJohn Marino {
95*86d7f5d3SJohn Marino 	struct lvinfo info;
96*86d7f5d3SJohn Marino 
97*86d7f5d3SJohn Marino 	memset(&info, 0, sizeof(info));
98*86d7f5d3SJohn Marino 
99*86d7f5d3SJohn Marino 	if (!lv_info(cmd, lv, &info, 1, 0) && driver_version(NULL, 0)) {
100*86d7f5d3SJohn Marino 		log_error("lv_info failed: aborting");
101*86d7f5d3SJohn Marino 		return 0;
102*86d7f5d3SJohn Marino 	}
103*86d7f5d3SJohn Marino 
104*86d7f5d3SJohn Marino 	if (lp->resizefs) {
105*86d7f5d3SJohn Marino 		if (!info.exists) {
106*86d7f5d3SJohn Marino 			log_error("Logical volume %s must be activated "
107*86d7f5d3SJohn Marino 				  "before resizing filesystem", lp->lv_name);
108*86d7f5d3SJohn Marino 			return 0;
109*86d7f5d3SJohn Marino 		}
110*86d7f5d3SJohn Marino 		return 1;
111*86d7f5d3SJohn Marino 	}
112*86d7f5d3SJohn Marino 
113*86d7f5d3SJohn Marino 	if (!info.exists)
114*86d7f5d3SJohn Marino 		return 1;
115*86d7f5d3SJohn Marino 
116*86d7f5d3SJohn Marino 	log_warn("WARNING: Reducing active%s logical volume to %s",
117*86d7f5d3SJohn Marino 		 info.open_count ? " and open" : "",
118*86d7f5d3SJohn Marino 		 display_size(cmd, (uint64_t) lp->extents * vg->extent_size));
119*86d7f5d3SJohn Marino 
120*86d7f5d3SJohn Marino 	log_warn("THIS MAY DESTROY YOUR DATA (filesystem etc.)");
121*86d7f5d3SJohn Marino 
122*86d7f5d3SJohn Marino 	if (!arg_count(cmd, force_ARG)) {
123*86d7f5d3SJohn Marino 		if (yes_no_prompt("Do you really want to reduce %s? [y/n]: ",
124*86d7f5d3SJohn Marino 				  lp->lv_name) == 'n') {
125*86d7f5d3SJohn Marino 			log_print("Logical volume %s NOT reduced", lp->lv_name);
126*86d7f5d3SJohn Marino 			return 0;
127*86d7f5d3SJohn Marino 		}
128*86d7f5d3SJohn Marino 		if (sigint_caught())
129*86d7f5d3SJohn Marino 			return 0;
130*86d7f5d3SJohn Marino 	}
131*86d7f5d3SJohn Marino 
132*86d7f5d3SJohn Marino 	return 1;
133*86d7f5d3SJohn Marino }
134*86d7f5d3SJohn Marino 
135*86d7f5d3SJohn Marino enum fsadm_cmd_e { FSADM_CMD_CHECK, FSADM_CMD_RESIZE };
136*86d7f5d3SJohn Marino #define FSADM_CMD "fsadm"
137*86d7f5d3SJohn Marino #define FSADM_CMD_MAX_ARGS 6
138*86d7f5d3SJohn Marino 
139*86d7f5d3SJohn Marino /*
140*86d7f5d3SJohn Marino  * FSADM_CMD --dry-run --verbose --force check lv_path
141*86d7f5d3SJohn Marino  * FSADM_CMD --dry-run --verbose --force resize lv_path size
142*86d7f5d3SJohn Marino  */
_fsadm_cmd(struct cmd_context * cmd,const struct volume_group * vg,const struct lvresize_params * lp,enum fsadm_cmd_e fcmd)143*86d7f5d3SJohn Marino static int _fsadm_cmd(struct cmd_context *cmd,
144*86d7f5d3SJohn Marino 		      const struct volume_group *vg,
145*86d7f5d3SJohn Marino 		      const struct lvresize_params *lp,
146*86d7f5d3SJohn Marino 		      enum fsadm_cmd_e fcmd)
147*86d7f5d3SJohn Marino {
148*86d7f5d3SJohn Marino 	char lv_path[PATH_MAX];
149*86d7f5d3SJohn Marino 	char size_buf[SIZE_BUF];
150*86d7f5d3SJohn Marino 	const char *argv[FSADM_CMD_MAX_ARGS + 2];
151*86d7f5d3SJohn Marino 	unsigned i = 0;
152*86d7f5d3SJohn Marino 
153*86d7f5d3SJohn Marino 	argv[i++] = FSADM_CMD;
154*86d7f5d3SJohn Marino 
155*86d7f5d3SJohn Marino 	if (test_mode())
156*86d7f5d3SJohn Marino 		argv[i++] = "--dry-run";
157*86d7f5d3SJohn Marino 
158*86d7f5d3SJohn Marino 	if (verbose_level() >= _LOG_NOTICE)
159*86d7f5d3SJohn Marino 		argv[i++] = "--verbose";
160*86d7f5d3SJohn Marino 
161*86d7f5d3SJohn Marino 	if (arg_count(cmd, force_ARG))
162*86d7f5d3SJohn Marino 		argv[i++] = "--force";
163*86d7f5d3SJohn Marino 
164*86d7f5d3SJohn Marino 	argv[i++] = (fcmd == FSADM_CMD_RESIZE) ? "resize" : "check";
165*86d7f5d3SJohn Marino 
166*86d7f5d3SJohn Marino 	if (dm_snprintf(lv_path, PATH_MAX, "%s%s/%s", cmd->dev_dir, lp->vg_name,
167*86d7f5d3SJohn Marino 			lp->lv_name) < 0) {
168*86d7f5d3SJohn Marino 		log_error("Couldn't create LV path for %s", lp->lv_name);
169*86d7f5d3SJohn Marino 		return 0;
170*86d7f5d3SJohn Marino 	}
171*86d7f5d3SJohn Marino 
172*86d7f5d3SJohn Marino 	argv[i++] = lv_path;
173*86d7f5d3SJohn Marino 
174*86d7f5d3SJohn Marino 	if (fcmd == FSADM_CMD_RESIZE) {
175*86d7f5d3SJohn Marino 		if (dm_snprintf(size_buf, SIZE_BUF, "%" PRIu64 "K",
176*86d7f5d3SJohn Marino 				(uint64_t) lp->extents * vg->extent_size / 2) < 0) {
177*86d7f5d3SJohn Marino 			log_error("Couldn't generate new LV size string");
178*86d7f5d3SJohn Marino 			return 0;
179*86d7f5d3SJohn Marino 		}
180*86d7f5d3SJohn Marino 
181*86d7f5d3SJohn Marino 		argv[i++] = size_buf;
182*86d7f5d3SJohn Marino 	}
183*86d7f5d3SJohn Marino 
184*86d7f5d3SJohn Marino 	argv[i] = NULL;
185*86d7f5d3SJohn Marino 
186*86d7f5d3SJohn Marino 	return exec_cmd(cmd, argv);
187*86d7f5d3SJohn Marino }
188*86d7f5d3SJohn Marino 
_lvresize_params(struct cmd_context * cmd,int argc,char ** argv,struct lvresize_params * lp)189*86d7f5d3SJohn Marino static int _lvresize_params(struct cmd_context *cmd, int argc, char **argv,
190*86d7f5d3SJohn Marino 			    struct lvresize_params *lp)
191*86d7f5d3SJohn Marino {
192*86d7f5d3SJohn Marino 	const char *cmd_name;
193*86d7f5d3SJohn Marino 	char *st;
194*86d7f5d3SJohn Marino 	unsigned dev_dir_found = 0;
195*86d7f5d3SJohn Marino 
196*86d7f5d3SJohn Marino 	lp->sign = SIGN_NONE;
197*86d7f5d3SJohn Marino 	lp->resize = LV_ANY;
198*86d7f5d3SJohn Marino 
199*86d7f5d3SJohn Marino 	cmd_name = command_name(cmd);
200*86d7f5d3SJohn Marino 	if (!strcmp(cmd_name, "lvreduce"))
201*86d7f5d3SJohn Marino 		lp->resize = LV_REDUCE;
202*86d7f5d3SJohn Marino 	if (!strcmp(cmd_name, "lvextend"))
203*86d7f5d3SJohn Marino 		lp->resize = LV_EXTEND;
204*86d7f5d3SJohn Marino 
205*86d7f5d3SJohn Marino 	/*
206*86d7f5d3SJohn Marino 	 * Allow omission of extents and size if the user has given us
207*86d7f5d3SJohn Marino 	 * one or more PVs.  Most likely, the intent was "resize this
208*86d7f5d3SJohn Marino 	 * LV the best you can with these PVs"
209*86d7f5d3SJohn Marino 	 */
210*86d7f5d3SJohn Marino 	if ((arg_count(cmd, extents_ARG) + arg_count(cmd, size_ARG) == 0) &&
211*86d7f5d3SJohn Marino 	    (argc >= 2)) {
212*86d7f5d3SJohn Marino 		lp->extents = 100;
213*86d7f5d3SJohn Marino 		lp->percent = PERCENT_PVS;
214*86d7f5d3SJohn Marino 		lp->sign = SIGN_PLUS;
215*86d7f5d3SJohn Marino 	} else if ((arg_count(cmd, extents_ARG) +
216*86d7f5d3SJohn Marino 		    arg_count(cmd, size_ARG) != 1)) {
217*86d7f5d3SJohn Marino 		log_error("Please specify either size or extents but not "
218*86d7f5d3SJohn Marino 			  "both.");
219*86d7f5d3SJohn Marino 		return 0;
220*86d7f5d3SJohn Marino 	}
221*86d7f5d3SJohn Marino 
222*86d7f5d3SJohn Marino 	if (arg_count(cmd, extents_ARG)) {
223*86d7f5d3SJohn Marino 		lp->extents = arg_uint_value(cmd, extents_ARG, 0);
224*86d7f5d3SJohn Marino 		lp->sign = arg_sign_value(cmd, extents_ARG, SIGN_NONE);
225*86d7f5d3SJohn Marino 		lp->percent = arg_percent_value(cmd, extents_ARG, PERCENT_NONE);
226*86d7f5d3SJohn Marino 	}
227*86d7f5d3SJohn Marino 
228*86d7f5d3SJohn Marino 	/* Size returned in kilobyte units; held in sectors */
229*86d7f5d3SJohn Marino 	if (arg_count(cmd, size_ARG)) {
230*86d7f5d3SJohn Marino 		lp->size = arg_uint64_value(cmd, size_ARG, UINT64_C(0));
231*86d7f5d3SJohn Marino 		lp->sign = arg_sign_value(cmd, size_ARG, SIGN_NONE);
232*86d7f5d3SJohn Marino 		lp->percent = PERCENT_NONE;
233*86d7f5d3SJohn Marino 	}
234*86d7f5d3SJohn Marino 
235*86d7f5d3SJohn Marino 	if (lp->resize == LV_EXTEND && lp->sign == SIGN_MINUS) {
236*86d7f5d3SJohn Marino 		log_error("Negative argument not permitted - use lvreduce");
237*86d7f5d3SJohn Marino 		return 0;
238*86d7f5d3SJohn Marino 	}
239*86d7f5d3SJohn Marino 
240*86d7f5d3SJohn Marino 	if (lp->resize == LV_REDUCE && lp->sign == SIGN_PLUS) {
241*86d7f5d3SJohn Marino 		log_error("Positive sign not permitted - use lvextend");
242*86d7f5d3SJohn Marino 		return 0;
243*86d7f5d3SJohn Marino 	}
244*86d7f5d3SJohn Marino 
245*86d7f5d3SJohn Marino 	lp->resizefs = arg_is_set(cmd, resizefs_ARG);
246*86d7f5d3SJohn Marino 	lp->nofsck = arg_is_set(cmd, nofsck_ARG);
247*86d7f5d3SJohn Marino 
248*86d7f5d3SJohn Marino 	if (!argc) {
249*86d7f5d3SJohn Marino 		log_error("Please provide the logical volume name");
250*86d7f5d3SJohn Marino 		return 0;
251*86d7f5d3SJohn Marino 	}
252*86d7f5d3SJohn Marino 
253*86d7f5d3SJohn Marino 	lp->lv_name = argv[0];
254*86d7f5d3SJohn Marino 	argv++;
255*86d7f5d3SJohn Marino 	argc--;
256*86d7f5d3SJohn Marino 
257*86d7f5d3SJohn Marino 	if (!(lp->lv_name = skip_dev_dir(cmd, lp->lv_name, &dev_dir_found)) ||
258*86d7f5d3SJohn Marino 	    !(lp->vg_name = extract_vgname(cmd, lp->lv_name))) {
259*86d7f5d3SJohn Marino 		log_error("Please provide a volume group name");
260*86d7f5d3SJohn Marino 		return 0;
261*86d7f5d3SJohn Marino 	}
262*86d7f5d3SJohn Marino 
263*86d7f5d3SJohn Marino 	if (!validate_name(lp->vg_name)) {
264*86d7f5d3SJohn Marino 		log_error("Volume group name %s has invalid characters",
265*86d7f5d3SJohn Marino 			  lp->vg_name);
266*86d7f5d3SJohn Marino 		return 0;
267*86d7f5d3SJohn Marino 	}
268*86d7f5d3SJohn Marino 
269*86d7f5d3SJohn Marino 	if ((st = strrchr(lp->lv_name, '/')))
270*86d7f5d3SJohn Marino 		lp->lv_name = st + 1;
271*86d7f5d3SJohn Marino 
272*86d7f5d3SJohn Marino 	lp->argc = argc;
273*86d7f5d3SJohn Marino 	lp->argv = argv;
274*86d7f5d3SJohn Marino 
275*86d7f5d3SJohn Marino 	return 1;
276*86d7f5d3SJohn Marino }
277*86d7f5d3SJohn Marino 
_lvresize(struct cmd_context * cmd,struct volume_group * vg,struct lvresize_params * lp)278*86d7f5d3SJohn Marino static int _lvresize(struct cmd_context *cmd, struct volume_group *vg,
279*86d7f5d3SJohn Marino 		     struct lvresize_params *lp)
280*86d7f5d3SJohn Marino {
281*86d7f5d3SJohn Marino 	struct logical_volume *lv;
282*86d7f5d3SJohn Marino 	struct lvinfo info;
283*86d7f5d3SJohn Marino 	uint32_t stripesize_extents = 0;
284*86d7f5d3SJohn Marino 	uint32_t seg_stripes = 0, seg_stripesize = 0, seg_size = 0;
285*86d7f5d3SJohn Marino 	uint32_t seg_mirrors = 0;
286*86d7f5d3SJohn Marino 	uint32_t extents_used = 0;
287*86d7f5d3SJohn Marino 	uint32_t size_rest;
288*86d7f5d3SJohn Marino 	uint32_t pv_extent_count = 0;
289*86d7f5d3SJohn Marino 	alloc_policy_t alloc;
290*86d7f5d3SJohn Marino 	struct logical_volume *lock_lv;
291*86d7f5d3SJohn Marino 	struct lv_list *lvl;
292*86d7f5d3SJohn Marino 	struct lv_segment *seg;
293*86d7f5d3SJohn Marino 	uint32_t seg_extents;
294*86d7f5d3SJohn Marino 	uint32_t sz, str;
295*86d7f5d3SJohn Marino 	struct dm_list *pvh = NULL;
296*86d7f5d3SJohn Marino 
297*86d7f5d3SJohn Marino 	/* does LV exist? */
298*86d7f5d3SJohn Marino 	if (!(lvl = find_lv_in_vg(vg, lp->lv_name))) {
299*86d7f5d3SJohn Marino 		log_error("Logical volume %s not found in volume group %s",
300*86d7f5d3SJohn Marino 			  lp->lv_name, lp->vg_name);
301*86d7f5d3SJohn Marino 		return ECMD_FAILED;
302*86d7f5d3SJohn Marino 	}
303*86d7f5d3SJohn Marino 
304*86d7f5d3SJohn Marino 	if (arg_count(cmd, stripes_ARG)) {
305*86d7f5d3SJohn Marino 		if (vg->fid->fmt->features & FMT_SEGMENTS)
306*86d7f5d3SJohn Marino 			lp->stripes = arg_uint_value(cmd, stripes_ARG, 1);
307*86d7f5d3SJohn Marino 		else
308*86d7f5d3SJohn Marino 			log_warn("Varied striping not supported. Ignoring.");
309*86d7f5d3SJohn Marino 	}
310*86d7f5d3SJohn Marino 
311*86d7f5d3SJohn Marino 	if (arg_count(cmd, mirrors_ARG)) {
312*86d7f5d3SJohn Marino 		if (vg->fid->fmt->features & FMT_SEGMENTS)
313*86d7f5d3SJohn Marino 			lp->mirrors = arg_uint_value(cmd, mirrors_ARG, 1) + 1;
314*86d7f5d3SJohn Marino 		else
315*86d7f5d3SJohn Marino 			log_warn("Mirrors not supported. Ignoring.");
316*86d7f5d3SJohn Marino 		if (arg_sign_value(cmd, mirrors_ARG, 0) == SIGN_MINUS) {
317*86d7f5d3SJohn Marino 			log_error("Mirrors argument may not be negative");
318*86d7f5d3SJohn Marino 			return EINVALID_CMD_LINE;
319*86d7f5d3SJohn Marino 		}
320*86d7f5d3SJohn Marino 	}
321*86d7f5d3SJohn Marino 
322*86d7f5d3SJohn Marino 	if (arg_count(cmd, stripesize_ARG) &&
323*86d7f5d3SJohn Marino 	    !_validate_stripesize(cmd, vg, lp))
324*86d7f5d3SJohn Marino 		return EINVALID_CMD_LINE;
325*86d7f5d3SJohn Marino 
326*86d7f5d3SJohn Marino 	lv = lvl->lv;
327*86d7f5d3SJohn Marino 
328*86d7f5d3SJohn Marino 	if (lv->status & LOCKED) {
329*86d7f5d3SJohn Marino 		log_error("Can't resize locked LV %s", lv->name);
330*86d7f5d3SJohn Marino 		return ECMD_FAILED;
331*86d7f5d3SJohn Marino 	}
332*86d7f5d3SJohn Marino 
333*86d7f5d3SJohn Marino 	if (lv->status & CONVERTING) {
334*86d7f5d3SJohn Marino 		log_error("Can't resize %s while lvconvert in progress", lv->name);
335*86d7f5d3SJohn Marino 		return ECMD_FAILED;
336*86d7f5d3SJohn Marino 	}
337*86d7f5d3SJohn Marino 
338*86d7f5d3SJohn Marino 	alloc = arg_uint_value(cmd, alloc_ARG, lv->alloc);
339*86d7f5d3SJohn Marino 
340*86d7f5d3SJohn Marino 	if (lp->size) {
341*86d7f5d3SJohn Marino 		if (lp->size % vg->extent_size) {
342*86d7f5d3SJohn Marino 			if (lp->sign == SIGN_MINUS)
343*86d7f5d3SJohn Marino 				lp->size -= lp->size % vg->extent_size;
344*86d7f5d3SJohn Marino 			else
345*86d7f5d3SJohn Marino 				lp->size += vg->extent_size -
346*86d7f5d3SJohn Marino 				    (lp->size % vg->extent_size);
347*86d7f5d3SJohn Marino 
348*86d7f5d3SJohn Marino 			log_print("Rounding up size to full physical extent %s",
349*86d7f5d3SJohn Marino 				  display_size(cmd, (uint64_t) lp->size));
350*86d7f5d3SJohn Marino 		}
351*86d7f5d3SJohn Marino 
352*86d7f5d3SJohn Marino 		lp->extents = lp->size / vg->extent_size;
353*86d7f5d3SJohn Marino 	}
354*86d7f5d3SJohn Marino 
355*86d7f5d3SJohn Marino 	if (!(pvh = lp->argc ? create_pv_list(cmd->mem, vg, lp->argc,
356*86d7f5d3SJohn Marino 						     lp->argv, 1) : &vg->pvs)) {
357*86d7f5d3SJohn Marino 		stack;
358*86d7f5d3SJohn Marino 		return ECMD_FAILED;
359*86d7f5d3SJohn Marino 	}
360*86d7f5d3SJohn Marino 
361*86d7f5d3SJohn Marino 	switch(lp->percent) {
362*86d7f5d3SJohn Marino 		case PERCENT_VG:
363*86d7f5d3SJohn Marino 			lp->extents = lp->extents * vg->extent_count / 100;
364*86d7f5d3SJohn Marino 			break;
365*86d7f5d3SJohn Marino 		case PERCENT_FREE:
366*86d7f5d3SJohn Marino 			lp->extents = lp->extents * vg->free_count / 100;
367*86d7f5d3SJohn Marino 			break;
368*86d7f5d3SJohn Marino 		case PERCENT_LV:
369*86d7f5d3SJohn Marino 			lp->extents = lp->extents * lv->le_count / 100;
370*86d7f5d3SJohn Marino 			break;
371*86d7f5d3SJohn Marino 		case PERCENT_PVS:
372*86d7f5d3SJohn Marino 			if (lp->argc) {
373*86d7f5d3SJohn Marino 				pv_extent_count = pv_list_extents_free(pvh);
374*86d7f5d3SJohn Marino 				lp->extents = lp->extents * pv_extent_count / 100;
375*86d7f5d3SJohn Marino 			} else
376*86d7f5d3SJohn Marino 				lp->extents = lp->extents * vg->extent_count / 100;
377*86d7f5d3SJohn Marino 			break;
378*86d7f5d3SJohn Marino 		case PERCENT_NONE:
379*86d7f5d3SJohn Marino 			break;
380*86d7f5d3SJohn Marino 	}
381*86d7f5d3SJohn Marino 
382*86d7f5d3SJohn Marino 	if (lp->sign == SIGN_PLUS)
383*86d7f5d3SJohn Marino 		lp->extents += lv->le_count;
384*86d7f5d3SJohn Marino 
385*86d7f5d3SJohn Marino 	if (lp->sign == SIGN_MINUS) {
386*86d7f5d3SJohn Marino 		if (lp->extents >= lv->le_count) {
387*86d7f5d3SJohn Marino 			log_error("Unable to reduce %s below 1 extent",
388*86d7f5d3SJohn Marino 				  lp->lv_name);
389*86d7f5d3SJohn Marino 			return EINVALID_CMD_LINE;
390*86d7f5d3SJohn Marino 		}
391*86d7f5d3SJohn Marino 
392*86d7f5d3SJohn Marino 		lp->extents = lv->le_count - lp->extents;
393*86d7f5d3SJohn Marino 	}
394*86d7f5d3SJohn Marino 
395*86d7f5d3SJohn Marino 	if (!lp->extents) {
396*86d7f5d3SJohn Marino 		log_error("New size of 0 not permitted");
397*86d7f5d3SJohn Marino 		return EINVALID_CMD_LINE;
398*86d7f5d3SJohn Marino 	}
399*86d7f5d3SJohn Marino 
400*86d7f5d3SJohn Marino 	if (lp->extents == lv->le_count) {
401*86d7f5d3SJohn Marino 		if (!lp->resizefs) {
402*86d7f5d3SJohn Marino 			log_error("New size (%d extents) matches existing size "
403*86d7f5d3SJohn Marino 				  "(%d extents)", lp->extents, lv->le_count);
404*86d7f5d3SJohn Marino 			return EINVALID_CMD_LINE;
405*86d7f5d3SJohn Marino 		}
406*86d7f5d3SJohn Marino 		lp->resize = LV_EXTEND; /* lets pretend zero size extension */
407*86d7f5d3SJohn Marino 	}
408*86d7f5d3SJohn Marino 
409*86d7f5d3SJohn Marino 	seg_size = lp->extents - lv->le_count;
410*86d7f5d3SJohn Marino 
411*86d7f5d3SJohn Marino 	/* Use segment type of last segment */
412*86d7f5d3SJohn Marino 	dm_list_iterate_items(seg, &lv->segments) {
413*86d7f5d3SJohn Marino 		lp->segtype = seg->segtype;
414*86d7f5d3SJohn Marino 	}
415*86d7f5d3SJohn Marino 
416*86d7f5d3SJohn Marino 	/* FIXME Support LVs with mixed segment types */
417*86d7f5d3SJohn Marino 	if (lp->segtype != arg_ptr_value(cmd, type_ARG, lp->segtype)) {
418*86d7f5d3SJohn Marino 		log_error("VolumeType does not match (%s)", lp->segtype->name);
419*86d7f5d3SJohn Marino 		return EINVALID_CMD_LINE;
420*86d7f5d3SJohn Marino 	}
421*86d7f5d3SJohn Marino 
422*86d7f5d3SJohn Marino 	/* If extending, find stripes, stripesize & size of last segment */
423*86d7f5d3SJohn Marino 	if ((lp->extents > lv->le_count) &&
424*86d7f5d3SJohn Marino 	    !(lp->stripes == 1 || (lp->stripes > 1 && lp->stripe_size))) {
425*86d7f5d3SJohn Marino 		dm_list_iterate_items(seg, &lv->segments) {
426*86d7f5d3SJohn Marino 			if (!seg_is_striped(seg))
427*86d7f5d3SJohn Marino 				continue;
428*86d7f5d3SJohn Marino 
429*86d7f5d3SJohn Marino 			sz = seg->stripe_size;
430*86d7f5d3SJohn Marino 			str = seg->area_count;
431*86d7f5d3SJohn Marino 
432*86d7f5d3SJohn Marino 			if ((seg_stripesize && seg_stripesize != sz &&
433*86d7f5d3SJohn Marino 			     !lp->stripe_size) ||
434*86d7f5d3SJohn Marino 			    (seg_stripes && seg_stripes != str && !lp->stripes)) {
435*86d7f5d3SJohn Marino 				log_error("Please specify number of "
436*86d7f5d3SJohn Marino 					  "stripes (-i) and stripesize (-I)");
437*86d7f5d3SJohn Marino 				return EINVALID_CMD_LINE;
438*86d7f5d3SJohn Marino 			}
439*86d7f5d3SJohn Marino 
440*86d7f5d3SJohn Marino 			seg_stripesize = sz;
441*86d7f5d3SJohn Marino 			seg_stripes = str;
442*86d7f5d3SJohn Marino 		}
443*86d7f5d3SJohn Marino 
444*86d7f5d3SJohn Marino 		if (!lp->stripes)
445*86d7f5d3SJohn Marino 			lp->stripes = seg_stripes;
446*86d7f5d3SJohn Marino 
447*86d7f5d3SJohn Marino 		if (!lp->stripe_size && lp->stripes > 1) {
448*86d7f5d3SJohn Marino 			if (seg_stripesize) {
449*86d7f5d3SJohn Marino 				log_print("Using stripesize of last segment %s",
450*86d7f5d3SJohn Marino 					  display_size(cmd, (uint64_t) seg_stripesize));
451*86d7f5d3SJohn Marino 				lp->stripe_size = seg_stripesize;
452*86d7f5d3SJohn Marino 			} else {
453*86d7f5d3SJohn Marino 				lp->stripe_size =
454*86d7f5d3SJohn Marino 					find_config_tree_int(cmd,
455*86d7f5d3SJohn Marino 							"metadata/stripesize",
456*86d7f5d3SJohn Marino 							DEFAULT_STRIPESIZE) * 2;
457*86d7f5d3SJohn Marino 				log_print("Using default stripesize %s",
458*86d7f5d3SJohn Marino 					  display_size(cmd, (uint64_t) lp->stripe_size));
459*86d7f5d3SJohn Marino 			}
460*86d7f5d3SJohn Marino 		}
461*86d7f5d3SJohn Marino 	}
462*86d7f5d3SJohn Marino 
463*86d7f5d3SJohn Marino 	/* If extending, find mirrors of last segment */
464*86d7f5d3SJohn Marino 	if ((lp->extents > lv->le_count)) {
465*86d7f5d3SJohn Marino 		dm_list_iterate_back_items(seg, &lv->segments) {
466*86d7f5d3SJohn Marino 			if (seg_is_mirrored(seg))
467*86d7f5d3SJohn Marino 				seg_mirrors = lv_mirror_count(seg->lv);
468*86d7f5d3SJohn Marino 			else
469*86d7f5d3SJohn Marino 				seg_mirrors = 0;
470*86d7f5d3SJohn Marino 			break;
471*86d7f5d3SJohn Marino 		}
472*86d7f5d3SJohn Marino 		if (!arg_count(cmd, mirrors_ARG) && seg_mirrors) {
473*86d7f5d3SJohn Marino 			log_print("Extending %" PRIu32 " mirror images.",
474*86d7f5d3SJohn Marino 				  seg_mirrors);
475*86d7f5d3SJohn Marino 			lp->mirrors = seg_mirrors;
476*86d7f5d3SJohn Marino 		}
477*86d7f5d3SJohn Marino 		if ((arg_count(cmd, mirrors_ARG) || seg_mirrors) &&
478*86d7f5d3SJohn Marino 		    (lp->mirrors != seg_mirrors)) {
479*86d7f5d3SJohn Marino 			log_error("Cannot vary number of mirrors in LV yet.");
480*86d7f5d3SJohn Marino 			return EINVALID_CMD_LINE;
481*86d7f5d3SJohn Marino 		}
482*86d7f5d3SJohn Marino 	}
483*86d7f5d3SJohn Marino 
484*86d7f5d3SJohn Marino 	/* If reducing, find stripes, stripesize & size of last segment */
485*86d7f5d3SJohn Marino 	if (lp->extents < lv->le_count) {
486*86d7f5d3SJohn Marino 		extents_used = 0;
487*86d7f5d3SJohn Marino 
488*86d7f5d3SJohn Marino 		if (lp->stripes || lp->stripe_size || lp->mirrors)
489*86d7f5d3SJohn Marino 			log_error("Ignoring stripes, stripesize and mirrors "
490*86d7f5d3SJohn Marino 				  "arguments when reducing");
491*86d7f5d3SJohn Marino 
492*86d7f5d3SJohn Marino 		dm_list_iterate_items(seg, &lv->segments) {
493*86d7f5d3SJohn Marino 			seg_extents = seg->len;
494*86d7f5d3SJohn Marino 
495*86d7f5d3SJohn Marino 			if (seg_is_striped(seg)) {
496*86d7f5d3SJohn Marino 				seg_stripesize = seg->stripe_size;
497*86d7f5d3SJohn Marino 				seg_stripes = seg->area_count;
498*86d7f5d3SJohn Marino 			}
499*86d7f5d3SJohn Marino 
500*86d7f5d3SJohn Marino 			if (seg_is_mirrored(seg))
501*86d7f5d3SJohn Marino 				seg_mirrors = lv_mirror_count(seg->lv);
502*86d7f5d3SJohn Marino 			else
503*86d7f5d3SJohn Marino 				seg_mirrors = 0;
504*86d7f5d3SJohn Marino 
505*86d7f5d3SJohn Marino 			if (lp->extents <= extents_used + seg_extents)
506*86d7f5d3SJohn Marino 				break;
507*86d7f5d3SJohn Marino 
508*86d7f5d3SJohn Marino 			extents_used += seg_extents;
509*86d7f5d3SJohn Marino 		}
510*86d7f5d3SJohn Marino 
511*86d7f5d3SJohn Marino 		seg_size = lp->extents - extents_used;
512*86d7f5d3SJohn Marino 		lp->stripe_size = seg_stripesize;
513*86d7f5d3SJohn Marino 		lp->stripes = seg_stripes;
514*86d7f5d3SJohn Marino 		lp->mirrors = seg_mirrors;
515*86d7f5d3SJohn Marino 	}
516*86d7f5d3SJohn Marino 
517*86d7f5d3SJohn Marino 	if (lp->stripes > 1 && !lp->stripe_size) {
518*86d7f5d3SJohn Marino 		log_error("Stripesize for striped segment should not be 0!");
519*86d7f5d3SJohn Marino 		return EINVALID_CMD_LINE;
520*86d7f5d3SJohn Marino 	}
521*86d7f5d3SJohn Marino 
522*86d7f5d3SJohn Marino 	if ((lp->stripes > 1)) {
523*86d7f5d3SJohn Marino 		if (!(stripesize_extents = lp->stripe_size / vg->extent_size))
524*86d7f5d3SJohn Marino 			stripesize_extents = 1;
525*86d7f5d3SJohn Marino 
526*86d7f5d3SJohn Marino 		if ((size_rest = seg_size % (lp->stripes * stripesize_extents))) {
527*86d7f5d3SJohn Marino 			log_print("Rounding size (%d extents) down to stripe "
528*86d7f5d3SJohn Marino 				  "boundary size for segment (%d extents)",
529*86d7f5d3SJohn Marino 				  lp->extents, lp->extents - size_rest);
530*86d7f5d3SJohn Marino 			lp->extents = lp->extents - size_rest;
531*86d7f5d3SJohn Marino 		}
532*86d7f5d3SJohn Marino 
533*86d7f5d3SJohn Marino 		if (lp->stripe_size < STRIPE_SIZE_MIN) {
534*86d7f5d3SJohn Marino 			log_error("Invalid stripe size %s",
535*86d7f5d3SJohn Marino 				  display_size(cmd, (uint64_t) lp->stripe_size));
536*86d7f5d3SJohn Marino 			return EINVALID_CMD_LINE;
537*86d7f5d3SJohn Marino 		}
538*86d7f5d3SJohn Marino 	}
539*86d7f5d3SJohn Marino 
540*86d7f5d3SJohn Marino 	if (lp->extents < lv->le_count) {
541*86d7f5d3SJohn Marino 		if (lp->resize == LV_EXTEND) {
542*86d7f5d3SJohn Marino 			log_error("New size given (%d extents) not larger "
543*86d7f5d3SJohn Marino 				  "than existing size (%d extents)",
544*86d7f5d3SJohn Marino 				  lp->extents, lv->le_count);
545*86d7f5d3SJohn Marino 			return EINVALID_CMD_LINE;
546*86d7f5d3SJohn Marino 		}
547*86d7f5d3SJohn Marino 		lp->resize = LV_REDUCE;
548*86d7f5d3SJohn Marino 	} else if (lp->extents > lv->le_count) {
549*86d7f5d3SJohn Marino 		if (lp->resize == LV_REDUCE) {
550*86d7f5d3SJohn Marino 			log_error("New size given (%d extents) not less than "
551*86d7f5d3SJohn Marino 				  "existing size (%d extents)", lp->extents,
552*86d7f5d3SJohn Marino 				  lv->le_count);
553*86d7f5d3SJohn Marino 			return EINVALID_CMD_LINE;
554*86d7f5d3SJohn Marino 		}
555*86d7f5d3SJohn Marino 		lp->resize = LV_EXTEND;
556*86d7f5d3SJohn Marino 	}
557*86d7f5d3SJohn Marino 
558*86d7f5d3SJohn Marino 	if (lv_is_origin(lv)) {
559*86d7f5d3SJohn Marino 		if (lp->resize == LV_REDUCE) {
560*86d7f5d3SJohn Marino 			log_error("Snapshot origin volumes cannot be reduced "
561*86d7f5d3SJohn Marino 				  "in size yet.");
562*86d7f5d3SJohn Marino 			return ECMD_FAILED;
563*86d7f5d3SJohn Marino 		}
564*86d7f5d3SJohn Marino 
565*86d7f5d3SJohn Marino 		memset(&info, 0, sizeof(info));
566*86d7f5d3SJohn Marino 
567*86d7f5d3SJohn Marino 		if (lv_info(cmd, lv, &info, 0, 0) && info.exists) {
568*86d7f5d3SJohn Marino 			log_error("Snapshot origin volumes can be resized "
569*86d7f5d3SJohn Marino 				  "only while inactive: try lvchange -an");
570*86d7f5d3SJohn Marino 			return ECMD_FAILED;
571*86d7f5d3SJohn Marino 		}
572*86d7f5d3SJohn Marino 	}
573*86d7f5d3SJohn Marino 
574*86d7f5d3SJohn Marino 	if ((lp->resize == LV_REDUCE) && lp->argc)
575*86d7f5d3SJohn Marino 		log_warn("Ignoring PVs on command line when reducing");
576*86d7f5d3SJohn Marino 
577*86d7f5d3SJohn Marino 	/* Request confirmation before operations that are often mistakes. */
578*86d7f5d3SJohn Marino 	if ((lp->resizefs || (lp->resize == LV_REDUCE)) &&
579*86d7f5d3SJohn Marino 	    !_request_confirmation(cmd, vg, lv, lp)) {
580*86d7f5d3SJohn Marino 		stack;
581*86d7f5d3SJohn Marino 		return ECMD_FAILED;
582*86d7f5d3SJohn Marino 	}
583*86d7f5d3SJohn Marino 
584*86d7f5d3SJohn Marino 	if (lp->resizefs) {
585*86d7f5d3SJohn Marino 		if (!lp->nofsck &&
586*86d7f5d3SJohn Marino 		    !_fsadm_cmd(cmd, vg, lp, FSADM_CMD_CHECK)) {
587*86d7f5d3SJohn Marino 			stack;
588*86d7f5d3SJohn Marino 			return ECMD_FAILED;
589*86d7f5d3SJohn Marino 		}
590*86d7f5d3SJohn Marino 
591*86d7f5d3SJohn Marino 		if ((lp->resize == LV_REDUCE) &&
592*86d7f5d3SJohn Marino 		    !_fsadm_cmd(cmd, vg, lp, FSADM_CMD_RESIZE)) {
593*86d7f5d3SJohn Marino 			stack;
594*86d7f5d3SJohn Marino 			return ECMD_FAILED;
595*86d7f5d3SJohn Marino 		}
596*86d7f5d3SJohn Marino 	}
597*86d7f5d3SJohn Marino 
598*86d7f5d3SJohn Marino 	if (!archive(vg)) {
599*86d7f5d3SJohn Marino 		stack;
600*86d7f5d3SJohn Marino 		return ECMD_FAILED;
601*86d7f5d3SJohn Marino 	}
602*86d7f5d3SJohn Marino 
603*86d7f5d3SJohn Marino 	log_print("%sing logical volume %s to %s",
604*86d7f5d3SJohn Marino 		  (lp->resize == LV_REDUCE) ? "Reduc" : "Extend",
605*86d7f5d3SJohn Marino 		  lp->lv_name,
606*86d7f5d3SJohn Marino 		  display_size(cmd, (uint64_t) lp->extents * vg->extent_size));
607*86d7f5d3SJohn Marino 
608*86d7f5d3SJohn Marino 	if (lp->resize == LV_REDUCE) {
609*86d7f5d3SJohn Marino 		if (!lv_reduce(lv, lv->le_count - lp->extents)) {
610*86d7f5d3SJohn Marino 			stack;
611*86d7f5d3SJohn Marino 			return ECMD_FAILED;
612*86d7f5d3SJohn Marino 		}
613*86d7f5d3SJohn Marino 	} else if ((lp->extents > lv->le_count) && /* Ensure we extend */
614*86d7f5d3SJohn Marino 		   !lv_extend(lv, lp->segtype, lp->stripes,
615*86d7f5d3SJohn Marino 			      lp->stripe_size, lp->mirrors,
616*86d7f5d3SJohn Marino 			      lp->extents - lv->le_count,
617*86d7f5d3SJohn Marino 			      NULL, 0u, 0u, pvh, alloc)) {
618*86d7f5d3SJohn Marino 		stack;
619*86d7f5d3SJohn Marino 		return ECMD_FAILED;
620*86d7f5d3SJohn Marino 	}
621*86d7f5d3SJohn Marino 
622*86d7f5d3SJohn Marino 	/* store vg on disk(s) */
623*86d7f5d3SJohn Marino 	if (!vg_write(vg)) {
624*86d7f5d3SJohn Marino 		stack;
625*86d7f5d3SJohn Marino 		return ECMD_FAILED;
626*86d7f5d3SJohn Marino 	}
627*86d7f5d3SJohn Marino 
628*86d7f5d3SJohn Marino 	/* If snapshot, must suspend all associated devices */
629*86d7f5d3SJohn Marino 	if (lv_is_cow(lv))
630*86d7f5d3SJohn Marino 		lock_lv = origin_from_cow(lv);
631*86d7f5d3SJohn Marino 	else
632*86d7f5d3SJohn Marino 		lock_lv = lv;
633*86d7f5d3SJohn Marino 
634*86d7f5d3SJohn Marino 	if (!suspend_lv(cmd, lock_lv)) {
635*86d7f5d3SJohn Marino 		log_error("Failed to suspend %s", lp->lv_name);
636*86d7f5d3SJohn Marino 		vg_revert(vg);
637*86d7f5d3SJohn Marino 		backup(vg);
638*86d7f5d3SJohn Marino 		return ECMD_FAILED;
639*86d7f5d3SJohn Marino 	}
640*86d7f5d3SJohn Marino 
641*86d7f5d3SJohn Marino 	if (!vg_commit(vg)) {
642*86d7f5d3SJohn Marino 		stack;
643*86d7f5d3SJohn Marino 		resume_lv(cmd, lock_lv);
644*86d7f5d3SJohn Marino 		backup(vg);
645*86d7f5d3SJohn Marino 		return ECMD_FAILED;
646*86d7f5d3SJohn Marino 	}
647*86d7f5d3SJohn Marino 
648*86d7f5d3SJohn Marino 	if (!resume_lv(cmd, lock_lv)) {
649*86d7f5d3SJohn Marino 		log_error("Problem reactivating %s", lp->lv_name);
650*86d7f5d3SJohn Marino 		backup(vg);
651*86d7f5d3SJohn Marino 		return ECMD_FAILED;
652*86d7f5d3SJohn Marino 	}
653*86d7f5d3SJohn Marino 
654*86d7f5d3SJohn Marino 	backup(vg);
655*86d7f5d3SJohn Marino 
656*86d7f5d3SJohn Marino 	log_print("Logical volume %s successfully resized", lp->lv_name);
657*86d7f5d3SJohn Marino 
658*86d7f5d3SJohn Marino 	if (lp->resizefs && (lp->resize == LV_EXTEND) &&
659*86d7f5d3SJohn Marino 	    !_fsadm_cmd(cmd, vg, lp, FSADM_CMD_RESIZE)) {
660*86d7f5d3SJohn Marino 		stack;
661*86d7f5d3SJohn Marino 		return ECMD_FAILED;
662*86d7f5d3SJohn Marino 	}
663*86d7f5d3SJohn Marino 
664*86d7f5d3SJohn Marino 	return ECMD_PROCESSED;
665*86d7f5d3SJohn Marino }
666*86d7f5d3SJohn Marino 
lvresize(struct cmd_context * cmd,int argc,char ** argv)667*86d7f5d3SJohn Marino int lvresize(struct cmd_context *cmd, int argc, char **argv)
668*86d7f5d3SJohn Marino {
669*86d7f5d3SJohn Marino 	struct lvresize_params lp;
670*86d7f5d3SJohn Marino 	struct volume_group *vg;
671*86d7f5d3SJohn Marino 	int r;
672*86d7f5d3SJohn Marino 
673*86d7f5d3SJohn Marino 	memset(&lp, 0, sizeof(lp));
674*86d7f5d3SJohn Marino 
675*86d7f5d3SJohn Marino 	if (!_lvresize_params(cmd, argc, argv, &lp))
676*86d7f5d3SJohn Marino 		return EINVALID_CMD_LINE;
677*86d7f5d3SJohn Marino 
678*86d7f5d3SJohn Marino 	log_verbose("Finding volume group %s", lp.vg_name);
679*86d7f5d3SJohn Marino 	vg = vg_read_for_update(cmd, lp.vg_name, NULL, 0);
680*86d7f5d3SJohn Marino 	if (vg_read_error(vg)) {
681*86d7f5d3SJohn Marino 		vg_release(vg);
682*86d7f5d3SJohn Marino 		stack;
683*86d7f5d3SJohn Marino 		return ECMD_FAILED;
684*86d7f5d3SJohn Marino 	}
685*86d7f5d3SJohn Marino 
686*86d7f5d3SJohn Marino 	if (!(r = _lvresize(cmd, vg, &lp)))
687*86d7f5d3SJohn Marino 		stack;
688*86d7f5d3SJohn Marino 
689*86d7f5d3SJohn Marino 	unlock_and_release_vg(cmd, vg, lp.vg_name);
690*86d7f5d3SJohn Marino 
691*86d7f5d3SJohn Marino 	return r;
692*86d7f5d3SJohn Marino }
693