]> sourceware.org Git - lvm2.git/blame - tools/lvresize.c
devices: fix dev_dm_uuid
[lvm2.git] / tools / lvresize.c
CommitLineData
03a8a07d 1/*
1832f310 2 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
5a32d2c1 3 * Copyright (C) 2004-2016 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 12 * along with this program; if not, write to the Free Software Foundation,
fcbef05a 13 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
03a8a07d
AK
14 */
15
16#include "tools.h"
17
18722dfd 18static int _lvresize_params(struct cmd_context *cmd, struct lvresize_params *lp)
241913fe 19{
f45b6894 20 const char *type_str = arg_str_value(cmd, type_ARG, NULL);
7a9efc5f 21 int only_linear = 0;
264827cb 22 int set_fsopt = 0;
18722dfd 23 int set_extents_and_size = 0;
f45b6894 24
18722dfd 25 memset(lp, 0, sizeof(struct lvresize_params));
7a9efc5f 26
18722dfd
DT
27 switch (cmd->command->command_enum) {
28 case lvextend_policy_CMD:
29 lp->resize = LV_EXTEND;
30 lp->size = 0;
31 lp->extents = 0;
32 lp->percent = PERCENT_LV;
33 lp->sign = SIGN_PLUS;
34 lp->poolmetadata_size = 0;
35 lp->use_policies = 1;
36 break;
37
38 case lvextend_pool_metadata_CMD:
39 case lvresize_pool_metadata_CMD:
40 lp->resize = LV_EXTEND;
41 lp->size = 0;
42 lp->extents = 0;
43 lp->percent = PERCENT_NONE;
44 lp->sign = SIGN_NONE;
45 lp->poolmetadata_size = arg_uint64_value(cmd, poolmetadatasize_ARG, 0);
46 lp->poolmetadata_sign = arg_sign_value(cmd, poolmetadatasize_ARG, SIGN_NONE);
47 break;
48
49 case lvextend_pv_CMD:
50 case lvresize_pv_CMD:
51 lp->resize = LV_EXTEND;
52 lp->size = 0;
53 lp->extents = 0;
54 lp->percent_value = 100;
55 lp->percent = PERCENT_PVS;
56 lp->sign = SIGN_PLUS;
57 lp->poolmetadata_size = 0;
264827cb 58 set_fsopt = 1;
18722dfd
DT
59 break;
60
61 case lvextend_size_CMD:
62 lp->resize = LV_EXTEND;
18722dfd
DT
63 if ((lp->poolmetadata_size = arg_uint64_value(cmd, poolmetadatasize_ARG, 0)))
64 lp->poolmetadata_sign = arg_sign_value(cmd, poolmetadatasize_ARG, SIGN_NONE);
65 set_extents_and_size = 1;
264827cb 66 set_fsopt = 1;
18722dfd 67 break;
241913fe 68
18722dfd 69 case lvreduce_size_CMD:
241913fe 70 lp->resize = LV_REDUCE;
18722dfd 71 lp->poolmetadata_size = 0;
18722dfd 72 set_extents_and_size = 1;
264827cb 73 set_fsopt = 1;
18722dfd
DT
74 break;
75
76 case lvresize_size_CMD:
0a525832 77 lp->resize = LV_ANY;
18722dfd 78 lp->poolmetadata_size = arg_uint64_value(cmd, poolmetadatasize_ARG, 0);
18722dfd
DT
79 if ((lp->poolmetadata_size = arg_uint64_value(cmd, poolmetadatasize_ARG, 0)))
80 lp->poolmetadata_sign = arg_sign_value(cmd, poolmetadatasize_ARG, SIGN_NONE);
81 set_extents_and_size = 1;
264827cb 82 set_fsopt = 1;
18722dfd 83 break;
0a525832 84
18722dfd
DT
85 default:
86 log_error(INTERNAL_ERROR "unknown lvresize type");
87 return 0;
88 };
89
264827cb
DT
90 if (set_fsopt) {
91 const char *str;
92
93 if (arg_is_set(cmd, resizefs_ARG) && arg_is_set(cmd, fs_ARG)) {
94 log_error("Options --fs and --resizefs cannot be used together.");
95 log_error("--resizefs is equivalent to --fs resize.");
96 return 0;
97 }
98
1fb5107e 99#ifdef HAVE_BLKID_SUBLKS_FSINFO
1924fed3
DT
100 /*
101 * When the libblkid fs info feature is available, use the
102 * the newer fs resizing capabability unless the older
103 * fsadm-based resizing is requested with --fs resize_fsadm.
104 */
264827cb
DT
105 if ((str = arg_str_value(cmd, fs_ARG, NULL))) {
106 if (!strcmp(str, "checksize") ||
107 !strcmp(str, "resize") ||
108 !strcmp(str, "resize_fsadm")) {
109 strncpy(lp->fsopt, str, sizeof(lp->fsopt)-1);
110 } else if (!strcmp(str, "ignore")) {
111 lp->fsopt[0] = '\0';
112 } else {
113 log_error("Unknown --fs value.");
114 return 0;
115 }
116 lp->user_set_fs = 1;
117 } else if (arg_is_set(cmd, resizefs_ARG)) {
118 /* --resizefs alone equates to --fs resize */
119 strncpy(lp->fsopt, "resize", sizeof(lp->fsopt)-1);
120 lp->user_set_fs = 1;
121 } else {
122 /*
123 * Use checksize when no fs option is specified.
124 * checksize with extend does nothing: the LV
125 * is extended and any fs is ignored.
126 * checksize with reduce checks for an fs that
127 * needs reducing: the LV is reduced only if the
128 * fs does not need to be reduced (or no fs.)
129 */
130 strncpy(lp->fsopt, "checksize", sizeof(lp->fsopt)-1);
131 }
1924fed3
DT
132#else
133 /*
134 * When the libblkid fs info feature is not available we can only
135 * use fsadm, so --resizefs, --fs resize, --fs resize_fsadm
136 * all translate to resize_fsadm.
137 */
138 if ((str = arg_str_value(cmd, fs_ARG, NULL))) {
139 if (!strcmp(str, "resize")) {
140 log_warn("Using fsadm for file system handling (resize_fsadm).");
141 strcpy(lp->fsopt, "resize_fsadm");
142 } else if (!strcmp(str, "resize_fsadm")) {
143 strcpy(lp->fsopt, "resize_fsadm");
144 } else if (!strcmp(str, "ignore")) {
145 log_warn("Ignoring unsupported --fs ignore with fsadm resizing.");
146 } else {
147 log_error("Unknown --fs value.");
148 return 0;
149 }
150 } else if (arg_is_set(cmd, resizefs_ARG)) {
151 /* --resizefs alone equates to --fs resize_fsadm */
152 strcpy(lp->fsopt, "resize_fsadm");
153 }
154#endif
264827cb
DT
155 if (lp->fsopt[0])
156 lp->nofsck = arg_is_set(cmd, nofsck_ARG);
157
158 if (!strcmp(lp->fsopt, "resize_fsadm") && arg_is_set(cmd, fsmode_ARG)) {
159 log_error("The --fsmode option does not apply to resize_fsadm.");
160 return 0;
161 }
162
163 if ((str = arg_str_value(cmd, fsmode_ARG, NULL))) {
164 if (!strcmp(str, "nochange") ||
165 !strcmp(str, "offline") ||
166 !strcmp(str, "manage")) {
167 strncpy(lp->fsmode, str, sizeof(lp->fsmode)-1);
168 lp->user_set_fsmode = 1;
169 } else {
170 log_error("Unknown --fsmode value.");
171 return 0;
172 }
173 } else {
174 /* Use manage when no fsmode option is specified. */
175 strncpy(lp->fsmode, "manage", sizeof(lp->fsmode)-1);
176 }
177 }
178
18722dfd 179 if (set_extents_and_size) {
f45b6894 180 if ((lp->extents = arg_uint_value(cmd, extents_ARG, 0))) {
c4b1bfa5 181 lp->sign = arg_sign_value(cmd, extents_ARG, SIGN_NONE);
f45b6894
ZK
182 lp->percent = arg_percent_value(cmd, extents_ARG, PERCENT_NONE);
183 }
f45b6894 184 if ((lp->size = arg_uint64_value(cmd, size_ARG, 0))) {
c4b1bfa5 185 lp->sign = arg_sign_value(cmd, size_ARG, SIGN_NONE);
f45b6894 186 lp->percent = PERCENT_NONE;
a341cab7 187 }
f45b6894
ZK
188 if (lp->size && lp->extents) {
189 log_error("Please specify either size or extents but not both.");
190 return 0;
a341cab7 191 }
03a8a07d
AK
192 }
193
18722dfd
DT
194 lp->alloc = (alloc_policy_t) arg_uint_value(cmd, alloc_ARG, 0);
195 lp->yes = arg_is_set(cmd, yes_ARG);
196 lp->force = arg_is_set(cmd, force_ARG),
197 lp->nosync = arg_is_set(cmd, nosync_ARG);
03a8a07d 198
18722dfd
DT
199 if (type_str) {
200 if (!strcmp(type_str, "linear")) {
201 type_str = "striped";
202 only_linear = 1; /* User requested linear only target */
203 }
17dd04ca 204
18722dfd
DT
205 if (!(lp->segtype = get_segtype_from_string(cmd, type_str)))
206 return_0;
d38bf361 207 }
03a8a07d 208
264827cb
DT
209 if ((lp->resize == LV_REDUCE) &&
210 (type_str ||
211 arg_is_set(cmd, mirrors_ARG) ||
212 arg_is_set(cmd, stripes_ARG) ||
213 arg_is_set(cmd, stripesize_ARG))) {
214 /* should be obvious since reduce doesn't alloc space. */
215 log_print_unless_silent("Ignoring type, stripes, stripesize and mirrors "
216 "arguments when reducing.");
217 goto out;
218 }
219
87c89ac2
ZK
220 if (arg_is_set(cmd, mirrors_ARG)) {
221 if (arg_sign_value(cmd, mirrors_ARG, SIGN_NONE) != SIGN_NONE) {
222 log_error("Mirrors argument may not be signed.");
223 return 0;
224 }
225 if ((lp->mirrors = arg_uint_value(cmd, mirrors_ARG, 0)))
226 lp->mirrors++;
9d550cfc
TA
227 }
228
f45b6894
ZK
229 if ((lp->stripes = arg_uint_value(cmd, stripes_ARG, 0)) &&
230 (arg_sign_value(cmd, stripes_ARG, SIGN_NONE) == SIGN_MINUS)) {
231 log_error("Stripes argument may not be negative.");
232 return 0;
9d550cfc
TA
233 }
234
7a9efc5f
ZK
235 if (only_linear && lp->stripes > 1) {
236 log_error("Cannot use stripes with linear type.");
237 return 0;
238 }
239
f45b6894
ZK
240 if ((lp->stripe_size = arg_uint64_value(cmd, stripesize_ARG, 0)) &&
241 (arg_sign_value(cmd, stripesize_ARG, SIGN_NONE) == SIGN_MINUS)) {
242 log_error("Stripesize may not be negative.");
243 return 0;
9d550cfc 244 }
264827cb 245out:
241913fe
AK
246 return 1;
247}
7d0e6e80 248
18722dfd
DT
249/*
250 * lvextend --use-policies is usually called by dmeventd, as a method of
251 * "auto extending" an LV as it's used. It checks how full a snapshot cow or
252 * thin pool is, and extends it if it's too full, based on threshold settings
253 * in lvm.conf for when to auto extend it.
254 *
255 * The extension of a thin pool LV can involve extending either the data sub
256 * LV, the metadata sub LV, or both, so there may be two LVs extended here.
257 */
258static int _lv_extend_policy(struct cmd_context *cmd, struct logical_volume *lv,
259 struct lvresize_params *lp, int *skipped)
241913fe 260{
18722dfd
DT
261 uint32_t percent_main = 0;
262 uint32_t percent_meta = 0;
263 int is_active;
264
a2b2ae35
ZK
265 if (lv_is_cow(lv))
266 is_active = lv_is_active(lv);
267 else if (lv_is_thin_pool(lv) || lv_is_vdo_pool(lv))
268 /* check for -layer active LV */
269 is_active = lv_info(lv->vg->cmd, lv, 1, NULL, 0, 0);
270 else {
18722dfd 271 log_error("lvextend policy is supported only for snapshot, thin pool and vdo pool volumes.");
18722dfd
DT
272 return 0;
273 }
274
a2b2ae35
ZK
275 if (!is_active) {
276 log_error("lvextend using policy requires the volume to be active.");
18722dfd 277 return 0;
0ba5571b 278 }
7c6526aa 279
18722dfd
DT
280 /*
281 * Calculate the percent of extents to extend the LV based on current
282 * usage info from the kernel and policy settings from lvm.conf, e.g.
283 * autoextend_threshold, autoextend_percent. For thin pools, both the
284 * thin pool data LV and thin pool metadata LV may need to be extended.
285 * In this case, percent_main is the amount to extend the data LV, and
286 * percent_meta is the amount to extend the metadata LV.
287 */
288 if (!lv_extend_policy_calculate_percent(lv, &percent_main, &percent_meta))
289 return_0;
290
291 if (!percent_main && !percent_meta) {
292 log_debug("lvextend policy not needed.");
293 *skipped = 1;
294 return 1;
295 }
7c6526aa 296
18722dfd
DT
297 *skipped = 0;
298 lp->policy_percent_main = percent_main;
299 lp->policy_percent_meta = percent_meta;
300
301 return lv_resize(cmd, lv, lp);
302}
303
304static int _lvextend_policy_single(struct cmd_context *cmd, struct logical_volume *lv,
305 struct processing_handle *handle)
306{
307 struct lvresize_params *lp = (struct lvresize_params *) handle->custom_handle;
308 int skipped = 0;
309
310 if (cmd->position_argc > 1) {
311 /* First pos arg is required LV, remaining are optional PVs. */
312 if (!(lp->pvh = create_pv_list(cmd->mem, lv->vg, cmd->position_argc - 1, cmd->position_argv + 1, 0)))
313 return_ECMD_FAILED;
314 } else
315 lp->pvh = &lv->vg->pvs;
316
317 if (!_lv_extend_policy(cmd, lv, lp, &skipped))
318 return ECMD_FAILED;
319
320 if (!skipped)
321 log_print_unless_silent("Logical volume %s successfully resized.", display_lvname(lv));
322 return ECMD_PROCESSED;
323}
324
325static int _lvresize_single(struct cmd_context *cmd, struct logical_volume *lv,
326 struct processing_handle *handle)
327{
328 struct lvresize_params *lp = (struct lvresize_params *) handle->custom_handle;
264827cb 329 int ret;
18722dfd
DT
330
331 if (cmd->position_argc > 1) {
332 /* First pos arg is required LV, remaining are optional PVs. */
333 if (!(lp->pvh = create_pv_list(cmd->mem, lv->vg, cmd->position_argc - 1, cmd->position_argv + 1, 0)))
334 return_ECMD_FAILED;
335 } else
336 lp->pvh = &lv->vg->pvs;
337
264827cb 338 ret = lv_resize(cmd, lv, lp);
18722dfd 339
264827cb
DT
340 if (ret || lp->extend_fs_error)
341 log_print_unless_silent("Logical volume %s successfully resized.",
342 display_lvname(lv));
343 if (!ret)
344 return ECMD_FAILED;
18722dfd
DT
345 return ECMD_PROCESSED;
346}
347
348int lvextend_policy_cmd(struct cmd_context *cmd, int argc, char **argv)
349{
350 struct processing_handle *handle;
351 struct lvresize_params lp;
352 int ret;
353
354 if (!_lvresize_params(cmd, &lp))
355 return EINVALID_CMD_LINE;
356
357 if (!(handle = init_processing_handle(cmd, NULL)))
358 return ECMD_FAILED;
359
360 handle->custom_handle = &lp;
361
362 ret = process_each_lv(cmd, 1, cmd->position_argv, NULL, NULL, READ_FOR_UPDATE,
363 handle, NULL, &_lvextend_policy_single);
364
365 destroy_processing_handle(cmd, handle);
7c6526aa 366
67763a9b
DT
367 return ret;
368}
369
18722dfd 370int lvresize_cmd(struct cmd_context *cmd, int argc, char **argv)
67763a9b 371{
5a32d2c1 372 struct processing_handle *handle;
18722dfd 373 struct lvresize_params lp;
264827cb 374 int retries = 0;
9b92cb27 375 int ret;
67763a9b 376
18722dfd 377 if (!_lvresize_params(cmd, &lp))
67763a9b
DT
378 return EINVALID_CMD_LINE;
379
18722dfd 380 if (!(handle = init_processing_handle(cmd, NULL)))
67763a9b 381 return ECMD_FAILED;
67763a9b
DT
382
383 handle->custom_handle = &lp;
384
264827cb 385retry:
18722dfd
DT
386 ret = process_each_lv(cmd, 1, cmd->position_argv, NULL, NULL, READ_FOR_UPDATE,
387 handle, NULL, &_lvresize_single);
241913fe 388
264827cb
DT
389 /*
390 * The VG can be changed by another command while it is unlocked
391 * during fs resize. The fs steps likely succeeded, and this
392 * retry will likely find that no more fs steps are needed, and
393 * will resize the LV directly.
394 */
395 if (lp.vg_changed_error && !retries) {
396 lp.vg_changed_error = 0;
397 retries = 1;
398 goto retry;
399 } else if (lp.vg_changed_error && retries) {
400 log_error("VG changed during file system resize, LV not resized.");
401 ret = ECMD_FAILED;
402 }
403
67763a9b 404 destroy_processing_handle(cmd, handle);
5a32d2c1 405
85e68a83
DT
406 if (lp.lockd_lv_refresh_path && !lockd_lv_refresh(cmd, &lp))
407 ret = ECMD_FAILED;
408
67763a9b 409 return ret;
241913fe 410}
18722dfd
DT
411
412/*
413 * All lvresize command defs have their own function,
414 * so the generic function name is unused.
415 */
416
417int lvresize(struct cmd_context *cmd, int argc, char **argv)
418{
419 log_error(INTERNAL_ERROR "Missing function for command definition %d:%s.",
bebbb1e6 420 cmd->command->command_index, command_enum(cmd->command->command_enum));
18722dfd
DT
421 return ECMD_FAILED;
422}
423
This page took 0.283372 seconds and 6 git commands to generate.