lvconvert.c revision 1.1.1.2 1 1.1 haad /* $NetBSD: lvconvert.c,v 1.1.1.2 2009/12/02 00:25:50 haad Exp $ */
2 1.1 haad
3 1.1 haad /*
4 1.1 haad * Copyright (C) 2005-2007 Red Hat, Inc. All rights reserved.
5 1.1 haad *
6 1.1 haad * This file is part of LVM2.
7 1.1 haad *
8 1.1 haad * This copyrighted material is made available to anyone wishing to use,
9 1.1 haad * modify, copy, or redistribute it subject to the terms and conditions
10 1.1 haad * of the GNU Lesser General Public License v.2.1.
11 1.1 haad *
12 1.1 haad * You should have received a copy of the GNU Lesser General Public License
13 1.1 haad * along with this program; if not, write to the Free Software Foundation,
14 1.1 haad * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15 1.1 haad */
16 1.1 haad
17 1.1 haad #include "tools.h"
18 1.1 haad #include "polldaemon.h"
19 1.1 haad #include "lv_alloc.h"
20 1.1 haad
21 1.1 haad struct lvconvert_params {
22 1.1 haad int snapshot;
23 1.1 haad int zero;
24 1.1 haad
25 1.1 haad const char *origin;
26 1.1 haad const char *lv_name;
27 1.1 haad const char *lv_name_full;
28 1.1 haad const char *vg_name;
29 1.1 haad int wait_completion;
30 1.1 haad int need_polling;
31 1.1 haad
32 1.1 haad uint32_t chunk_size;
33 1.1 haad uint32_t region_size;
34 1.1 haad
35 1.1 haad uint32_t mirrors;
36 1.1 haad sign_t mirrors_sign;
37 1.1 haad
38 1.1 haad struct segment_type *segtype;
39 1.1 haad
40 1.1 haad alloc_policy_t alloc;
41 1.1 haad
42 1.1 haad int pv_count;
43 1.1 haad char **pvs;
44 1.1 haad struct dm_list *pvh;
45 1.1 haad };
46 1.1 haad
47 1.1 haad static int _lvconvert_name_params(struct lvconvert_params *lp,
48 1.1 haad struct cmd_context *cmd,
49 1.1 haad int *pargc, char ***pargv)
50 1.1 haad {
51 1.1 haad char *ptr;
52 1.1 haad const char *vg_name = NULL;
53 1.1 haad
54 1.1 haad if (lp->snapshot) {
55 1.1 haad if (!*pargc) {
56 1.1 haad log_error("Please specify a logical volume to act as "
57 1.1 haad "the snapshot origin.");
58 1.1 haad return 0;
59 1.1 haad }
60 1.1 haad
61 1.1 haad lp->origin = *pargv[0];
62 1.1 haad (*pargv)++, (*pargc)--;
63 1.1 haad if (!(lp->vg_name = extract_vgname(cmd, lp->origin))) {
64 1.1 haad log_error("The origin name should include the "
65 1.1 haad "volume group.");
66 1.1 haad return 0;
67 1.1 haad }
68 1.1 haad
69 1.1 haad /* Strip the volume group from the origin */
70 1.1 haad if ((ptr = strrchr(lp->origin, (int) '/')))
71 1.1 haad lp->origin = ptr + 1;
72 1.1 haad }
73 1.1 haad
74 1.1 haad if (!*pargc) {
75 1.1 haad log_error("Please provide logical volume path");
76 1.1 haad return 0;
77 1.1 haad }
78 1.1 haad
79 1.1 haad lp->lv_name = lp->lv_name_full = (*pargv)[0];
80 1.1 haad (*pargv)++, (*pargc)--;
81 1.1 haad
82 1.1 haad if (strchr(lp->lv_name_full, '/') &&
83 1.1 haad (vg_name = extract_vgname(cmd, lp->lv_name_full)) &&
84 1.1 haad lp->vg_name && strcmp(vg_name, lp->vg_name)) {
85 1.1 haad log_error("Please use a single volume group name "
86 1.1 haad "(\"%s\" or \"%s\")", vg_name, lp->vg_name);
87 1.1 haad return 0;
88 1.1 haad }
89 1.1 haad
90 1.1 haad if (!lp->vg_name)
91 1.1 haad lp->vg_name = vg_name;
92 1.1 haad
93 1.1 haad if (!validate_name(lp->vg_name)) {
94 1.1 haad log_error("Please provide a valid volume group name");
95 1.1 haad return 0;
96 1.1 haad }
97 1.1 haad
98 1.1 haad if ((ptr = strrchr(lp->lv_name_full, '/')))
99 1.1 haad lp->lv_name = ptr + 1;
100 1.1 haad
101 1.1 haad if (!apply_lvname_restrictions(lp->lv_name))
102 1.1 haad return_0;
103 1.1 haad
104 1.1 haad return 1;
105 1.1 haad }
106 1.1 haad
107 1.1 haad static int _read_params(struct lvconvert_params *lp, struct cmd_context *cmd,
108 1.1 haad int argc, char **argv)
109 1.1 haad {
110 1.1 haad int region_size;
111 1.1 haad int pagesize = lvm_getpagesize();
112 1.1 haad
113 1.1 haad memset(lp, 0, sizeof(*lp));
114 1.1 haad
115 1.1 haad if (arg_count(cmd, snapshot_ARG) &&
116 1.1.1.2 haad (arg_count(cmd, mirrorlog_ARG) || arg_count(cmd, mirrors_ARG) ||
117 1.1.1.2 haad arg_count(cmd, repair_ARG))) {
118 1.1.1.2 haad log_error("--snapshot argument cannot be mixed "
119 1.1.1.2 haad "with --mirrors, --repair or --log");
120 1.1 haad return 0;
121 1.1 haad }
122 1.1 haad
123 1.1 haad if (!arg_count(cmd, background_ARG))
124 1.1 haad lp->wait_completion = 1;
125 1.1 haad
126 1.1 haad if (arg_count(cmd, snapshot_ARG))
127 1.1 haad lp->snapshot = 1;
128 1.1 haad
129 1.1 haad if (arg_count(cmd, mirrors_ARG)) {
130 1.1 haad lp->mirrors = arg_uint_value(cmd, mirrors_ARG, 0);
131 1.1 haad lp->mirrors_sign = arg_sign_value(cmd, mirrors_ARG, 0);
132 1.1 haad }
133 1.1 haad
134 1.1.1.2 haad lp->alloc = arg_uint_value(cmd, alloc_ARG, ALLOC_INHERIT);
135 1.1 haad
136 1.1 haad if (lp->snapshot) {
137 1.1 haad if (arg_count(cmd, regionsize_ARG)) {
138 1.1 haad log_error("--regionsize is only available with mirrors");
139 1.1 haad return 0;
140 1.1 haad }
141 1.1 haad
142 1.1 haad if (arg_sign_value(cmd, chunksize_ARG, 0) == SIGN_MINUS) {
143 1.1 haad log_error("Negative chunk size is invalid");
144 1.1 haad return 0;
145 1.1 haad }
146 1.1 haad lp->chunk_size = arg_uint_value(cmd, chunksize_ARG, 8);
147 1.1 haad if (lp->chunk_size < 8 || lp->chunk_size > 1024 ||
148 1.1 haad (lp->chunk_size & (lp->chunk_size - 1))) {
149 1.1 haad log_error("Chunk size must be a power of 2 in the "
150 1.1 haad "range 4K to 512K");
151 1.1 haad return 0;
152 1.1 haad }
153 1.1 haad log_verbose("Setting chunksize to %d sectors.", lp->chunk_size);
154 1.1 haad
155 1.1 haad if (!(lp->segtype = get_segtype_from_string(cmd, "snapshot")))
156 1.1 haad return_0;
157 1.1 haad
158 1.1 haad lp->zero = strcmp(arg_str_value(cmd, zero_ARG,
159 1.1 haad (lp->segtype->flags &
160 1.1 haad SEG_CANNOT_BE_ZEROED) ?
161 1.1 haad "n" : "y"), "n");
162 1.1 haad
163 1.1 haad } else { /* Mirrors */
164 1.1 haad if (arg_count(cmd, chunksize_ARG)) {
165 1.1 haad log_error("--chunksize is only available with "
166 1.1 haad "snapshots");
167 1.1 haad return 0;
168 1.1 haad }
169 1.1 haad
170 1.1 haad if (arg_count(cmd, zero_ARG)) {
171 1.1 haad log_error("--zero is only available with snapshots");
172 1.1 haad return 0;
173 1.1 haad }
174 1.1 haad
175 1.1 haad /*
176 1.1 haad * --regionsize is only valid if converting an LV into a mirror.
177 1.1 haad * Checked when we know the state of the LV being converted.
178 1.1 haad */
179 1.1 haad
180 1.1 haad if (arg_count(cmd, regionsize_ARG)) {
181 1.1 haad if (arg_sign_value(cmd, regionsize_ARG, 0) ==
182 1.1 haad SIGN_MINUS) {
183 1.1 haad log_error("Negative regionsize is invalid");
184 1.1 haad return 0;
185 1.1 haad }
186 1.1 haad lp->region_size = arg_uint_value(cmd, regionsize_ARG, 0);
187 1.1 haad } else {
188 1.1 haad region_size = 2 * find_config_tree_int(cmd,
189 1.1 haad "activation/mirror_region_size",
190 1.1 haad DEFAULT_MIRROR_REGION_SIZE);
191 1.1 haad if (region_size < 0) {
192 1.1 haad log_error("Negative regionsize in "
193 1.1 haad "configuration file is invalid");
194 1.1 haad return 0;
195 1.1 haad }
196 1.1 haad lp->region_size = region_size;
197 1.1 haad }
198 1.1 haad
199 1.1 haad if (lp->region_size % (pagesize >> SECTOR_SHIFT)) {
200 1.1 haad log_error("Region size (%" PRIu32 ") must be "
201 1.1 haad "a multiple of machine memory "
202 1.1 haad "page size (%d)",
203 1.1 haad lp->region_size, pagesize >> SECTOR_SHIFT);
204 1.1 haad return 0;
205 1.1 haad }
206 1.1 haad
207 1.1 haad if (lp->region_size & (lp->region_size - 1)) {
208 1.1 haad log_error("Region size (%" PRIu32
209 1.1 haad ") must be a power of 2", lp->region_size);
210 1.1 haad return 0;
211 1.1 haad }
212 1.1 haad
213 1.1 haad if (!lp->region_size) {
214 1.1 haad log_error("Non-zero region size must be supplied.");
215 1.1 haad return 0;
216 1.1 haad }
217 1.1 haad
218 1.1 haad if (!(lp->segtype = get_segtype_from_string(cmd, "mirror")))
219 1.1 haad return_0;
220 1.1 haad }
221 1.1 haad
222 1.1 haad if (activation() && lp->segtype->ops->target_present &&
223 1.1.1.2 haad !lp->segtype->ops->target_present(cmd, NULL, NULL)) {
224 1.1 haad log_error("%s: Required device-mapper target(s) not "
225 1.1 haad "detected in your kernel", lp->segtype->name);
226 1.1 haad return 0;
227 1.1 haad }
228 1.1 haad
229 1.1 haad if (!_lvconvert_name_params(lp, cmd, &argc, &argv))
230 1.1 haad return_0;
231 1.1 haad
232 1.1 haad lp->pv_count = argc;
233 1.1 haad lp->pvs = argv;
234 1.1 haad
235 1.1 haad return 1;
236 1.1 haad }
237 1.1 haad
238 1.1 haad static struct volume_group *_get_lvconvert_vg(struct cmd_context *cmd,
239 1.1.1.2 haad const char *lv_name, const char *uuid)
240 1.1 haad {
241 1.1 haad dev_close_all();
242 1.1 haad
243 1.1.1.2 haad return vg_read_for_update(cmd, extract_vgname(cmd, lv_name),
244 1.1.1.2 haad NULL, 0);
245 1.1 haad }
246 1.1 haad
247 1.1 haad static struct logical_volume *_get_lvconvert_lv(struct cmd_context *cmd __attribute((unused)),
248 1.1 haad struct volume_group *vg,
249 1.1 haad const char *name,
250 1.1.1.2 haad const char *uuid,
251 1.1 haad uint32_t lv_type __attribute((unused)))
252 1.1 haad {
253 1.1.1.2 haad struct logical_volume *lv = find_lv(vg, name);
254 1.1.1.2 haad
255 1.1.1.2 haad if (!lv || (uuid && strcmp(uuid, (char *)&lv->lvid)))
256 1.1.1.2 haad return NULL;
257 1.1.1.2 haad
258 1.1.1.2 haad return lv;
259 1.1 haad }
260 1.1 haad
261 1.1 haad static int _update_lvconvert_mirror(struct cmd_context *cmd __attribute((unused)),
262 1.1 haad struct volume_group *vg __attribute((unused)),
263 1.1 haad struct logical_volume *lv __attribute((unused)),
264 1.1 haad struct dm_list *lvs_changed __attribute((unused)),
265 1.1 haad unsigned flags __attribute((unused)))
266 1.1 haad {
267 1.1 haad /* lvconvert mirror doesn't require periodical metadata update */
268 1.1 haad return 1;
269 1.1 haad }
270 1.1 haad
271 1.1 haad static int _finish_lvconvert_mirror(struct cmd_context *cmd,
272 1.1 haad struct volume_group *vg,
273 1.1 haad struct logical_volume *lv,
274 1.1 haad struct dm_list *lvs_changed __attribute((unused)))
275 1.1 haad {
276 1.1.1.2 haad int r = 0;
277 1.1.1.2 haad
278 1.1 haad if (!collapse_mirrored_lv(lv)) {
279 1.1 haad log_error("Failed to remove temporary sync layer.");
280 1.1 haad return 0;
281 1.1 haad }
282 1.1 haad
283 1.1 haad lv->status &= ~CONVERTING;
284 1.1 haad
285 1.1 haad log_very_verbose("Updating logical volume \"%s\" on disk(s)", lv->name);
286 1.1 haad
287 1.1 haad if (!vg_write(vg))
288 1.1 haad return_0;
289 1.1 haad
290 1.1 haad if (!suspend_lv(cmd, lv)) {
291 1.1 haad log_error("Failed to lock %s", lv->name);
292 1.1 haad vg_revert(vg);
293 1.1.1.2 haad goto out;
294 1.1 haad }
295 1.1 haad
296 1.1 haad if (!vg_commit(vg)) {
297 1.1 haad resume_lv(cmd, lv);
298 1.1.1.2 haad goto_out;
299 1.1 haad }
300 1.1 haad
301 1.1 haad log_very_verbose("Updating \"%s\" in kernel", lv->name);
302 1.1 haad
303 1.1 haad if (!resume_lv(cmd, lv)) {
304 1.1 haad log_error("Problem reactivating %s", lv->name);
305 1.1.1.2 haad goto out;
306 1.1 haad }
307 1.1 haad
308 1.1.1.2 haad r = 1;
309 1.1 haad log_print("Logical volume %s converted.", lv->name);
310 1.1.1.2 haad out:
311 1.1.1.2 haad backup(vg);
312 1.1.1.2 haad return r;
313 1.1 haad }
314 1.1 haad
315 1.1 haad static struct poll_functions _lvconvert_mirror_fns = {
316 1.1 haad .get_copy_vg = _get_lvconvert_vg,
317 1.1 haad .get_copy_lv = _get_lvconvert_lv,
318 1.1.1.2 haad .poll_progress = poll_mirror_progress,
319 1.1 haad .update_metadata = _update_lvconvert_mirror,
320 1.1 haad .finish_copy = _finish_lvconvert_mirror,
321 1.1 haad };
322 1.1 haad
323 1.1.1.2 haad int lvconvert_poll(struct cmd_context *cmd, struct logical_volume *lv,
324 1.1 haad unsigned background)
325 1.1 haad {
326 1.1.1.2 haad int len = strlen(lv->vg->name) + strlen(lv->name) + 2;
327 1.1.1.2 haad char *uuid = alloca(sizeof(lv->lvid));
328 1.1.1.2 haad char *lv_full_name = alloca(len);
329 1.1.1.2 haad
330 1.1.1.2 haad
331 1.1.1.2 haad if (!uuid || !lv_full_name)
332 1.1.1.2 haad return_0;
333 1.1.1.2 haad
334 1.1.1.2 haad if (!dm_snprintf(lv_full_name, len, "%s/%s", lv->vg->name, lv->name))
335 1.1.1.2 haad return_0;
336 1.1.1.2 haad
337 1.1.1.2 haad memcpy(uuid, &lv->lvid, sizeof(lv->lvid));
338 1.1.1.2 haad
339 1.1.1.2 haad return poll_daemon(cmd, lv_full_name, uuid, background, 0,
340 1.1.1.2 haad &_lvconvert_mirror_fns, "Converted");
341 1.1 haad }
342 1.1 haad
343 1.1 haad static int _insert_lvconvert_layer(struct cmd_context *cmd,
344 1.1 haad struct logical_volume *lv)
345 1.1 haad {
346 1.1 haad char *format, *layer_name;
347 1.1 haad size_t len;
348 1.1 haad int i;
349 1.1 haad
350 1.1 haad /*
351 1.1 haad * We would like to give the same number for this layer
352 1.1 haad * and the newly added mimage.
353 1.1 haad * However, LV name of newly added mimage is determined *after*
354 1.1 haad * the LV name of this layer is determined.
355 1.1 haad *
356 1.1 haad * So, use generate_lv_name() to generate mimage name first
357 1.1 haad * and take the number from it.
358 1.1 haad */
359 1.1 haad
360 1.1 haad len = strlen(lv->name) + 32;
361 1.1 haad if (!(format = alloca(len)) ||
362 1.1 haad !(layer_name = alloca(len)) ||
363 1.1 haad dm_snprintf(format, len, "%s_mimage_%%d", lv->name) < 0) {
364 1.1 haad log_error("lvconvert: layer name allocation failed.");
365 1.1 haad return 0;
366 1.1 haad }
367 1.1 haad
368 1.1 haad if (!generate_lv_name(lv->vg, format, layer_name, len) ||
369 1.1 haad sscanf(layer_name, format, &i) != 1) {
370 1.1 haad log_error("lvconvert: layer name generation failed.");
371 1.1 haad return 0;
372 1.1 haad }
373 1.1 haad
374 1.1 haad if (dm_snprintf(layer_name, len, MIRROR_SYNC_LAYER "_%d", i) < 0) {
375 1.1 haad log_error("layer name allocation failed.");
376 1.1 haad return 0;
377 1.1 haad }
378 1.1 haad
379 1.1 haad if (!insert_layer_for_lv(cmd, lv, 0, layer_name)) {
380 1.1 haad log_error("Failed to insert resync layer");
381 1.1 haad return 0;
382 1.1 haad }
383 1.1 haad
384 1.1 haad return 1;
385 1.1 haad }
386 1.1 haad
387 1.1.1.2 haad static int _area_missing(struct lv_segment *lvseg, int s)
388 1.1.1.2 haad {
389 1.1.1.2 haad if (seg_type(lvseg, s) == AREA_LV) {
390 1.1.1.2 haad if (seg_lv(lvseg, s)->status & PARTIAL_LV)
391 1.1.1.2 haad return 1;
392 1.1.1.2 haad } else if ((seg_type(lvseg, s) == AREA_PV) &&
393 1.1.1.2 haad (seg_pv(lvseg, s)->status & MISSING_PV))
394 1.1.1.2 haad return 1;
395 1.1.1.2 haad
396 1.1.1.2 haad return 0;
397 1.1.1.2 haad }
398 1.1.1.2 haad
399 1.1.1.2 haad /* FIXME we want to handle mirror stacks here... */
400 1.1.1.2 haad static int _failed_mirrors_count(struct logical_volume *lv)
401 1.1.1.2 haad {
402 1.1.1.2 haad struct lv_segment *lvseg;
403 1.1.1.2 haad int ret = 0;
404 1.1.1.2 haad int s;
405 1.1.1.2 haad
406 1.1.1.2 haad dm_list_iterate_items(lvseg, &lv->segments) {
407 1.1.1.2 haad if (!seg_is_mirrored(lvseg))
408 1.1.1.2 haad return -1;
409 1.1.1.2 haad for (s = 0; s < lvseg->area_count; s++)
410 1.1.1.2 haad if (_area_missing(lvseg, s))
411 1.1.1.2 haad ret++;
412 1.1.1.2 haad }
413 1.1.1.2 haad
414 1.1.1.2 haad return ret;
415 1.1.1.2 haad }
416 1.1.1.2 haad
417 1.1.1.2 haad static struct dm_list *_failed_pv_list(struct volume_group *vg)
418 1.1.1.2 haad {
419 1.1.1.2 haad struct dm_list *failed_pvs;
420 1.1.1.2 haad struct pv_list *pvl, *new_pvl;
421 1.1.1.2 haad
422 1.1.1.2 haad if (!(failed_pvs = dm_pool_alloc(vg->vgmem, sizeof(*failed_pvs)))) {
423 1.1.1.2 haad log_error("Allocation of list of failed_pvs failed.");
424 1.1.1.2 haad return_NULL;
425 1.1.1.2 haad }
426 1.1.1.2 haad
427 1.1.1.2 haad dm_list_init(failed_pvs);
428 1.1.1.2 haad
429 1.1.1.2 haad dm_list_iterate_items(pvl, &vg->pvs) {
430 1.1.1.2 haad if (!(pvl->pv->status & MISSING_PV))
431 1.1.1.2 haad continue;
432 1.1.1.2 haad
433 1.1.1.2 haad if (!(new_pvl = dm_pool_alloc(vg->vgmem, sizeof(*new_pvl)))) {
434 1.1.1.2 haad log_error("Allocation of failed_pvs list entry failed.");
435 1.1.1.2 haad return_NULL;
436 1.1.1.2 haad }
437 1.1.1.2 haad new_pvl->pv = pvl->pv;
438 1.1.1.2 haad dm_list_add(failed_pvs, &new_pvl->list);
439 1.1.1.2 haad }
440 1.1.1.2 haad
441 1.1.1.2 haad return failed_pvs;
442 1.1.1.2 haad }
443 1.1.1.2 haad
444 1.1.1.2 haad /*
445 1.1.1.2 haad * Walk down the stacked mirror LV to the original mirror LV.
446 1.1.1.2 haad */
447 1.1 haad static struct logical_volume *_original_lv(struct logical_volume *lv)
448 1.1 haad {
449 1.1 haad struct logical_volume *next_lv = lv, *tmp_lv;
450 1.1 haad
451 1.1 haad while ((tmp_lv = find_temporary_mirror(next_lv)))
452 1.1 haad next_lv = tmp_lv;
453 1.1 haad
454 1.1 haad return next_lv;
455 1.1 haad }
456 1.1 haad
457 1.1.1.2 haad static void _lvconvert_mirrors_repair_ask(struct cmd_context *cmd,
458 1.1.1.2 haad int failed_log, int failed_mirrors,
459 1.1.1.2 haad int *replace_log, int *replace_mirrors)
460 1.1.1.2 haad {
461 1.1.1.2 haad const char *leg_policy = NULL, *log_policy = NULL;
462 1.1.1.2 haad
463 1.1.1.2 haad int force = arg_count(cmd, force_ARG);
464 1.1.1.2 haad int yes = arg_count(cmd, yes_ARG);
465 1.1.1.2 haad
466 1.1.1.2 haad *replace_log = *replace_mirrors = 1;
467 1.1.1.2 haad
468 1.1.1.2 haad if (arg_count(cmd, use_policies_ARG)) {
469 1.1.1.2 haad leg_policy = find_config_tree_str(cmd,
470 1.1.1.2 haad "activation/mirror_device_fault_policy",
471 1.1.1.2 haad DEFAULT_MIRROR_DEVICE_FAULT_POLICY);
472 1.1.1.2 haad log_policy = find_config_tree_str(cmd,
473 1.1.1.2 haad "activation/mirror_log_fault_policy",
474 1.1.1.2 haad DEFAULT_MIRROR_LOG_FAULT_POLICY);
475 1.1.1.2 haad *replace_mirrors = strcmp(leg_policy, "remove");
476 1.1.1.2 haad *replace_log = strcmp(log_policy, "remove");
477 1.1.1.2 haad return;
478 1.1.1.2 haad }
479 1.1.1.2 haad
480 1.1.1.2 haad if (yes)
481 1.1.1.2 haad return;
482 1.1.1.2 haad
483 1.1.1.2 haad if (force != PROMPT) {
484 1.1.1.2 haad *replace_log = *replace_mirrors = 0;
485 1.1.1.2 haad return;
486 1.1.1.2 haad }
487 1.1.1.2 haad
488 1.1.1.2 haad if (failed_log &&
489 1.1.1.2 haad yes_no_prompt("Attempt to replace failed mirror log? [y/n]: ") == 'n') {
490 1.1.1.2 haad *replace_log = 0;
491 1.1.1.2 haad }
492 1.1.1.2 haad
493 1.1.1.2 haad if (failed_mirrors &&
494 1.1.1.2 haad yes_no_prompt("Attempt to replace failed mirror images "
495 1.1.1.2 haad "(requires full device resync)? [y/n]: ") == 'n') {
496 1.1.1.2 haad *replace_mirrors = 0;
497 1.1.1.2 haad }
498 1.1.1.2 haad }
499 1.1.1.2 haad
500 1.1.1.2 haad static int _using_corelog(struct logical_volume *lv)
501 1.1.1.2 haad {
502 1.1.1.2 haad return !first_seg(_original_lv(lv))->log_lv;
503 1.1.1.2 haad }
504 1.1.1.2 haad
505 1.1.1.2 haad static int _lv_update_log_type(struct cmd_context *cmd,
506 1.1.1.2 haad struct lvconvert_params *lp,
507 1.1.1.2 haad struct logical_volume *lv,
508 1.1.1.2 haad int corelog)
509 1.1.1.2 haad {
510 1.1.1.2 haad struct logical_volume *original_lv = _original_lv(lv);
511 1.1.1.2 haad if (_using_corelog(lv) && !corelog) {
512 1.1.1.2 haad if (!add_mirror_log(cmd, original_lv, 1,
513 1.1.1.2 haad adjusted_mirror_region_size(
514 1.1.1.2 haad lv->vg->extent_size,
515 1.1.1.2 haad lv->le_count,
516 1.1.1.2 haad lp->region_size),
517 1.1.1.2 haad lp->pvh, lp->alloc))
518 1.1.1.2 haad return_0;
519 1.1.1.2 haad } else if (!_using_corelog(lv) && corelog) {
520 1.1.1.2 haad if (!remove_mirror_log(cmd, original_lv,
521 1.1.1.2 haad lp->pv_count ? lp->pvh : NULL))
522 1.1.1.2 haad return_0;
523 1.1.1.2 haad }
524 1.1.1.2 haad return 1;
525 1.1.1.2 haad }
526 1.1.1.2 haad
527 1.1.1.2 haad static int _lvconvert_mirrors(struct cmd_context *cmd, struct logical_volume *lv,
528 1.1.1.2 haad struct lvconvert_params *lp)
529 1.1 haad {
530 1.1 haad struct lv_segment *seg;
531 1.1 haad uint32_t existing_mirrors;
532 1.1 haad const char *mirrorlog;
533 1.1 haad unsigned corelog = 0;
534 1.1.1.2 haad int r = 0;
535 1.1.1.2 haad struct logical_volume *log_lv, *layer_lv;
536 1.1.1.2 haad int failed_mirrors = 0, failed_log = 0;
537 1.1.1.2 haad struct dm_list *old_pvh = NULL, *remove_pvs = NULL;
538 1.1.1.2 haad
539 1.1.1.2 haad int repair = arg_count(cmd, repair_ARG);
540 1.1.1.2 haad int replace_log = 1, replace_mirrors = 1;
541 1.1 haad
542 1.1 haad seg = first_seg(lv);
543 1.1 haad existing_mirrors = lv_mirror_count(lv);
544 1.1 haad
545 1.1 haad /* If called with no argument, try collapsing the resync layers */
546 1.1 haad if (!arg_count(cmd, mirrors_ARG) && !arg_count(cmd, mirrorlog_ARG) &&
547 1.1.1.2 haad !arg_count(cmd, corelog_ARG) && !arg_count(cmd, regionsize_ARG) &&
548 1.1.1.2 haad !repair) {
549 1.1.1.2 haad if (find_temporary_mirror(lv) || (lv->status & CONVERTING))
550 1.1.1.2 haad lp->need_polling = 1;
551 1.1 haad return 1;
552 1.1 haad }
553 1.1 haad
554 1.1.1.2 haad if (arg_count(cmd, mirrors_ARG) && repair) {
555 1.1.1.2 haad log_error("You may only use one of --mirrors and --repair.");
556 1.1.1.2 haad return 0;
557 1.1.1.2 haad }
558 1.1.1.2 haad
559 1.1 haad /*
560 1.1 haad * Adjust required number of mirrors
561 1.1 haad *
562 1.1 haad * We check mirrors_ARG again to see if it
563 1.1 haad * was supplied. If not, they want the mirror
564 1.1 haad * count to remain the same. They may be changing
565 1.1 haad * the logging type.
566 1.1 haad */
567 1.1 haad if (!arg_count(cmd, mirrors_ARG))
568 1.1 haad lp->mirrors = existing_mirrors;
569 1.1 haad else if (lp->mirrors_sign == SIGN_PLUS)
570 1.1 haad lp->mirrors = existing_mirrors + lp->mirrors;
571 1.1 haad else if (lp->mirrors_sign == SIGN_MINUS)
572 1.1 haad lp->mirrors = existing_mirrors - lp->mirrors;
573 1.1 haad else
574 1.1 haad lp->mirrors += 1;
575 1.1 haad
576 1.1.1.2 haad if (repair) {
577 1.1.1.2 haad cmd->handles_missing_pvs = 1;
578 1.1.1.2 haad cmd->partial_activation = 1;
579 1.1.1.2 haad lp->need_polling = 0;
580 1.1.1.2 haad if (!(lv->status & PARTIAL_LV)) {
581 1.1.1.2 haad log_error("The mirror is consistent, nothing to repair.");
582 1.1.1.2 haad return 0;
583 1.1.1.2 haad }
584 1.1.1.2 haad if ((failed_mirrors = _failed_mirrors_count(lv)) < 0)
585 1.1.1.2 haad return_0;
586 1.1.1.2 haad lp->mirrors -= failed_mirrors;
587 1.1.1.2 haad log_error("Mirror status: %d of %d images failed.",
588 1.1.1.2 haad failed_mirrors, existing_mirrors);
589 1.1.1.2 haad old_pvh = lp->pvh;
590 1.1.1.2 haad if (!(lp->pvh = _failed_pv_list(lv->vg)))
591 1.1.1.2 haad return_0;
592 1.1.1.2 haad log_lv=first_seg(lv)->log_lv;
593 1.1.1.2 haad if (!log_lv || log_lv->status & PARTIAL_LV)
594 1.1.1.2 haad failed_log = corelog = 1;
595 1.1.1.2 haad } else {
596 1.1.1.2 haad /*
597 1.1.1.2 haad * Did the user try to subtract more legs than available?
598 1.1.1.2 haad */
599 1.1.1.2 haad if (lp->mirrors < 1) {
600 1.1.1.2 haad log_error("Logical volume %s only has %" PRIu32 " mirrors.",
601 1.1.1.2 haad lv->name, existing_mirrors);
602 1.1.1.2 haad return 0;
603 1.1.1.2 haad }
604 1.1 haad
605 1.1.1.2 haad /*
606 1.1.1.2 haad * Adjust log type
607 1.1.1.2 haad */
608 1.1.1.2 haad if (arg_count(cmd, corelog_ARG))
609 1.1.1.2 haad corelog = 1;
610 1.1 haad
611 1.1.1.2 haad mirrorlog = arg_str_value(cmd, mirrorlog_ARG,
612 1.1.1.2 haad corelog ? "core" : DEFAULT_MIRRORLOG);
613 1.1.1.2 haad if (!strcmp("disk", mirrorlog)) {
614 1.1.1.2 haad if (corelog) {
615 1.1.1.2 haad log_error("--mirrorlog disk and --corelog "
616 1.1.1.2 haad "are incompatible");
617 1.1.1.2 haad return 0;
618 1.1.1.2 haad }
619 1.1.1.2 haad corelog = 0;
620 1.1.1.2 haad } else if (!strcmp("core", mirrorlog))
621 1.1.1.2 haad corelog = 1;
622 1.1.1.2 haad else {
623 1.1.1.2 haad log_error("Unknown mirrorlog type: %s", mirrorlog);
624 1.1 haad return 0;
625 1.1 haad }
626 1.1 haad
627 1.1.1.2 haad log_verbose("Setting logging type to %s", mirrorlog);
628 1.1.1.2 haad }
629 1.1 haad
630 1.1 haad /*
631 1.1 haad * Region size must not change on existing mirrors
632 1.1 haad */
633 1.1 haad if (arg_count(cmd, regionsize_ARG) && (lv->status & MIRRORED) &&
634 1.1 haad (lp->region_size != seg->region_size)) {
635 1.1 haad log_error("Mirror log region size cannot be changed on "
636 1.1 haad "an existing mirror.");
637 1.1 haad return 0;
638 1.1 haad }
639 1.1 haad
640 1.1 haad /*
641 1.1.1.2 haad * For the most part, we cannot handle multi-segment mirrors. Bail out
642 1.1.1.2 haad * early if we have encountered one.
643 1.1.1.2 haad */
644 1.1.1.2 haad if ((lv->status & MIRRORED) && dm_list_size(&lv->segments) != 1) {
645 1.1.1.2 haad log_error("Logical volume %s has multiple "
646 1.1.1.2 haad "mirror segments.", lv->name);
647 1.1.1.2 haad return 0;
648 1.1.1.2 haad }
649 1.1.1.2 haad
650 1.1.1.2 haad if (repair)
651 1.1.1.2 haad _lvconvert_mirrors_repair_ask(cmd, failed_log, failed_mirrors,
652 1.1.1.2 haad &replace_log, &replace_mirrors);
653 1.1.1.2 haad
654 1.1.1.2 haad restart:
655 1.1.1.2 haad /*
656 1.1 haad * Converting from mirror to linear
657 1.1 haad */
658 1.1 haad if ((lp->mirrors == 1)) {
659 1.1 haad if (!(lv->status & MIRRORED)) {
660 1.1 haad log_error("Logical volume %s is already not mirrored.",
661 1.1 haad lv->name);
662 1.1 haad return 1;
663 1.1 haad }
664 1.1 haad }
665 1.1 haad
666 1.1 haad /*
667 1.1.1.2 haad * Downconversion.
668 1.1 haad */
669 1.1.1.2 haad if (lp->mirrors < existing_mirrors) {
670 1.1.1.2 haad /* Reduce number of mirrors */
671 1.1.1.2 haad if (repair || lp->pv_count)
672 1.1.1.2 haad remove_pvs = lp->pvh;
673 1.1.1.2 haad if (!lv_remove_mirrors(cmd, lv, existing_mirrors - lp->mirrors,
674 1.1.1.2 haad (corelog || lp->mirrors == 1) ? 1U : 0U,
675 1.1.1.2 haad remove_pvs, 0))
676 1.1.1.2 haad return_0;
677 1.1.1.2 haad if (lp->mirrors > 1 &&
678 1.1.1.2 haad !_lv_update_log_type(cmd, lp, lv, corelog))
679 1.1.1.2 haad return_0;
680 1.1.1.2 haad } else if (!(lv->status & MIRRORED)) {
681 1.1.1.2 haad /*
682 1.1.1.2 haad * Converting from linear to mirror
683 1.1.1.2 haad */
684 1.1.1.2 haad
685 1.1 haad /* FIXME Share code with lvcreate */
686 1.1 haad
687 1.1 haad /* FIXME Why is this restriction here? Fix it! */
688 1.1 haad dm_list_iterate_items(seg, &lv->segments) {
689 1.1 haad if (seg_is_striped(seg) && seg->area_count > 1) {
690 1.1 haad log_error("Mirrors of striped volumes are not yet supported.");
691 1.1 haad return 0;
692 1.1 haad }
693 1.1 haad }
694 1.1 haad
695 1.1.1.2 haad /*
696 1.1.1.2 haad * FIXME should we give not only lp->pvh, but also all PVs
697 1.1.1.2 haad * currently taken by the mirror? Would make more sense from
698 1.1.1.2 haad * user perspective.
699 1.1.1.2 haad */
700 1.1 haad if (!lv_add_mirrors(cmd, lv, lp->mirrors - 1, 1,
701 1.1 haad adjusted_mirror_region_size(
702 1.1 haad lv->vg->extent_size,
703 1.1 haad lv->le_count,
704 1.1 haad lp->region_size),
705 1.1 haad corelog ? 0U : 1U, lp->pvh, lp->alloc,
706 1.1 haad MIRROR_BY_LV))
707 1.1 haad return_0;
708 1.1 haad if (lp->wait_completion)
709 1.1 haad lp->need_polling = 1;
710 1.1.1.2 haad } else if (lp->mirrors > existing_mirrors || failed_mirrors) {
711 1.1.1.2 haad if (lv->status & MIRROR_NOTSYNCED) {
712 1.1.1.2 haad log_error("Can't add mirror to out-of-sync mirrored "
713 1.1.1.2 haad "LV: use lvchange --resync first.");
714 1.1.1.2 haad return 0;
715 1.1.1.2 haad }
716 1.1 haad
717 1.1 haad /*
718 1.1.1.2 haad * We allow snapshots of mirrors, but for now, we
719 1.1.1.2 haad * do not allow up converting mirrors that are under
720 1.1.1.2 haad * snapshots. The layering logic is somewhat complex,
721 1.1.1.2 haad * and preliminary test show that the conversion can't
722 1.1.1.2 haad * seem to get the correct %'age of completion.
723 1.1 haad */
724 1.1.1.2 haad if (lv_is_origin(lv)) {
725 1.1.1.2 haad log_error("Can't add additional mirror images to "
726 1.1.1.2 haad "mirrors that are under snapshots");
727 1.1 haad return 0;
728 1.1 haad }
729 1.1.1.2 haad
730 1.1 haad /*
731 1.1 haad * Log addition/removal should be done before the layer
732 1.1 haad * insertion to make the end result consistent with
733 1.1 haad * linear-to-mirror conversion.
734 1.1 haad */
735 1.1.1.2 haad if (!_lv_update_log_type(cmd, lp, lv, corelog))
736 1.1.1.2 haad return_0;
737 1.1 haad /* Insert a temporary layer for syncing,
738 1.1 haad * only if the original lv is using disk log. */
739 1.1 haad if (seg->log_lv && !_insert_lvconvert_layer(cmd, lv)) {
740 1.1 haad log_error("Failed to insert resync layer");
741 1.1 haad return 0;
742 1.1 haad }
743 1.1 haad /* FIXME: can't have multiple mlogs. force corelog. */
744 1.1 haad if (!lv_add_mirrors(cmd, lv, lp->mirrors - existing_mirrors, 1,
745 1.1 haad adjusted_mirror_region_size(
746 1.1 haad lv->vg->extent_size,
747 1.1 haad lv->le_count,
748 1.1 haad lp->region_size),
749 1.1 haad 0U, lp->pvh, lp->alloc,
750 1.1.1.2 haad MIRROR_BY_LV)) {
751 1.1.1.2 haad layer_lv = seg_lv(first_seg(lv), 0);
752 1.1.1.2 haad if (!remove_layer_from_lv(lv, layer_lv) ||
753 1.1.1.2 haad !deactivate_lv(cmd, layer_lv) ||
754 1.1.1.2 haad !lv_remove(layer_lv) || !vg_write(lv->vg) ||
755 1.1.1.2 haad !vg_commit(lv->vg)) {
756 1.1.1.2 haad log_error("ABORTING: Failed to remove "
757 1.1.1.2 haad "temporary mirror layer %s.",
758 1.1.1.2 haad layer_lv->name);
759 1.1.1.2 haad log_error("Manual cleanup with vgcfgrestore "
760 1.1.1.2 haad "and dmsetup may be required.");
761 1.1.1.2 haad return 0;
762 1.1.1.2 haad }
763 1.1 haad return_0;
764 1.1.1.2 haad }
765 1.1 haad lv->status |= CONVERTING;
766 1.1 haad lp->need_polling = 1;
767 1.1 haad }
768 1.1 haad
769 1.1.1.2 haad if (lp->mirrors == existing_mirrors) {
770 1.1.1.2 haad if (_using_corelog(lv) != corelog) {
771 1.1.1.2 haad if (!_lv_update_log_type(cmd, lp, lv, corelog))
772 1.1.1.2 haad return_0;
773 1.1.1.2 haad } else {
774 1.1.1.2 haad log_error("Logical volume %s already has %"
775 1.1.1.2 haad PRIu32 " mirror(s).", lv->name,
776 1.1.1.2 haad lp->mirrors - 1);
777 1.1.1.2 haad if (lv->status & CONVERTING)
778 1.1.1.2 haad lp->need_polling = 1;
779 1.1.1.2 haad return 1;
780 1.1.1.2 haad }
781 1.1.1.2 haad }
782 1.1.1.2 haad
783 1.1 haad log_very_verbose("Updating logical volume \"%s\" on disk(s)", lv->name);
784 1.1 haad
785 1.1 haad if (!vg_write(lv->vg))
786 1.1 haad return_0;
787 1.1 haad
788 1.1 haad if (!suspend_lv(cmd, lv)) {
789 1.1 haad log_error("Failed to lock %s", lv->name);
790 1.1 haad vg_revert(lv->vg);
791 1.1.1.2 haad goto out;
792 1.1 haad }
793 1.1 haad
794 1.1 haad if (!vg_commit(lv->vg)) {
795 1.1 haad resume_lv(cmd, lv);
796 1.1.1.2 haad goto_out;
797 1.1 haad }
798 1.1 haad
799 1.1 haad log_very_verbose("Updating \"%s\" in kernel", lv->name);
800 1.1 haad
801 1.1 haad if (!resume_lv(cmd, lv)) {
802 1.1 haad log_error("Problem reactivating %s", lv->name);
803 1.1.1.2 haad goto out;
804 1.1.1.2 haad }
805 1.1.1.2 haad
806 1.1.1.2 haad if (failed_log || failed_mirrors) {
807 1.1.1.2 haad lp->pvh = old_pvh;
808 1.1.1.2 haad if (failed_log && replace_log)
809 1.1.1.2 haad failed_log = corelog = 0;
810 1.1.1.2 haad if (replace_mirrors)
811 1.1.1.2 haad lp->mirrors += failed_mirrors;
812 1.1.1.2 haad failed_mirrors = 0;
813 1.1.1.2 haad existing_mirrors = lv_mirror_count(lv);
814 1.1.1.2 haad /* Now replace missing devices. */
815 1.1.1.2 haad if (replace_log || replace_mirrors)
816 1.1.1.2 haad goto restart;
817 1.1 haad }
818 1.1 haad
819 1.1 haad if (!lp->need_polling)
820 1.1 haad log_print("Logical volume %s converted.", lv->name);
821 1.1 haad
822 1.1.1.2 haad r = 1;
823 1.1.1.2 haad out:
824 1.1.1.2 haad backup(lv->vg);
825 1.1.1.2 haad return r;
826 1.1 haad }
827 1.1 haad
828 1.1 haad static int lvconvert_snapshot(struct cmd_context *cmd,
829 1.1 haad struct logical_volume *lv,
830 1.1 haad struct lvconvert_params *lp)
831 1.1 haad {
832 1.1 haad struct logical_volume *org;
833 1.1.1.2 haad int r = 0;
834 1.1 haad
835 1.1 haad if (!(org = find_lv(lv->vg, lp->origin))) {
836 1.1 haad log_error("Couldn't find origin volume '%s'.", lp->origin);
837 1.1 haad return 0;
838 1.1 haad }
839 1.1 haad
840 1.1 haad if (org == lv) {
841 1.1 haad log_error("Unable to use \"%s\" as both snapshot and origin.",
842 1.1 haad lv->name);
843 1.1 haad return 0;
844 1.1 haad }
845 1.1 haad
846 1.1 haad if (org->status & (LOCKED|PVMOVE|MIRRORED) || lv_is_cow(org)) {
847 1.1 haad log_error("Unable to create a snapshot of a %s LV.",
848 1.1 haad org->status & LOCKED ? "locked" :
849 1.1 haad org->status & PVMOVE ? "pvmove" :
850 1.1 haad org->status & MIRRORED ? "mirrored" :
851 1.1 haad "snapshot");
852 1.1 haad return 0;
853 1.1 haad }
854 1.1 haad
855 1.1 haad if (!lp->zero || !(lv->status & LVM_WRITE))
856 1.1 haad log_warn("WARNING: \"%s\" not zeroed", lv->name);
857 1.1 haad else if (!set_lv(cmd, lv, UINT64_C(0), 0)) {
858 1.1 haad log_error("Aborting. Failed to wipe snapshot "
859 1.1 haad "exception store.");
860 1.1 haad return 0;
861 1.1 haad }
862 1.1 haad
863 1.1 haad if (!deactivate_lv(cmd, lv)) {
864 1.1 haad log_error("Couldn't deactivate LV %s.", lv->name);
865 1.1 haad return 0;
866 1.1 haad }
867 1.1 haad
868 1.1.1.2 haad if (!vg_add_snapshot(org, lv, NULL, org->le_count, lp->chunk_size)) {
869 1.1 haad log_error("Couldn't create snapshot.");
870 1.1 haad return 0;
871 1.1 haad }
872 1.1 haad
873 1.1 haad /* store vg on disk(s) */
874 1.1 haad if (!vg_write(lv->vg))
875 1.1 haad return_0;
876 1.1 haad
877 1.1 haad if (!suspend_lv(cmd, org)) {
878 1.1 haad log_error("Failed to suspend origin %s", org->name);
879 1.1 haad vg_revert(lv->vg);
880 1.1.1.2 haad goto out;
881 1.1 haad }
882 1.1 haad
883 1.1 haad if (!vg_commit(lv->vg))
884 1.1.1.2 haad goto_out;
885 1.1 haad
886 1.1 haad if (!resume_lv(cmd, org)) {
887 1.1 haad log_error("Problem reactivating origin %s", org->name);
888 1.1.1.2 haad goto out;
889 1.1 haad }
890 1.1 haad
891 1.1 haad log_print("Logical volume %s converted to snapshot.", lv->name);
892 1.1.1.2 haad r = 1;
893 1.1.1.2 haad out:
894 1.1.1.2 haad backup(lv->vg);
895 1.1.1.2 haad return r;
896 1.1 haad }
897 1.1 haad
898 1.1 haad static int lvconvert_single(struct cmd_context *cmd, struct logical_volume *lv,
899 1.1 haad void *handle)
900 1.1 haad {
901 1.1 haad struct lvconvert_params *lp = handle;
902 1.1 haad
903 1.1 haad if (lv->status & LOCKED) {
904 1.1 haad log_error("Cannot convert locked LV %s", lv->name);
905 1.1 haad return ECMD_FAILED;
906 1.1 haad }
907 1.1 haad
908 1.1 haad if (lv_is_cow(lv)) {
909 1.1 haad log_error("Can't convert snapshot logical volume \"%s\"",
910 1.1 haad lv->name);
911 1.1 haad return ECMD_FAILED;
912 1.1 haad }
913 1.1 haad
914 1.1 haad if (lv->status & PVMOVE) {
915 1.1 haad log_error("Unable to convert pvmove LV %s", lv->name);
916 1.1 haad return ECMD_FAILED;
917 1.1 haad }
918 1.1 haad
919 1.1.1.2 haad if (arg_count(cmd, repair_ARG) && !(lv->status & MIRRORED)) {
920 1.1.1.2 haad log_error("Can't repair non-mirrored LV \"%s\".", lv->name);
921 1.1.1.2 haad return ECMD_FAILED;
922 1.1.1.2 haad }
923 1.1.1.2 haad
924 1.1 haad if (lp->snapshot) {
925 1.1 haad if (lv->status & MIRRORED) {
926 1.1 haad log_error("Unable to convert mirrored LV \"%s\" into a snapshot.", lv->name);
927 1.1 haad return ECMD_FAILED;
928 1.1 haad }
929 1.1.1.2 haad if (!archive(lv->vg)) {
930 1.1.1.2 haad stack;
931 1.1 haad return ECMD_FAILED;
932 1.1.1.2 haad }
933 1.1.1.2 haad if (!lvconvert_snapshot(cmd, lv, lp)) {
934 1.1.1.2 haad stack;
935 1.1 haad return ECMD_FAILED;
936 1.1.1.2 haad }
937 1.1 haad } else if (arg_count(cmd, mirrors_ARG) || (lv->status & MIRRORED)) {
938 1.1.1.2 haad if (!archive(lv->vg)) {
939 1.1.1.2 haad stack;
940 1.1 haad return ECMD_FAILED;
941 1.1.1.2 haad }
942 1.1.1.2 haad if (!_lvconvert_mirrors(cmd, lv, lp)) {
943 1.1.1.2 haad stack;
944 1.1 haad return ECMD_FAILED;
945 1.1.1.2 haad }
946 1.1 haad }
947 1.1 haad
948 1.1 haad return ECMD_PROCESSED;
949 1.1 haad }
950 1.1 haad
951 1.1 haad int lvconvert(struct cmd_context * cmd, int argc, char **argv)
952 1.1 haad {
953 1.1 haad struct volume_group *vg;
954 1.1 haad struct lv_list *lvl;
955 1.1 haad struct lvconvert_params lp;
956 1.1 haad int ret = ECMD_FAILED;
957 1.1 haad struct lvinfo info;
958 1.1.1.2 haad int saved_ignore_suspended_devices = ignore_suspended_devices();
959 1.1 haad
960 1.1 haad if (!_read_params(&lp, cmd, argc, argv)) {
961 1.1 haad stack;
962 1.1 haad return EINVALID_CMD_LINE;
963 1.1 haad }
964 1.1 haad
965 1.1.1.2 haad if (arg_count(cmd, repair_ARG)) {
966 1.1.1.2 haad init_ignore_suspended_devices(1);
967 1.1.1.2 haad cmd->handles_missing_pvs = 1;
968 1.1.1.2 haad }
969 1.1.1.2 haad
970 1.1 haad log_verbose("Checking for existing volume group \"%s\"", lp.vg_name);
971 1.1 haad
972 1.1.1.2 haad vg = vg_read_for_update(cmd, lp.vg_name, NULL, 0);
973 1.1.1.2 haad if (vg_read_error(vg))
974 1.1.1.2 haad goto out;
975 1.1 haad
976 1.1 haad if (!(lvl = find_lv_in_vg(vg, lp.lv_name))) {
977 1.1 haad log_error("Logical volume \"%s\" not found in "
978 1.1 haad "volume group \"%s\"", lp.lv_name, lp.vg_name);
979 1.1 haad goto bad;
980 1.1 haad }
981 1.1 haad
982 1.1 haad if (lp.pv_count) {
983 1.1 haad if (!(lp.pvh = create_pv_list(cmd->mem, vg, lp.pv_count,
984 1.1 haad lp.pvs, 0)))
985 1.1 haad goto_bad;
986 1.1 haad } else
987 1.1 haad lp.pvh = &vg->pvs;
988 1.1 haad
989 1.1 haad ret = lvconvert_single(cmd, lvl->lv, &lp);
990 1.1 haad
991 1.1 haad bad:
992 1.1 haad unlock_vg(cmd, lp.vg_name);
993 1.1 haad
994 1.1 haad if (ret == ECMD_PROCESSED && lp.need_polling) {
995 1.1 haad if (!lv_info(cmd, lvl->lv, &info, 1, 0) || !info.exists) {
996 1.1 haad log_print("Conversion starts after activation");
997 1.1.1.2 haad goto out;
998 1.1 haad }
999 1.1.1.2 haad ret = lvconvert_poll(cmd, lvl->lv,
1000 1.1 haad lp.wait_completion ? 0 : 1U);
1001 1.1 haad }
1002 1.1.1.2 haad out:
1003 1.1.1.2 haad init_ignore_suspended_devices(saved_ignore_suspended_devices);
1004 1.1.1.2 haad vg_release(vg);
1005 1.1 haad return ret;
1006 1.1 haad }
1007