]> sourceware.org Git - lvm2.git/blob - tools/pvmove.c
31bb739a37e53adab8889e711b0027f5182c907e
[lvm2.git] / tools / pvmove.c
1 /*
2 * Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
3 * Copyright (C) 2004-2010 Red Hat, Inc. All rights reserved.
4 *
5 * This file is part of LVM2.
6 *
7 * This copyrighted material is made available to anyone wishing to use,
8 * modify, copy, or redistribute it subject to the terms and conditions
9 * of the GNU Lesser General Public License v.2.1.
10 *
11 * You should have received a copy of the GNU Lesser General Public License
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
14 */
15
16 #include "tools.h"
17 #include "polldaemon.h"
18 #include "display.h"
19
20 #define PVMOVE_FIRST_TIME 0x00000001 /* Called for first time */
21
22 static int _pvmove_target_present(struct cmd_context *cmd, int clustered)
23 {
24 const struct segment_type *segtype;
25 unsigned attr = 0;
26 int found = 1;
27 static int _clustered_found = -1;
28
29 if (clustered && _clustered_found >= 0)
30 return _clustered_found;
31
32 if (!(segtype = get_segtype_from_string(cmd, "mirror")))
33 return_0;
34
35 if (activation() && segtype->ops->target_present &&
36 !segtype->ops->target_present(cmd, NULL, clustered ? &attr : NULL))
37 found = 0;
38
39 if (activation() && clustered) {
40 if (found && (attr & MIRROR_LOG_CLUSTERED))
41 _clustered_found = found = 1;
42 else
43 _clustered_found = found = 0;
44 }
45
46 return found;
47 }
48
49 static unsigned _pvmove_is_exclusive(struct cmd_context *cmd,
50 struct volume_group *vg)
51 {
52 if (vg_is_clustered(vg))
53 if (!_pvmove_target_present(cmd, 1))
54 return 1;
55
56 return 0;
57 }
58
59 /* Allow /dev/vgname/lvname, vgname/lvname or lvname */
60 static const char *_extract_lvname(struct cmd_context *cmd, const char *vgname,
61 const char *arg)
62 {
63 const char *lvname;
64
65 /* Is an lvname supplied directly? */
66 if (!strchr(arg, '/'))
67 return arg;
68
69 lvname = skip_dev_dir(cmd, arg, NULL);
70 while (*lvname == '/')
71 lvname++;
72 if (!strchr(lvname, '/')) {
73 log_error("--name takes a logical volume name");
74 return NULL;
75 }
76 if (strncmp(vgname, lvname, strlen(vgname)) ||
77 (lvname += strlen(vgname), *lvname != '/')) {
78 log_error("Named LV and old PV must be in the same VG");
79 return NULL;
80 }
81 while (*lvname == '/')
82 lvname++;
83 if (!*lvname) {
84 log_error("Incomplete LV name supplied with --name");
85 return NULL;
86 }
87 return lvname;
88 }
89
90 static struct volume_group *_get_vg(struct cmd_context *cmd, const char *vgname)
91 {
92 dev_close_all();
93
94 return vg_read_for_update(cmd, vgname, NULL, 0);
95 }
96
97 /* Create list of PVs for allocation of replacement extents */
98 static struct dm_list *_get_allocatable_pvs(struct cmd_context *cmd, int argc,
99 char **argv, struct volume_group *vg,
100 struct physical_volume *pv,
101 alloc_policy_t alloc)
102 {
103 struct dm_list *allocatable_pvs, *pvht, *pvh;
104 struct pv_list *pvl;
105
106 if (argc)
107 allocatable_pvs = create_pv_list(cmd->mem, vg, argc, argv, 1);
108 else
109 allocatable_pvs = clone_pv_list(cmd->mem, &vg->pvs);
110
111 if (!allocatable_pvs)
112 return_NULL;
113
114 dm_list_iterate_safe(pvh, pvht, allocatable_pvs) {
115 pvl = dm_list_item(pvh, struct pv_list);
116
117 /* Don't allocate onto the PV we're clearing! */
118 if ((alloc != ALLOC_ANYWHERE) && (pvl->pv->dev == pv_dev(pv))) {
119 dm_list_del(&pvl->list);
120 continue;
121 }
122
123 /* Remove PV if full */
124 if (pvl->pv->pe_count == pvl->pv->pe_alloc_count)
125 dm_list_del(&pvl->list);
126 }
127
128 if (dm_list_empty(allocatable_pvs)) {
129 log_error("No extents available for allocation");
130 return NULL;
131 }
132
133 return allocatable_pvs;
134 }
135
136 /*
137 * Replace any LV segments on given PV with temporary mirror.
138 * Returns list of LVs changed.
139 */
140 static int _insert_pvmove_mirrors(struct cmd_context *cmd,
141 struct logical_volume *lv_mirr,
142 struct dm_list *source_pvl,
143 struct logical_volume *lv,
144 struct dm_list *lvs_changed)
145
146 {
147 struct pv_list *pvl;
148 uint32_t prev_le_count;
149
150 /* Only 1 PV may feature in source_pvl */
151 pvl = dm_list_item(source_pvl->n, struct pv_list);
152
153 prev_le_count = lv_mirr->le_count;
154 if (!insert_layer_for_segments_on_pv(cmd, lv, lv_mirr, PVMOVE,
155 pvl, lvs_changed))
156 return_0;
157
158 /* check if layer was inserted */
159 if (lv_mirr->le_count - prev_le_count) {
160 lv->status |= LOCKED;
161
162 log_verbose("Moving %u extents of logical volume %s/%s",
163 lv_mirr->le_count - prev_le_count,
164 lv->vg->name, lv->name);
165 }
166
167 return 1;
168 }
169
170 /* Create new LV with mirror segments for the required copies */
171 static struct logical_volume *_set_up_pvmove_lv(struct cmd_context *cmd,
172 struct volume_group *vg,
173 struct dm_list *source_pvl,
174 const char *lv_name,
175 struct dm_list *allocatable_pvs,
176 alloc_policy_t alloc,
177 struct dm_list **lvs_changed)
178 {
179 struct logical_volume *lv_mirr, *lv;
180 struct lv_list *lvl;
181 uint32_t log_count = 0;
182 int lv_found = 0;
183 int lv_skipped = 0;
184
185 /* FIXME Cope with non-contiguous => splitting existing segments */
186 if (!(lv_mirr = lv_create_empty("pvmove%d", NULL,
187 LVM_READ | LVM_WRITE,
188 ALLOC_CONTIGUOUS, vg))) {
189 log_error("Creation of temporary pvmove LV failed");
190 return NULL;
191 }
192
193 lv_mirr->status |= (PVMOVE | LOCKED);
194
195 if (!(*lvs_changed = dm_pool_alloc(cmd->mem, sizeof(**lvs_changed)))) {
196 log_error("lvs_changed list struct allocation failed");
197 return NULL;
198 }
199
200 dm_list_init(*lvs_changed);
201
202 /* Find segments to be moved and set up mirrors */
203 dm_list_iterate_items(lvl, &vg->lvs) {
204 lv = lvl->lv;
205 if (lv == lv_mirr)
206 continue;
207 if (lv_name) {
208 if (strcmp(lv->name, lv_name))
209 continue;
210 lv_found = 1;
211 }
212 if (lv_is_origin(lv) || lv_is_cow(lv)) {
213 lv_skipped = 1;
214 log_print("Skipping snapshot-related LV %s", lv->name);
215 continue;
216 }
217 if (lv->status & MIRRORED) {
218 lv_skipped = 1;
219 log_print("Skipping mirror LV %s", lv->name);
220 continue;
221 }
222 if (lv->status & MIRROR_LOG) {
223 lv_skipped = 1;
224 log_print("Skipping mirror log LV %s", lv->name);
225 continue;
226 }
227 if (lv->status & MIRROR_IMAGE) {
228 lv_skipped = 1;
229 log_print("Skipping mirror image LV %s", lv->name);
230 continue;
231 }
232 if (lv->status & LOCKED) {
233 lv_skipped = 1;
234 log_print("Skipping locked LV %s", lv->name);
235 continue;
236 }
237 if (!_insert_pvmove_mirrors(cmd, lv_mirr, source_pvl, lv,
238 *lvs_changed))
239 return_NULL;
240 }
241
242 if (lv_name && !lv_found) {
243 log_error("Logical volume %s not found.", lv_name);
244 return NULL;
245 }
246
247 /* Is temporary mirror empty? */
248 if (!lv_mirr->le_count) {
249 if (lv_skipped)
250 log_error("All data on source PV skipped. "
251 "It contains locked, hidden or "
252 "non-top level LVs only.");
253 log_error("No data to move for %s", vg->name);
254 return NULL;
255 }
256
257 if (!lv_add_mirrors(cmd, lv_mirr, 1, 1, 0, 0, log_count,
258 allocatable_pvs, alloc, MIRROR_BY_SEG)) {
259 log_error("Failed to convert pvmove LV to mirrored");
260 return_NULL;
261 }
262
263 if (!split_parent_segments_for_layer(cmd, lv_mirr)) {
264 log_error("Failed to split segments being moved");
265 return_NULL;
266 }
267
268 return lv_mirr;
269 }
270
271 static int _activate_lv(struct cmd_context *cmd, struct logical_volume *lv_mirr,
272 unsigned exclusive)
273 {
274 int r = 0;
275
276 if (exclusive)
277 r = activate_lv_excl(cmd, lv_mirr);
278 else
279 r = activate_lv(cmd, lv_mirr);
280
281 if (!r)
282 stack;
283
284 return r;
285 }
286
287 static int _detach_pvmove_mirror(struct cmd_context *cmd,
288 struct logical_volume *lv_mirr)
289 {
290 struct dm_list lvs_completed;
291 struct lv_list *lvl;
292
293 /* Update metadata to remove mirror segments and break dependencies */
294 dm_list_init(&lvs_completed);
295 if (!lv_remove_mirrors(cmd, lv_mirr, 1, 0, NULL, NULL, PVMOVE) ||
296 !remove_layers_for_segments_all(cmd, lv_mirr, PVMOVE,
297 &lvs_completed)) {
298 return 0;
299 }
300
301 dm_list_iterate_items(lvl, &lvs_completed)
302 /* FIXME Assumes only one pvmove at a time! */
303 lvl->lv->status &= ~LOCKED;
304
305 return 1;
306 }
307
308 static int _suspend_lvs(struct cmd_context *cmd, unsigned first_time,
309 struct logical_volume *lv_mirr,
310 struct dm_list *lvs_changed,
311 struct volume_group *vg_to_revert)
312 {
313 /*
314 * Suspend lvs_changed the first time.
315 * Suspend mirrors on subsequent calls.
316 */
317 if (first_time) {
318 if (!suspend_lvs(cmd, lvs_changed, vg_to_revert))
319 return_0;
320 } else if (!suspend_lv(cmd, lv_mirr)) {
321 if (vg_to_revert)
322 vg_revert(vg_to_revert);
323 return_0;
324 }
325
326 return 1;
327 }
328
329 static int _resume_lvs(struct cmd_context *cmd, unsigned first_time,
330 struct logical_volume *lv_mirr,
331 struct dm_list *lvs_changed)
332 {
333 /*
334 * Suspend lvs_changed the first time.
335 * Suspend mirrors on subsequent calls.
336 */
337
338 if (first_time) {
339 if (!resume_lvs(cmd, lvs_changed)) {
340 log_error("Unable to resume logical volumes");
341 return 0;
342 }
343 } else if (!resume_lv(cmd, lv_mirr)) {
344 log_error("Unable to reactivate logical volume \"%s\"",
345 lv_mirr->name);
346 return 0;
347 }
348
349 return 1;
350 }
351
352 /*
353 * Called to set up initial pvmove LV and to advance the mirror
354 * to successive sections of it.
355 * (Not called after the last section completes.)
356 */
357 static int _update_metadata(struct cmd_context *cmd, struct volume_group *vg,
358 struct logical_volume *lv_mirr,
359 struct dm_list *lvs_changed, unsigned flags)
360 {
361 unsigned exclusive = _pvmove_is_exclusive(cmd, vg);
362 unsigned first_time = (flags & PVMOVE_FIRST_TIME) ? 1 : 0;
363 int r = 0;
364
365 log_verbose("Updating volume group metadata");
366 if (!vg_write(vg)) {
367 log_error("ABORTING: Volume group metadata update failed.");
368 return 0;
369 }
370
371 if (!_suspend_lvs(cmd, first_time, lv_mirr, lvs_changed, vg)) {
372 log_error("ABORTING: Volume group metadata update failed. (first_time: %d)", first_time);
373 /* FIXME Add a recovery path for first time too. */
374 if (!first_time && !revert_lv(cmd, lv_mirr))
375 stack;
376 return 0;
377 }
378
379 /* Commit on-disk metadata */
380 if (!vg_commit(vg)) {
381 log_error("ABORTING: Volume group metadata update failed.");
382 if (!_resume_lvs(cmd, first_time, lv_mirr, lvs_changed))
383 stack;
384 if (!first_time && !revert_lv(cmd, lv_mirr))
385 stack;
386 return 0;
387 }
388
389 /* Activate the temporary mirror LV */
390 /* Only the first mirror segment gets activated as a mirror */
391 /* FIXME: Add option to use a log */
392 if (first_time) {
393 if (!_activate_lv(cmd, lv_mirr, exclusive)) {
394 if (test_mode()) {
395 r = 1;
396 goto out;
397 }
398
399 /*
400 * FIXME Run --abort internally here.
401 */
402 log_error("ABORTING: Temporary pvmove mirror activation failed. Run pvmove --abort.");
403 goto_out;
404 }
405 }
406
407 r = 1;
408
409 out:
410 if (!_resume_lvs(cmd, first_time, lv_mirr, lvs_changed))
411 r = 0;
412
413 if (r)
414 backup(vg);
415
416 return r;
417 }
418
419 static int _set_up_pvmove(struct cmd_context *cmd, const char *pv_name,
420 int argc, char **argv)
421 {
422 const char *lv_name = NULL;
423 char *pv_name_arg;
424 struct volume_group *vg;
425 struct dm_list *source_pvl;
426 struct dm_list *allocatable_pvs;
427 alloc_policy_t alloc;
428 struct dm_list *lvs_changed;
429 struct physical_volume *pv;
430 struct logical_volume *lv_mirr;
431 unsigned first_time = 1;
432 unsigned exclusive;
433 int r = ECMD_FAILED;
434
435 pv_name_arg = argv[0];
436 argc--;
437 argv++;
438
439 /* Find PV (in VG) */
440 if (!(pv = find_pv_by_name(cmd, pv_name))) {
441 stack;
442 return EINVALID_CMD_LINE;
443 }
444
445 if (arg_count(cmd, name_ARG)) {
446 if (!(lv_name = _extract_lvname(cmd, pv_vg_name(pv),
447 arg_value(cmd, name_ARG)))) {
448 stack;
449 free_pv_fid(pv);
450 return EINVALID_CMD_LINE;
451 }
452
453 if (!validate_name(lv_name)) {
454 log_error("Logical volume name %s is invalid", lv_name);
455 free_pv_fid(pv);
456 return EINVALID_CMD_LINE;
457 }
458 }
459
460 /* Read VG */
461 log_verbose("Finding volume group \"%s\"", pv_vg_name(pv));
462
463 vg = _get_vg(cmd, pv_vg_name(pv));
464 if (vg_read_error(vg)) {
465 release_vg(vg);
466 stack;
467 return ECMD_FAILED;
468 }
469
470 exclusive = _pvmove_is_exclusive(cmd, vg);
471
472 if ((lv_mirr = find_pvmove_lv(vg, pv_dev(pv), PVMOVE))) {
473 log_print("Detected pvmove in progress for %s", pv_name);
474 if (argc || lv_name)
475 log_error("Ignoring remaining command line arguments");
476
477 if (!(lvs_changed = lvs_using_lv(cmd, vg, lv_mirr))) {
478 log_error("ABORTING: Failed to generate list of moving LVs");
479 goto out;
480 }
481
482 /* Ensure mirror LV is active */
483 if (!_activate_lv(cmd, lv_mirr, exclusive)) {
484 log_error("ABORTING: Temporary mirror activation failed.");
485 goto out;
486 }
487
488 first_time = 0;
489 } else {
490 /* Determine PE ranges to be moved */
491 if (!(source_pvl = create_pv_list(cmd->mem, vg, 1,
492 &pv_name_arg, 0)))
493 goto_out;
494
495 alloc = (alloc_policy_t) arg_uint_value(cmd, alloc_ARG, ALLOC_INHERIT);
496 if (alloc == ALLOC_INHERIT)
497 alloc = vg->alloc;
498
499 /* Get PVs we can use for allocation */
500 if (!(allocatable_pvs = _get_allocatable_pvs(cmd, argc, argv,
501 vg, pv, alloc)))
502 goto_out;
503
504 if (!archive(vg))
505 goto_out;
506
507 if (!(lv_mirr = _set_up_pvmove_lv(cmd, vg, source_pvl, lv_name,
508 allocatable_pvs, alloc,
509 &lvs_changed)))
510 goto_out;
511 }
512
513 /* Lock lvs_changed and activate (with old metadata) */
514 if (!activate_lvs(cmd, lvs_changed, exclusive))
515 goto_out;
516
517 /* FIXME Presence of a mirror once set PVMOVE - now remove associated logic */
518 /* init_pvmove(1); */
519 /* vg->status |= PVMOVE; */
520
521 if (first_time) {
522 if (!_update_metadata
523 (cmd, vg, lv_mirr, lvs_changed, PVMOVE_FIRST_TIME))
524 goto_out;
525 }
526
527 /* LVs are all in status LOCKED */
528 r = ECMD_PROCESSED;
529 out:
530 free_pv_fid(pv);
531 unlock_and_release_vg(cmd, vg, pv_vg_name(pv));
532 return r;
533 }
534
535 static int _finish_pvmove(struct cmd_context *cmd, struct volume_group *vg,
536 struct logical_volume *lv_mirr,
537 struct dm_list *lvs_changed)
538 {
539 int r = 1;
540
541 if (!dm_list_empty(lvs_changed) &&
542 (!_detach_pvmove_mirror(cmd, lv_mirr) ||
543 !replace_lv_with_error_segment(lv_mirr))) {
544 log_error("ABORTING: Removal of temporary mirror failed");
545 return 0;
546 }
547
548 /* Store metadata without dependencies on mirror segments */
549 if (!vg_write(vg)) {
550 log_error("ABORTING: Failed to write new data locations "
551 "to disk.");
552 return 0;
553 }
554
555 /* Suspend LVs changed (implicitly suspends lv_mirr) */
556 if (!suspend_lvs(cmd, lvs_changed, vg)) {
557 log_error("ABORTING: Locking LVs to remove temporary mirror failed");
558 if (!revert_lv(cmd, lv_mirr))
559 stack;
560 return 0;
561 }
562
563 /* Store metadata without dependencies on mirror segments */
564 if (!vg_commit(vg)) {
565 log_error("ABORTING: Failed to write new data locations "
566 "to disk.");
567 if (!revert_lv(cmd, lv_mirr))
568 stack;
569 if (!revert_lvs(cmd, lvs_changed))
570 stack;
571 return 0;
572 }
573
574 /* Release mirror LV. (No pending I/O because it's been suspended.) */
575 if (!resume_lv(cmd, lv_mirr)) {
576 log_error("Unable to reactivate logical volume \"%s\"",
577 lv_mirr->name);
578 r = 0;
579 }
580
581 /* Unsuspend LVs */
582 if (!resume_lvs(cmd, lvs_changed))
583 stack;
584
585 /* Deactivate mirror LV */
586 if (!deactivate_lv(cmd, lv_mirr)) {
587 log_error("ABORTING: Unable to deactivate temporary logical "
588 "volume \"%s\"", lv_mirr->name);
589 r = 0;
590 }
591
592 log_verbose("Removing temporary pvmove LV");
593 if (!lv_remove(lv_mirr)) {
594 log_error("ABORTING: Removal of temporary pvmove LV failed");
595 return 0;
596 }
597
598 /* Store it on disks */
599 log_verbose("Writing out final volume group after pvmove");
600 if (!vg_write(vg) || !vg_commit(vg)) {
601 log_error("ABORTING: Failed to write new data locations "
602 "to disk.");
603 return 0;
604 }
605
606 /* FIXME backup positioning */
607 backup(vg);
608
609 return r;
610 }
611
612 static struct volume_group *_get_move_vg(struct cmd_context *cmd,
613 const char *name,
614 const char *uuid __attribute__((unused)))
615 {
616 struct physical_volume *pv;
617 struct volume_group *vg;
618
619 /* Reread all metadata in case it got changed */
620 if (!(pv = find_pv_by_name(cmd, name))) {
621 log_error("ABORTING: Can't reread PV %s", name);
622 /* What more could we do here? */
623 return NULL;
624 }
625
626 vg = _get_vg(cmd, pv_vg_name(pv));
627 free_pv_fid(pv);
628
629 return vg;
630 }
631
632 static struct poll_functions _pvmove_fns = {
633 .get_copy_name_from_lv = get_pvmove_pvname_from_lv_mirr,
634 .get_copy_vg = _get_move_vg,
635 .get_copy_lv = find_pvmove_lv_from_pvname,
636 .poll_progress = poll_mirror_progress,
637 .update_metadata = _update_metadata,
638 .finish_copy = _finish_pvmove,
639 };
640
641 int pvmove_poll(struct cmd_context *cmd, const char *pv_name,
642 unsigned background)
643 {
644 if (test_mode())
645 return ECMD_PROCESSED;
646
647 return poll_daemon(cmd, pv_name, NULL, background, PVMOVE, &_pvmove_fns,
648 "Moved");
649 }
650
651 int pvmove(struct cmd_context *cmd, int argc, char **argv)
652 {
653 char *pv_name = NULL;
654 char *colon;
655 int ret;
656
657 /* dm raid1 target must be present in every case */
658 if (!_pvmove_target_present(cmd, 0)) {
659 log_error("Required device-mapper target(s) not "
660 "detected in your kernel");
661 return ECMD_FAILED;
662 }
663
664 if (argc) {
665 if (!(pv_name = dm_pool_strdup(cmd->mem, argv[0]))) {
666 log_error("Failed to clone PV name");
667 return ECMD_FAILED;
668 }
669
670 dm_unescape_colons_and_at_signs(pv_name, &colon, NULL);
671
672 /* Drop any PE lists from PV name */
673 if (colon)
674 *colon = '\0';
675
676 if (!arg_count(cmd, abort_ARG) &&
677 (ret = _set_up_pvmove(cmd, pv_name, argc, argv)) !=
678 ECMD_PROCESSED) {
679 stack;
680 return ret;
681 }
682 }
683
684 return pvmove_poll(cmd, pv_name, arg_is_set(cmd, background_ARG));
685 }
This page took 0.068634 seconds and 4 git commands to generate.