]> sourceware.org Git - lvm2.git/blame - tools/lvresize.c
Fix a failing test (it used a combination of lvconvert parameters that is no
[lvm2.git] / tools / lvresize.c
CommitLineData
03a8a07d 1/*
1832f310 2 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
c8669f6b 3 * Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
03a8a07d 4 *
6606c3ae 5 * This file is part of LVM2.
03a8a07d 6 *
6606c3ae
AK
7 * This copyrighted material is made available to anyone wishing to use,
8 * modify, copy, or redistribute it subject to the terms and conditions
be684599 9 * of the GNU Lesser General Public License v.2.1.
03a8a07d 10 *
be684599 11 * You should have received a copy of the GNU Lesser General Public License
6606c3ae
AK
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
03a8a07d
AK
14 */
15
16#include "tools.h"
17
1a9ea74d
AK
18#define SIZE_BUF 128
19
241913fe 20struct lvresize_params {
8ef2b021 21 const char *vg_name;
241913fe
AK
22 const char *lv_name;
23
24 uint32_t stripes;
25 uint32_t stripe_size;
ffb0e538 26 uint32_t mirrors;
241913fe 27
72b2cb61 28 const struct segment_type *segtype;
241913fe 29
241913fe
AK
30 /* size */
31 uint32_t extents;
32 uint64_t size;
33 sign_t sign;
34fadac4 34 percent_t percent;
03a8a07d
AK
35
36 enum {
37 LV_ANY = 0,
38 LV_REDUCE = 1,
39 LV_EXTEND = 2
241913fe
AK
40 } resize;
41
1a9ea74d
AK
42 int resizefs;
43 int nofsck;
44
241913fe
AK
45 int argc;
46 char **argv;
47};
48
bc175d28
AK
49static int _validate_stripesize(struct cmd_context *cmd,
50 const struct volume_group *vg,
51 struct lvresize_params *lp)
406a9754
DW
52{
53 if (arg_sign_value(cmd, stripesize_ARG, 0) == SIGN_MINUS) {
54 log_error("Stripesize may not be negative.");
55 return 0;
56 }
57
204a12e5 58 if (arg_uint_value(cmd, stripesize_ARG, 0) > STRIPE_SIZE_LIMIT * 2) {
406a9754
DW
59 log_error("Stripe size cannot be larger than %s",
60 display_size(cmd, (uint64_t) STRIPE_SIZE_LIMIT));
61 return 0;
62 }
63
64 if (!(vg->fid->fmt->features & FMT_SEGMENTS))
65 log_warn("Varied stripesize not supported. Ignoring.");
204a12e5 66 else if (arg_uint_value(cmd, stripesize_ARG, 0) > vg->extent_size * 2) {
406a9754
DW
67 log_error("Reducing stripe size %s to maximum, "
68 "physical extent size %s",
69 display_size(cmd,
204a12e5 70 (uint64_t) arg_uint_value(cmd, stripesize_ARG, 0)),
406a9754
DW
71 display_size(cmd, (uint64_t) vg->extent_size));
72 lp->stripe_size = vg->extent_size;
73 } else
204a12e5 74 lp->stripe_size = arg_uint_value(cmd, stripesize_ARG, 0);
406a9754 75
406a9754
DW
76 if (lp->stripe_size & (lp->stripe_size - 1)) {
77 log_error("Stripe size must be power of 2");
78 return 0;
79 }
80
81 return 1;
82}
83
bc175d28
AK
84static int _request_confirmation(struct cmd_context *cmd,
85 const struct volume_group *vg,
86 const struct logical_volume *lv,
87 const struct lvresize_params *lp)
406a9754
DW
88{
89 struct lvinfo info;
90
91 memset(&info, 0, sizeof(info));
92
2d6fcbf6 93 if (!lv_info(cmd, lv, 0, &info, 1, 0) && driver_version(NULL, 0)) {
406a9754
DW
94 log_error("lv_info failed: aborting");
95 return 0;
96 }
97
bc175d28
AK
98 if (lp->resizefs) {
99 if (!info.exists) {
100 log_error("Logical volume %s must be activated "
101 "before resizing filesystem", lp->lv_name);
102 return 0;
103 }
104 return 1;
406a9754
DW
105 }
106
bc175d28
AK
107 if (!info.exists)
108 return 1;
406a9754 109
bc175d28
AK
110 log_warn("WARNING: Reducing active%s logical volume to %s",
111 info.open_count ? " and open" : "",
112 display_size(cmd, (uint64_t) lp->extents * vg->extent_size));
406a9754 113
bc175d28
AK
114 log_warn("THIS MAY DESTROY YOUR DATA (filesystem etc.)");
115
116 if (!arg_count(cmd, force_ARG)) {
117 if (yes_no_prompt("Do you really want to reduce %s? [y/n]: ",
118 lp->lv_name) == 'n') {
fec4de95 119 log_error("Logical volume %s NOT reduced", lp->lv_name);
bc175d28 120 return 0;
406a9754 121 }
bc175d28
AK
122 if (sigint_caught())
123 return 0;
406a9754
DW
124 }
125
126 return 1;
127}
128
c8669f6b 129enum fsadm_cmd_e { FSADM_CMD_CHECK, FSADM_CMD_RESIZE };
bc175d28
AK
130#define FSADM_CMD "fsadm"
131#define FSADM_CMD_MAX_ARGS 6
2955b913 132#define FSADM_CHECK_FAILS_FOR_MOUNTED 3 /* shell exist status code */
c8669f6b 133
bc175d28
AK
134/*
135 * FSADM_CMD --dry-run --verbose --force check lv_path
136 * FSADM_CMD --dry-run --verbose --force resize lv_path size
137 */
ed82bfd2 138static int _fsadm_cmd(struct cmd_context *cmd,
bc175d28
AK
139 const struct volume_group *vg,
140 const struct lvresize_params *lp,
2955b913
ZK
141 enum fsadm_cmd_e fcmd,
142 int *status)
406a9754
DW
143{
144 char lv_path[PATH_MAX];
145 char size_buf[SIZE_BUF];
bc175d28
AK
146 const char *argv[FSADM_CMD_MAX_ARGS + 2];
147 unsigned i = 0;
c8669f6b 148
bc175d28 149 argv[i++] = FSADM_CMD;
c8669f6b
ZK
150
151 if (test_mode())
152 argv[i++] = "--dry-run";
153
bc175d28 154 if (verbose_level() >= _LOG_NOTICE)
c8669f6b
ZK
155 argv[i++] = "--verbose";
156
157 if (arg_count(cmd, force_ARG))
158 argv[i++] = "--force";
159
160 argv[i++] = (fcmd == FSADM_CMD_RESIZE) ? "resize" : "check";
406a9754 161
bc175d28
AK
162 if (dm_snprintf(lv_path, PATH_MAX, "%s%s/%s", cmd->dev_dir, lp->vg_name,
163 lp->lv_name) < 0) {
164 log_error("Couldn't create LV path for %s", lp->lv_name);
406a9754
DW
165 return 0;
166 }
167
c8669f6b 168 argv[i++] = lv_path;
406a9754 169
c8669f6b
ZK
170 if (fcmd == FSADM_CMD_RESIZE) {
171 if (dm_snprintf(size_buf, SIZE_BUF, "%" PRIu64 "K",
172 (uint64_t) lp->extents * vg->extent_size / 2) < 0) {
173 log_error("Couldn't generate new LV size string");
174 return 0;
175 }
406a9754 176
c8669f6b
ZK
177 argv[i++] = size_buf;
178 }
406a9754 179
c8669f6b
ZK
180 argv[i] = NULL;
181
2955b913 182 return exec_cmd(cmd, argv, status);
406a9754
DW
183}
184
8a2fc586
AK
185static int _lvresize_params(struct cmd_context *cmd, int argc, char **argv,
186 struct lvresize_params *lp)
241913fe
AK
187{
188 const char *cmd_name;
189 char *st;
17dd04ca 190 unsigned dev_dir_found = 0;
a341cab7 191 int use_policy = arg_count(cmd, use_policies_ARG);
241913fe
AK
192
193 lp->sign = SIGN_NONE;
194 lp->resize = LV_ANY;
03a8a07d 195
60274aba 196 cmd_name = command_name(cmd);
03a8a07d 197 if (!strcmp(cmd_name, "lvreduce"))
241913fe 198 lp->resize = LV_REDUCE;
03a8a07d 199 if (!strcmp(cmd_name, "lvextend"))
241913fe 200 lp->resize = LV_EXTEND;
03a8a07d 201
a341cab7
PR
202 if (use_policy) {
203 /* do nothing; _lvresize will handle --use-policies itself */
204 lp->extents = 0;
dfef7f69 205 lp->sign = SIGN_PLUS;
a341cab7
PR
206 lp->percent = PERCENT_LV;
207 } else {
208 /*
209 * Allow omission of extents and size if the user has given us
210 * one or more PVs. Most likely, the intent was "resize this
211 * LV the best you can with these PVs"
212 */
213 if ((arg_count(cmd, extents_ARG) + arg_count(cmd, size_ARG) == 0) &&
214 (argc >= 2)) {
215 lp->extents = 100;
216 lp->percent = PERCENT_PVS;
217 lp->sign = SIGN_PLUS;
218 } else if ((arg_count(cmd, extents_ARG) +
219 arg_count(cmd, size_ARG) != 1)) {
220 log_error("Please specify either size or extents but not "
221 "both.");
222 return 0;
223 }
03a8a07d 224
a341cab7
PR
225 if (arg_count(cmd, extents_ARG)) {
226 lp->extents = arg_uint_value(cmd, extents_ARG, 0);
227 lp->sign = arg_sign_value(cmd, extents_ARG, SIGN_NONE);
228 lp->percent = arg_percent_value(cmd, extents_ARG, PERCENT_NONE);
229 }
03a8a07d 230
a341cab7
PR
231 /* Size returned in kilobyte units; held in sectors */
232 if (arg_count(cmd, size_ARG)) {
233 lp->size = arg_uint64_value(cmd, size_ARG, 0);
234 lp->sign = arg_sign_value(cmd, size_ARG, SIGN_NONE);
235 lp->percent = PERCENT_NONE;
236 }
03a8a07d
AK
237 }
238
241913fe 239 if (lp->resize == LV_EXTEND && lp->sign == SIGN_MINUS) {
03a8a07d 240 log_error("Negative argument not permitted - use lvreduce");
241913fe 241 return 0;
03a8a07d
AK
242 }
243
241913fe 244 if (lp->resize == LV_REDUCE && lp->sign == SIGN_PLUS) {
03a8a07d 245 log_error("Positive sign not permitted - use lvextend");
241913fe 246 return 0;
03a8a07d
AK
247 }
248
a8fb89ad
AK
249 lp->resizefs = arg_is_set(cmd, resizefs_ARG);
250 lp->nofsck = arg_is_set(cmd, nofsck_ARG);
1a9ea74d 251
03a8a07d
AK
252 if (!argc) {
253 log_error("Please provide the logical volume name");
241913fe 254 return 0;
03a8a07d
AK
255 }
256
241913fe 257 lp->lv_name = argv[0];
03a8a07d
AK
258 argv++;
259 argc--;
260
3a370b73
AK
261 if (!(lp->lv_name = skip_dev_dir(cmd, lp->lv_name, &dev_dir_found)) ||
262 !(lp->vg_name = extract_vgname(cmd, lp->lv_name))) {
03a8a07d 263 log_error("Please provide a volume group name");
241913fe 264 return 0;
03a8a07d 265 }
17dd04ca 266
d38bf361
AK
267 if (!validate_name(lp->vg_name)) {
268 log_error("Volume group name %s has invalid characters",
269 lp->vg_name);
6c3dc203 270 return 0;
d38bf361 271 }
03a8a07d 272
241913fe
AK
273 if ((st = strrchr(lp->lv_name, '/')))
274 lp->lv_name = st + 1;
03a8a07d 275
241913fe
AK
276 lp->argc = argc;
277 lp->argv = argv;
278
279 return 1;
280}
7d0e6e80 281
a341cab7
PR
282static int _adjust_policy_params(struct cmd_context *cmd,
283 struct logical_volume *lv, struct lvresize_params *lp)
284{
285 float percent;
286 percent_range_t range;
287 int policy_threshold, policy_amount;
288
289 policy_threshold =
290 find_config_tree_int(cmd, "activation/snapshot_autoextend_threshold",
291 DEFAULT_SNAPSHOT_AUTOEXTEND_THRESHOLD);
292 policy_amount =
293 find_config_tree_int(cmd, "activation/snapshot_autoextend_percent",
294 DEFAULT_SNAPSHOT_AUTOEXTEND_PERCENT);
295
296 if (policy_threshold >= 100)
297 return 1; /* nothing to do */
298
299 if (!lv_snapshot_percent(lv, &percent, &range))
300 return_0;
301
302 if (range != PERCENT_0_TO_100 || percent <= policy_threshold)
303 return 1; /* nothing to do */
304
305 lp->extents = policy_amount;
306 return 1;
307}
308
e5f7352b
AK
309static int _lvresize(struct cmd_context *cmd, struct volume_group *vg,
310 struct lvresize_params *lp)
241913fe 311{
241913fe 312 struct logical_volume *lv;
241913fe
AK
313 struct lvinfo info;
314 uint32_t stripesize_extents = 0;
315 uint32_t seg_stripes = 0, seg_stripesize = 0, seg_size = 0;
ffb0e538 316 uint32_t seg_mirrors = 0;
241913fe
AK
317 uint32_t extents_used = 0;
318 uint32_t size_rest;
dfef7f69 319 uint32_t pv_extent_count = 0;
a0a23eff 320 alloc_policy_t alloc;
0fb173aa 321 struct logical_volume *lock_lv;
241913fe 322 struct lv_list *lvl;
1485ce69 323 struct lv_segment *seg, *uninitialized_var(mirr_seg);
241913fe
AK
324 uint32_t seg_extents;
325 uint32_t sz, str;
2955b913 326 int status;
2c44337b 327 struct dm_list *pvh = NULL;
a341cab7 328 int use_policy = arg_count(cmd, use_policies_ARG);
241913fe 329
03a8a07d 330 /* does LV exist? */
241913fe 331 if (!(lvl = find_lv_in_vg(vg, lp->lv_name))) {
03a8a07d 332 log_error("Logical volume %s not found in volume group %s",
241913fe 333 lp->lv_name, lp->vg_name);
7f0dc9c4 334 return ECMD_FAILED;
03a8a07d
AK
335 }
336
25b73380
AK
337 if (arg_count(cmd, stripes_ARG)) {
338 if (vg->fid->fmt->features & FMT_SEGMENTS)
241913fe 339 lp->stripes = arg_uint_value(cmd, stripes_ARG, 1);
25b73380 340 else
e7ddf416 341 log_warn("Varied striping not supported. Ignoring.");
25b73380
AK
342 }
343
ffb0e538
AK
344 if (arg_count(cmd, mirrors_ARG)) {
345 if (vg->fid->fmt->features & FMT_SEGMENTS)
346 lp->mirrors = arg_uint_value(cmd, mirrors_ARG, 1) + 1;
347 else
e7ddf416 348 log_warn("Mirrors not supported. Ignoring.");
7424de5b
AK
349 if (arg_sign_value(cmd, mirrors_ARG, 0) == SIGN_MINUS) {
350 log_error("Mirrors argument may not be negative");
406a9754 351 return EINVALID_CMD_LINE;
7424de5b 352 }
ffb0e538
AK
353 }
354
bc175d28
AK
355 if (arg_count(cmd, stripesize_ARG) &&
356 !_validate_stripesize(cmd, vg, lp))
357 return EINVALID_CMD_LINE;
25b73380 358
f868d635 359 lv = lvl->lv;
03a8a07d 360
a341cab7
PR
361 if (use_policy) {
362 if (!lv_is_cow(lv)) {
363 log_error("Can't use policy-based resize for non-snapshot volumes.");
364 return ECMD_FAILED;
365 }
366 _adjust_policy_params(cmd, lv, lp);
367 }
368
fd817ff3
MS
369 if (!lv_is_visible(lv)) {
370 log_error("Can't resize internal logical volume %s", lv->name);
371 return ECMD_FAILED;
372 }
373
6e03b44c
AK
374 if (lv->status & LOCKED) {
375 log_error("Can't resize locked LV %s", lv->name);
7f0dc9c4 376 return ECMD_FAILED;
6e03b44c
AK
377 }
378
08b481bb
AK
379 if (lv->status & CONVERTING) {
380 log_error("Can't resize %s while lvconvert in progress", lv->name);
381 return ECMD_FAILED;
382 }
383
72b2cb61 384 alloc = arg_uint_value(cmd, alloc_ARG, lv->alloc);
7f0dc9c4 385
241913fe
AK
386 if (lp->size) {
387 if (lp->size % vg->extent_size) {
388 if (lp->sign == SIGN_MINUS)
389 lp->size -= lp->size % vg->extent_size;
03a8a07d 390 else
241913fe
AK
391 lp->size += vg->extent_size -
392 (lp->size % vg->extent_size);
03a8a07d
AK
393
394 log_print("Rounding up size to full physical extent %s",
72b2cb61 395 display_size(cmd, (uint64_t) lp->size));
03a8a07d
AK
396 }
397
241913fe 398 lp->extents = lp->size / vg->extent_size;
03a8a07d
AK
399 }
400
dfef7f69
DW
401 if (!(pvh = lp->argc ? create_pv_list(cmd->mem, vg, lp->argc,
402 lp->argv, 1) : &vg->pvs)) {
403 stack;
404 return ECMD_FAILED;
405 }
406
34fadac4
AK
407 switch(lp->percent) {
408 case PERCENT_VG:
409 lp->extents = lp->extents * vg->extent_count / 100;
410 break;
411 case PERCENT_FREE:
412 lp->extents = lp->extents * vg->free_count / 100;
413 break;
414 case PERCENT_LV:
415 lp->extents = lp->extents * lv->le_count / 100;
416 break;
dfef7f69 417 case PERCENT_PVS:
ba3851fd
MB
418 if (lp->argc) {
419 pv_extent_count = pv_list_extents_free(pvh);
420 lp->extents = lp->extents * pv_extent_count / 100;
421 } else
422 lp->extents = lp->extents * vg->extent_count / 100;
dfef7f69 423 break;
5bc2af26
MS
424 case PERCENT_ORIGIN:
425 if (!lv_is_cow(lv)) {
426 log_error("Specified LV does not have an origin LV.");
427 return EINVALID_CMD_LINE;
428 }
429 lp->extents = lp->extents * origin_from_cow(lv)->le_count / 100;
430 break;
34fadac4
AK
431 case PERCENT_NONE:
432 break;
433 }
434
241913fe
AK
435 if (lp->sign == SIGN_PLUS)
436 lp->extents += lv->le_count;
03a8a07d 437
241913fe
AK
438 if (lp->sign == SIGN_MINUS) {
439 if (lp->extents >= lv->le_count) {
03a8a07d 440 log_error("Unable to reduce %s below 1 extent",
241913fe 441 lp->lv_name);
7f0dc9c4 442 return EINVALID_CMD_LINE;
03a8a07d
AK
443 }
444
241913fe 445 lp->extents = lv->le_count - lp->extents;
03a8a07d
AK
446 }
447
241913fe 448 if (!lp->extents) {
03a8a07d 449 log_error("New size of 0 not permitted");
7f0dc9c4 450 return EINVALID_CMD_LINE;
03a8a07d
AK
451 }
452
241913fe 453 if (lp->extents == lv->le_count) {
a341cab7
PR
454 if (use_policy)
455 return ECMD_PROCESSED; /* Nothing to do. */
c8669f6b
ZK
456 if (!lp->resizefs) {
457 log_error("New size (%d extents) matches existing size "
458 "(%d extents)", lp->extents, lv->le_count);
459 return EINVALID_CMD_LINE;
460 }
461 lp->resize = LV_EXTEND; /* lets pretend zero size extension */
03a8a07d
AK
462 }
463
241913fe 464 seg_size = lp->extents - lv->le_count;
25b73380 465
1832f310 466 /* Use segment type of last segment */
2c44337b 467 dm_list_iterate_items(seg, &lv->segments) {
241913fe 468 lp->segtype = seg->segtype;
1832f310
AK
469 }
470
471 /* FIXME Support LVs with mixed segment types */
54d7741a
AK
472 if (lp->segtype != get_segtype_from_string(cmd, arg_str_value(cmd, type_ARG,
473 lp->segtype->name))) {
241913fe 474 log_error("VolumeType does not match (%s)", lp->segtype->name);
7f0dc9c4 475 return EINVALID_CMD_LINE;
1832f310
AK
476 }
477
1485ce69
AK
478 /* If extending, find mirrors of last segment */
479 if ((lp->extents > lv->le_count)) {
480 dm_list_iterate_back_items(mirr_seg, &lv->segments) {
481 if (seg_is_mirrored(mirr_seg))
482 seg_mirrors = lv_mirror_count(mirr_seg->lv);
483 else
484 seg_mirrors = 0;
485 break;
486 }
487 if (!arg_count(cmd, mirrors_ARG) && seg_mirrors) {
488 log_print("Extending %" PRIu32 " mirror images.",
489 seg_mirrors);
490 lp->mirrors = seg_mirrors;
491 }
492 if ((arg_count(cmd, mirrors_ARG) || seg_mirrors) &&
493 (lp->mirrors != seg_mirrors)) {
494 log_error("Cannot vary number of mirrors in LV yet.");
495 return EINVALID_CMD_LINE;
496 }
497 }
498
52dc2139 499 /* If extending, find stripes, stripesize & size of last segment */
241913fe
AK
500 if ((lp->extents > lv->le_count) &&
501 !(lp->stripes == 1 || (lp->stripes > 1 && lp->stripe_size))) {
1485ce69
AK
502 /* FIXME Don't assume mirror seg will always be AREA_LV */
503 dm_list_iterate_items(seg, seg_mirrors ? &seg_lv(mirr_seg, 0)->segments : &lv->segments) {
32469fb2 504 if (!seg_is_striped(seg))
1832f310 505 continue;
b8c919b4 506
579944d3 507 sz = seg->stripe_size;
b8c919b4 508 str = seg->area_count;
52dc2139 509
bc175d28 510 if ((seg_stripesize && seg_stripesize != sz &&
1485ce69 511 sz && !lp->stripe_size) ||
241913fe 512 (seg_stripes && seg_stripes != str && !lp->stripes)) {
52dc2139
AK
513 log_error("Please specify number of "
514 "stripes (-i) and stripesize (-I)");
7f0dc9c4 515 return EINVALID_CMD_LINE;
52dc2139
AK
516 }
517
518 seg_stripesize = sz;
519 seg_stripes = str;
520 }
521
241913fe
AK
522 if (!lp->stripes)
523 lp->stripes = seg_stripes;
52dc2139 524
241913fe 525 if (!lp->stripe_size && lp->stripes > 1) {
25b73380 526 if (seg_stripesize) {
12de747d 527 log_print("Using stripesize of last segment %s",
72b2cb61 528 display_size(cmd, (uint64_t) seg_stripesize));
241913fe 529 lp->stripe_size = seg_stripesize;
25b73380 530 } else {
7f0dc9c4 531 lp->stripe_size =
2293567c 532 find_config_tree_int(cmd,
8ef2b021 533 "metadata/stripesize",
8ef2b021 534 DEFAULT_STRIPESIZE) * 2;
12de747d 535 log_print("Using default stripesize %s",
72b2cb61 536 display_size(cmd, (uint64_t) lp->stripe_size));
25b73380
AK
537 }
538 }
52dc2139
AK
539 }
540
541 /* If reducing, find stripes, stripesize & size of last segment */
241913fe 542 if (lp->extents < lv->le_count) {
25b73380 543 extents_used = 0;
52dc2139 544
ffb0e538
AK
545 if (lp->stripes || lp->stripe_size || lp->mirrors)
546 log_error("Ignoring stripes, stripesize and mirrors "
547 "arguments when reducing");
52dc2139 548
2c44337b 549 dm_list_iterate_items(seg, &lv->segments) {
579944d3
AK
550 seg_extents = seg->len;
551
32469fb2 552 if (seg_is_striped(seg)) {
b8c919b4
AK
553 seg_stripesize = seg->stripe_size;
554 seg_stripes = seg->area_count;
555 }
52dc2139 556
ffb0e538 557 if (seg_is_mirrored(seg))
31e9db26 558 seg_mirrors = lv_mirror_count(seg->lv);
ffb0e538
AK
559 else
560 seg_mirrors = 0;
561
241913fe 562 if (lp->extents <= extents_used + seg_extents)
52dc2139
AK
563 break;
564
565 extents_used += seg_extents;
566 }
567
241913fe
AK
568 seg_size = lp->extents - extents_used;
569 lp->stripe_size = seg_stripesize;
570 lp->stripes = seg_stripes;
ffb0e538 571 lp->mirrors = seg_mirrors;
52dc2139
AK
572 }
573
241913fe 574 if (lp->stripes > 1 && !lp->stripe_size) {
25b73380 575 log_error("Stripesize for striped segment should not be 0!");
7f0dc9c4 576 return EINVALID_CMD_LINE;
d4e5f63e 577 }
5a52dca9 578
241913fe
AK
579 if ((lp->stripes > 1)) {
580 if (!(stripesize_extents = lp->stripe_size / vg->extent_size))
d4e5f63e
AK
581 stripesize_extents = 1;
582
241913fe 583 if ((size_rest = seg_size % (lp->stripes * stripesize_extents))) {
d4e5f63e
AK
584 log_print("Rounding size (%d extents) down to stripe "
585 "boundary size for segment (%d extents)",
241913fe
AK
586 lp->extents, lp->extents - size_rest);
587 lp->extents = lp->extents - size_rest;
d4e5f63e 588 }
12de747d
AK
589
590 if (lp->stripe_size < STRIPE_SIZE_MIN) {
591 log_error("Invalid stripe size %s",
72b2cb61 592 display_size(cmd, (uint64_t) lp->stripe_size));
406a9754 593 return EINVALID_CMD_LINE;
12de747d 594 }
da4e57f2 595 }
52dc2139 596
241913fe
AK
597 if (lp->extents < lv->le_count) {
598 if (lp->resize == LV_EXTEND) {
03a8a07d
AK
599 log_error("New size given (%d extents) not larger "
600 "than existing size (%d extents)",
241913fe 601 lp->extents, lv->le_count);
7f0dc9c4 602 return EINVALID_CMD_LINE;
c8669f6b
ZK
603 }
604 lp->resize = LV_REDUCE;
605 } else if (lp->extents > lv->le_count) {
241913fe 606 if (lp->resize == LV_REDUCE) {
03a8a07d 607 log_error("New size given (%d extents) not less than "
241913fe 608 "existing size (%d extents)", lp->extents,
03a8a07d 609 lv->le_count);
7f0dc9c4 610 return EINVALID_CMD_LINE;
c8669f6b
ZK
611 }
612 lp->resize = LV_EXTEND;
03a8a07d
AK
613 }
614
864de9ce
AK
615 if (lv_is_origin(lv)) {
616 if (lp->resize == LV_REDUCE) {
617 log_error("Snapshot origin volumes cannot be reduced "
618 "in size yet.");
619 return ECMD_FAILED;
620 }
621
622 memset(&info, 0, sizeof(info));
623
2d6fcbf6 624 if (lv_info(cmd, lv, 0, &info, 0, 0) && info.exists) {
864de9ce
AK
625 log_error("Snapshot origin volumes can be resized "
626 "only while inactive: try lvchange -an");
627 return ECMD_FAILED;
628 }
629 }
630
bc175d28
AK
631 if ((lp->resize == LV_REDUCE) && lp->argc)
632 log_warn("Ignoring PVs on command line when reducing");
03a8a07d 633
bc175d28
AK
634 /* Request confirmation before operations that are often mistakes. */
635 if ((lp->resizefs || (lp->resize == LV_REDUCE)) &&
636 !_request_confirmation(cmd, vg, lv, lp)) {
637 stack;
2b238642 638 return ECMD_FAILED;
bc175d28 639 }
03a8a07d 640
1a9ea74d 641 if (lp->resizefs) {
bc175d28 642 if (!lp->nofsck &&
2955b913
ZK
643 !_fsadm_cmd(cmd, vg, lp, FSADM_CMD_CHECK, &status)) {
644 if (status != FSADM_CHECK_FAILS_FOR_MOUNTED) {
645 stack;
646 return ECMD_FAILED;
647 }
648 /* some filesystems supports online resize */
c8669f6b
ZK
649 }
650
bc175d28 651 if ((lp->resize == LV_REDUCE) &&
2955b913 652 !_fsadm_cmd(cmd, vg, lp, FSADM_CMD_RESIZE, NULL)) {
c8669f6b
ZK
653 stack;
654 return ECMD_FAILED;
655 }
1a9ea74d 656 }
614a4508 657
1a9ea74d
AK
658 if (!archive(vg)) {
659 stack;
660 return ECMD_FAILED;
661 }
03a8a07d 662
1a9ea74d
AK
663 log_print("%sing logical volume %s to %s",
664 (lp->resize == LV_REDUCE) ? "Reduc" : "Extend",
665 lp->lv_name,
72b2cb61 666 display_size(cmd, (uint64_t) lp->extents * vg->extent_size));
1a9ea74d
AK
667
668 if (lp->resize == LV_REDUCE) {
32469fb2 669 if (!lv_reduce(lv, lv->le_count - lp->extents)) {
7f0dc9c4
AK
670 stack;
671 return ECMD_FAILED;
241913fe 672 }
bc175d28
AK
673 } else if ((lp->extents > lv->le_count) && /* Ensure we extend */
674 !lv_extend(lv, lp->segtype, lp->stripes,
ffb0e538 675 lp->stripe_size, lp->mirrors,
32469fb2
AK
676 lp->extents - lv->le_count,
677 NULL, 0u, 0u, pvh, alloc)) {
1a9ea74d
AK
678 stack;
679 return ECMD_FAILED;
03a8a07d
AK
680 }
681
03a8a07d 682 /* store vg on disk(s) */
25b73380 683 if (!vg_write(vg)) {
914c9723 684 stack;
7f0dc9c4 685 return ECMD_FAILED;
cc8b2cd7 686 }
03a8a07d 687
914c9723 688 /* If snapshot, must suspend all associated devices */
2cd0aa72
AK
689 if (lv_is_cow(lv))
690 lock_lv = origin_from_cow(lv);
914c9723 691 else
0fb173aa 692 lock_lv = lv;
914c9723 693
0fb173aa 694 if (!suspend_lv(cmd, lock_lv)) {
241913fe 695 log_error("Failed to suspend %s", lp->lv_name);
914c9723 696 vg_revert(vg);
8f3fd69f 697 backup(vg);
7f0dc9c4 698 return ECMD_FAILED;
914c9723
AK
699 }
700
701 if (!vg_commit(vg)) {
702 stack;
df13cf08
MS
703 if (!resume_lv(cmd, lock_lv))
704 stack;
8f3fd69f 705 backup(vg);
7f0dc9c4 706 return ECMD_FAILED;
914c9723
AK
707 }
708
0fb173aa 709 if (!resume_lv(cmd, lock_lv)) {
241913fe 710 log_error("Problem reactivating %s", lp->lv_name);
8f3fd69f 711 backup(vg);
7f0dc9c4 712 return ECMD_FAILED;
cc8b2cd7 713 }
03a8a07d 714
8f3fd69f
MB
715 backup(vg);
716
241913fe 717 log_print("Logical volume %s successfully resized", lp->lv_name);
03a8a07d 718
bc175d28 719 if (lp->resizefs && (lp->resize == LV_EXTEND) &&
2955b913 720 !_fsadm_cmd(cmd, vg, lp, FSADM_CMD_RESIZE, NULL)) {
c8669f6b
ZK
721 stack;
722 return ECMD_FAILED;
1a9ea74d
AK
723 }
724
cfb7bfc7 725 return ECMD_PROCESSED;
03a8a07d 726}
241913fe
AK
727
728int lvresize(struct cmd_context *cmd, int argc, char **argv)
729{
730 struct lvresize_params lp;
e5f7352b 731 struct volume_group *vg;
241913fe
AK
732 int r;
733
734 memset(&lp, 0, sizeof(lp));
735
8a2fc586 736 if (!_lvresize_params(cmd, argc, argv, &lp))
241913fe
AK
737 return EINVALID_CMD_LINE;
738
739 log_verbose("Finding volume group %s", lp.vg_name);
b8b3508c
DW
740 vg = vg_read_for_update(cmd, lp.vg_name, NULL, 0);
741 if (vg_read_error(vg)) {
4c611a22 742 vg_release(vg);
d0bf2f3f 743 stack;
241913fe 744 return ECMD_FAILED;
d0bf2f3f 745 }
241913fe 746
e5f7352b 747 if (!(r = _lvresize(cmd, vg, &lp)))
241913fe
AK
748 stack;
749
25a2e7b8 750 unlock_and_release_vg(cmd, vg, lp.vg_name);
241913fe
AK
751
752 return r;
753}
This page took 0.177214 seconds and 5 git commands to generate.