]> sourceware.org Git - lvm2.git/blame - tools/lvresize.c
Remove lv_update_write_access: use lv_reactivate directly now instead.
[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
60274aba 23int lvresize(struct cmd_context *cmd, int argc, char **argv)
03a8a07d
AK
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
60274aba 48 cmd_name = command_name(cmd);
03a8a07d
AK
49 if (!strcmp(cmd_name, "lvreduce"))
50 resize = LV_REDUCE;
51 if (!strcmp(cmd_name, "lvextend"))
52 resize = LV_EXTEND;
53
6fda126d 54 if (arg_count(cmd, extents_ARG) + arg_count(cmd, size_ARG) != 1) {
03a8a07d
AK
55 log_error("Please specify either size or extents (not both)");
56 return EINVALID_CMD_LINE;
57 }
58
6fda126d
AK
59 if (arg_count(cmd, extents_ARG)) {
60 extents = arg_int_value(cmd, extents_ARG, 0);
61 sign = arg_sign_value(cmd, extents_ARG, SIGN_NONE);
03a8a07d
AK
62 }
63
6fda126d
AK
64 if (arg_count(cmd, size_ARG)) {
65 size = arg_int_value(cmd, size_ARG, 0);
66 sign = arg_sign_value(cmd, size_ARG, SIGN_NONE);
03a8a07d
AK
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
6fda126d 79 if (arg_count(cmd, stripes_ARG)) {
265d372f 80 log_print("Varied striping not yet supported. Ignoring.");
60274aba 81 /* FUTURE stripes = arg_int_value(cmd,stripes_ARG, 1); */
da4e57f2
AK
82 }
83
6fda126d 84 if (arg_count(cmd, stripesize_ARG)) {
265d372f 85 log_print("Varied stripesize not yet supported. Ignoring.");
60274aba 86 /* FUTURE stripesize = 2 * arg_int_value(cmd,stripesize_ARG, 0); */
265d372f 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
60274aba 98 if (!(vg_name = extract_vgname(cmd->fid, lv_name))) {
03a8a07d
AK
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
60274aba 113 if (!(vg = cmd->fid->ops->vg_read(cmd->fid, vg_name))) {
03a8a07d 114 log_error("Volume group %s doesn't exist", vg_name);
7d0e6e80 115 goto error;
03a8a07d
AK
116 }
117
6fda126d
AK
118 if (vg->status & EXPORTED_VG) {
119 log_error("Volume group %s is exported", vg->name);
120 goto error;
121 }
f53c6aa6 122
6fda126d
AK
123 if (!(vg->status & LVM_WRITE)) {
124 log_error("Volume group %s is read-only", vg_name);
125 goto error;
126 }
f53c6aa6 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
6fda126d 189 seg = list_item(segh, struct stripe_segment);
579944d3
AK
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 281 dummy =
a45f546f 282 display_size((uint64_t)
f48d3bcb 283 extents * (vg->extent_size / 2),
03a8a07d
AK
284 SIZE_SHORT);
285 log_print("WARNING: Reducing active%s logical volume "
286 "to %s", lv_open_count(lv) ? " and open" : "",
287 dummy);
288
289 log_print("THIS MAY DESTROY YOUR DATA "
290 "(filesystem etc.)");
291 dbg_free(dummy);
292 }
293
6fda126d 294 if (!arg_count(cmd, force_ARG)) {
03a8a07d
AK
295 if (yes_no_prompt("Do you really want to reduce %s?"
296 " [y/n]: ", lv_name) == 'n') {
297 log_print("Logical volume %s NOT reduced",
298 lv_name);
7d0e6e80 299 goto error;
03a8a07d
AK
300 }
301 }
302
614a4508 303 if (!archive(vg))
7d0e6e80 304 goto error;
614a4508 305
60274aba 306 if (!lv_reduce(cmd->fid, lv, lv->le_count - extents))
7d0e6e80 307 goto error;
03a8a07d
AK
308 }
309
cc282870 310 if ((resize == LV_EXTEND && argc) &&
6fda126d 311 !(pvh = create_pv_list(cmd->mem, vg, argc - opt, argv + opt))) {
cc282870 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 }
a45f546f 324 dummy = display_size((uint64_t)
f48d3bcb
HM
325 extents * (vg->extent_size / 2),
326 SIZE_SHORT);
03a8a07d
AK
327 log_print("Extending logical volume %s to %s", lv_name, dummy);
328 dbg_free(dummy);
329
60274aba 330 if (!lv_extend(cmd->fid, lv, stripes, stripesize,
168b7bf9 331 extents - lv->le_count, pvh))
7d0e6e80 332 goto error;
03a8a07d
AK
333 }
334
2fb0db77
AK
335 active = lv_active(lv);
336
03a8a07d
AK
337/********* FIXME Suspend lv ***********/
338
339 /* store vg on disk(s) */
60274aba 340 if (!cmd->fid->ops->vg_write(cmd->fid, vg))
7d0e6e80 341 goto error;
03a8a07d 342
6fda126d 343 backup(vg);
cc219483 344
2fb0db77 345 if (active && !lv_reactivate(lv))
7d0e6e80 346 goto error;
03a8a07d
AK
347
348/********* FIXME Resume *********/
349
7d0e6e80
AK
350 lock_vol(vg_name, LCK_VG | LCK_NONE);
351
03a8a07d
AK
352 log_print("Logical volume %s successfully resized", lv_name);
353
354 return 0;
7d0e6e80
AK
355
356 error:
357 lock_vol(vg_name, LCK_VG | LCK_NONE);
358 return ECMD_FAILED;
359
360 error_cmdline:
361 lock_vol(vg_name, LCK_VG | LCK_NONE);
362 return EINVALID_CMD_LINE;
03a8a07d 363}
This page took 0.069297 seconds and 5 git commands to generate.