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