]> sourceware.org Git - lvm2.git/blame - tools/lvresize.c
Now that most of the usage of 'stack' only occurs when there's an error,
[lvm2.git] / tools / lvresize.c
CommitLineData
03a8a07d
AK
1/*
2 * Copyright (C) 2001 Sistina Software
3 *
4 * LVM is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2, or (at your option)
7 * any later version.
8 *
9 * LVM is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with LVM; see the file COPYING. If not, write to
16 * the Free Software Foundation, 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
18 *
19 */
20
21#include "tools.h"
22
23int lvresize(int argc, char **argv)
24{
25 struct volume_group *vg;
26 struct logical_volume *lv;
27 uint32_t extents = 0;
28 uint32_t size = 0;
52dc2139
AK
29 uint32_t stripes = 0, stripesize = 0;
30 uint32_t seg_stripes = 0, seg_stripesize = 0, seg_size = 0;
31 uint32_t size_rest;
03a8a07d
AK
32 sign_t sign = SIGN_NONE;
33 char *lv_name, *vg_name;
34 char *st;
35 char *dummy;
36 const char *cmd_name;
e586401e
JT
37 struct list *pvh, *segh;
38 struct lv_list *lvl;
03a8a07d 39 int opt = 0;
2fb0db77 40 int active;
03a8a07d
AK
41
42 enum {
43 LV_ANY = 0,
44 LV_REDUCE = 1,
45 LV_EXTEND = 2
46 } resize = LV_ANY;
47
48 cmd_name = command_name();
49 if (!strcmp(cmd_name, "lvreduce"))
50 resize = LV_REDUCE;
51 if (!strcmp(cmd_name, "lvextend"))
52 resize = LV_EXTEND;
53
54 if (arg_count(extents_ARG) + arg_count(size_ARG) != 1) {
55 log_error("Please specify either size or extents (not both)");
56 return EINVALID_CMD_LINE;
57 }
58
59 if (arg_count(extents_ARG)) {
60 extents = arg_int_value(extents_ARG, 0);
61 sign = arg_sign_value(extents_ARG, SIGN_NONE);
62 }
63
64 if (arg_count(size_ARG)) {
65 size = arg_int_value(size_ARG, 0);
66 sign = arg_sign_value(size_ARG, SIGN_NONE);
67 }
68
69 if (resize == LV_EXTEND && sign == SIGN_MINUS) {
70 log_error("Negative argument not permitted - use lvreduce");
71 return EINVALID_CMD_LINE;
72 }
73
74 if (resize == LV_REDUCE && sign == SIGN_PLUS) {
75 log_error("Positive sign not permitted - use lvextend");
76 return EINVALID_CMD_LINE;
77 }
78
52dc2139 79 if (arg_count(stripes_ARG)) {
265d372f
AK
80 log_print("Varied striping not yet supported. Ignoring.");
81 /* FUTURE stripes = arg_int_value(stripes_ARG, 1); */
da4e57f2
AK
82 }
83
265d372f
AK
84 if (arg_count(stripesize_ARG)) {
85 log_print("Varied stripesize not yet supported. Ignoring.");
86 /* FUTURE stripesize = 2 * arg_int_value(stripesize_ARG, 0); */
87 }
52dc2139 88
03a8a07d
AK
89 if (!argc) {
90 log_error("Please provide the logical volume name");
91 return EINVALID_CMD_LINE;
92 }
93
94 lv_name = argv[0];
95 argv++;
96 argc--;
97
98 if (!(vg_name = extract_vgname(fid, lv_name))) {
99 log_error("Please provide a volume group name");
100 return EINVALID_CMD_LINE;
101 }
102
103 if ((st = strrchr(lv_name, '/')))
104 lv_name = st + 1;
105
106 /* does VG exist? */
107 log_verbose("Finding volume group %s", vg_name);
7d0e6e80
AK
108 if (!lock_vol(vg_name, LCK_VG | LCK_WRITE)) {
109 log_error("Can't get lock for %s", vg_name);
110 return ECMD_FAILED;
111 }
112
03a8a07d
AK
113 if (!(vg = fid->ops->vg_read(fid, vg_name))) {
114 log_error("Volume group %s doesn't exist", vg_name);
7d0e6e80 115 goto error;
03a8a07d
AK
116 }
117
f53c6aa6
AK
118 if (vg->status & EXPORTED_VG) {
119 log_error("Volume group %s is exported", vg->name);
7d0e6e80 120 goto error;
f53c6aa6
AK
121 }
122
123 if (!(vg->status & LVM_WRITE)) {
124 log_error("Volume group %s is read-only", vg_name);
7d0e6e80 125 goto error;
f53c6aa6
AK
126 }
127
03a8a07d 128 /* does LV exist? */
e586401e 129 if (!(lvl = find_lv_in_vg(vg, lv_name))) {
03a8a07d
AK
130 log_error("Logical volume %s not found in volume group %s",
131 lv_name, vg_name);
7d0e6e80 132 goto error;
03a8a07d
AK
133 }
134
f868d635 135 lv = lvl->lv;
03a8a07d 136
03a8a07d
AK
137 if (size) {
138 /* No of 512-byte sectors */
139 extents = size * 2;
140
141 if (extents % vg->extent_size) {
142 char *s1;
143
144 if (sign == SIGN_MINUS)
145 extents -= extents % vg->extent_size;
146 else
147 extents += vg->extent_size -
148 (extents % vg->extent_size);
149
150 log_print("Rounding up size to full physical extent %s",
151 (s1 = display_size(extents / 2, SIZE_SHORT)));
152 dbg_free(s1);
153 }
154
155 extents /= vg->extent_size;
156 }
157
158 if (sign == SIGN_PLUS)
159 extents += lv->le_count;
160
161 if (sign == SIGN_MINUS) {
162 if (extents >= lv->le_count) {
163 log_error("Unable to reduce %s below 1 extent",
164 lv_name);
7d0e6e80 165 goto error_cmdline;
03a8a07d
AK
166 }
167
168 extents = lv->le_count - extents;
169 }
170
03a8a07d
AK
171 if (!extents) {
172 log_error("New size of 0 not permitted");
7d0e6e80 173 goto error_cmdline;
03a8a07d
AK
174 }
175
176 if (extents == lv->le_count) {
177 log_error("New size (%d extents) matches existing size "
178 "(%d extents)", extents, lv->le_count);
7d0e6e80 179 goto error_cmdline;
03a8a07d
AK
180 }
181
52dc2139 182 /* If extending, find stripes, stripesize & size of last segment */
cc282870 183 if (extents > lv->le_count &&
7a61472a 184 !(stripes == 1 || (stripes > 1 && stripesize))) {
579944d3
AK
185 list_iterate(segh, &lv->segments) {
186 struct stripe_segment *seg;
187 uint32_t sz, str;
188
189 seg = list_item(segh, struct stripe_segment);
190 sz = seg->stripe_size;
191 str = seg->stripes;
52dc2139 192
da4e57f2 193 if ((seg_stripesize && seg_stripesize != sz
52dc2139 194 && !stripesize) ||
da4e57f2 195 (seg_stripes && seg_stripes != str && !stripes)) {
52dc2139
AK
196 log_error("Please specify number of "
197 "stripes (-i) and stripesize (-I)");
7d0e6e80 198 goto error_cmdline;
52dc2139
AK
199 }
200
201 seg_stripesize = sz;
202 seg_stripes = str;
203 }
204
52dc2139
AK
205 if (!stripes)
206 stripes = seg_stripes;
207
93d6fa7d
AK
208 if (!stripesize && stripes > 1)
209 stripesize = seg_stripesize;
210
52dc2139
AK
211 seg_size = extents - lv->le_count;
212 }
213
214 /* If reducing, find stripes, stripesize & size of last segment */
215 if (extents < lv->le_count) {
216 uint32_t extents_used = 0;
217
218 if (stripes || stripesize)
219 log_error("Ignoring stripes and stripesize arguments "
220 "when reducing");
52dc2139 221
579944d3
AK
222 list_iterate(segh, &lv->segments) {
223 struct stripe_segment *seg;
224 uint32_t seg_extents;
225
226 seg = list_item(segh, struct stripe_segment);
227 seg_extents = seg->len;
228
229 seg_stripesize = seg->stripe_size;
230 seg_stripes = seg->stripes;
52dc2139
AK
231
232 if (extents <= extents_used + seg_extents)
233 break;
234
235 extents_used += seg_extents;
236 }
237
238 seg_size = extents - extents_used;
239 stripesize = seg_stripesize;
240 stripes = seg_stripes;
241 }
242
3c762e6d 243 if ((size_rest = seg_size % stripes)) {
da4e57f2
AK
244 log_print("Rounding size (%d extents) down to stripe boundary "
245 "size of last segment (%d extents)", extents,
246 extents - size_rest);
247 extents = extents - size_rest;
248 }
52dc2139
AK
249
250 if (extents == lv->le_count) {
251 log_error("New size (%d extents) matches existing size "
252 "(%d extents)", extents, lv->le_count);
7d0e6e80 253 goto error_cmdline;
52dc2139
AK
254 }
255
03a8a07d
AK
256 if (extents < lv->le_count) {
257 if (resize == LV_EXTEND) {
258 log_error("New size given (%d extents) not larger "
259 "than existing size (%d extents)",
260 extents, lv->le_count);
7d0e6e80 261 goto error_cmdline;
03a8a07d
AK
262 } else
263 resize = LV_REDUCE;
264 }
265
266 if (extents > lv->le_count) {
267 if (resize == LV_REDUCE) {
268 log_error("New size given (%d extents) not less than "
269 "existing size (%d extents)", extents,
270 lv->le_count);
7d0e6e80 271 goto error_cmdline;
03a8a07d
AK
272 } else
273 resize = LV_EXTEND;
274 }
275
276 if (resize == LV_REDUCE) {
277 if (argc)
278 log_print("Ignoring PVs on command line when reducing");
279
4af6dc96 280 if (lv_active(lv) > 0) {
03a8a07d
AK
281 dummy =
282 display_size(extents * vg->extent_size / 2,
283 SIZE_SHORT);
284 log_print("WARNING: Reducing active%s logical volume "
285 "to %s", lv_open_count(lv) ? " and open" : "",
286 dummy);
287
288 log_print("THIS MAY DESTROY YOUR DATA "
289 "(filesystem etc.)");
290 dbg_free(dummy);
291 }
292
293 if (!arg_count(force_ARG)) {
294 if (yes_no_prompt("Do you really want to reduce %s?"
295 " [y/n]: ", lv_name) == 'n') {
296 log_print("Logical volume %s NOT reduced",
297 lv_name);
7d0e6e80 298 goto error;
03a8a07d
AK
299 }
300 }
301
614a4508 302 if (!archive(vg))
7d0e6e80 303 goto error;
614a4508 304
168b7bf9 305 if (!lv_reduce(fid, lv, lv->le_count - extents))
7d0e6e80 306 goto error;
03a8a07d
AK
307 }
308
cc282870
JT
309 if ((resize == LV_EXTEND && argc) &&
310 !(pvh = create_pv_list(fid->cmd->mem, vg,
311 argc - opt, argv + opt))) {
312 stack;
7d0e6e80 313 goto error;
03a8a07d
AK
314 }
315
316 if (resize == LV_EXTEND) {
614a4508 317 if (!archive(vg))
7d0e6e80 318 goto error;
614a4508 319
03a8a07d
AK
320 if (!argc) {
321 /* Use full list from VG */
322 pvh = &vg->pvs;
323 }
324 dummy = display_size(extents * vg->extent_size / 2, SIZE_SHORT);
325 log_print("Extending logical volume %s to %s", lv_name, dummy);
326 dbg_free(dummy);
327
168b7bf9
JT
328 if (!lv_extend(fid, lv, stripes, stripesize,
329 extents - lv->le_count, pvh))
7d0e6e80 330 goto error;
03a8a07d
AK
331 }
332
2fb0db77
AK
333
334 active = lv_active(lv);
335
03a8a07d
AK
336/********* FIXME Suspend lv ***********/
337
338 /* store vg on disk(s) */
339 if (!fid->ops->vg_write(fid, vg))
7d0e6e80 340 goto error;
03a8a07d 341
197c3f2a 342 backup(vg);
cc219483 343
2fb0db77 344 if (active && !lv_reactivate(lv))
7d0e6e80 345 goto error;
03a8a07d
AK
346
347/********* FIXME Resume *********/
348
7d0e6e80
AK
349 lock_vol(vg_name, LCK_VG | LCK_NONE);
350
03a8a07d
AK
351 log_print("Logical volume %s successfully resized", lv_name);
352
353 return 0;
7d0e6e80
AK
354
355 error:
356 lock_vol(vg_name, LCK_VG | LCK_NONE);
357 return ECMD_FAILED;
358
359 error_cmdline:
360 lock_vol(vg_name, LCK_VG | LCK_NONE);
361 return EINVALID_CMD_LINE;
03a8a07d 362}
This page took 0.060223 seconds and 5 git commands to generate.