Home | History | Annotate | Line # | Download | only in tools
pvmove.c revision 1.1
      1 /*	$NetBSD: pvmove.c,v 1.1 2008/12/22 00:19:07 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(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 	struct volume_group *vg;
     95 
     96 	dev_close_all();
     97 
     98 	if (!(vg = vg_lock_and_read(cmd, vgname, NULL, LCK_VG_WRITE,
     99 				    CLUSTERED | EXPORTED_VG | LVM_WRITE,
    100 				    CORRECT_INCONSISTENT | FAIL_INCONSISTENT)))
    101 		 return NULL;
    102 
    103 	return vg;
    104 }
    105 
    106 /* Create list of PVs for allocation of replacement extents */
    107 static struct dm_list *_get_allocatable_pvs(struct cmd_context *cmd, int argc,
    108 					 char **argv, struct volume_group *vg,
    109 					 struct physical_volume *pv,
    110 					 alloc_policy_t alloc)
    111 {
    112 	struct dm_list *allocatable_pvs, *pvht, *pvh;
    113 	struct pv_list *pvl;
    114 
    115 	if (argc)
    116 		allocatable_pvs = create_pv_list(cmd->mem, vg, argc, argv, 1);
    117 	else
    118 		allocatable_pvs = clone_pv_list(cmd->mem, &vg->pvs);
    119 
    120 	if (!allocatable_pvs)
    121 		return_NULL;
    122 
    123 	dm_list_iterate_safe(pvh, pvht, allocatable_pvs) {
    124 		pvl = dm_list_item(pvh, struct pv_list);
    125 
    126 		/* Don't allocate onto the PV we're clearing! */
    127 		if ((alloc != ALLOC_ANYWHERE) && (pvl->pv->dev == pv_dev(pv))) {
    128 			dm_list_del(&pvl->list);
    129 			continue;
    130 		}
    131 
    132 		/* Remove PV if full */
    133 		if ((pvl->pv->pe_count == pvl->pv->pe_alloc_count))
    134 			dm_list_del(&pvl->list);
    135 	}
    136 
    137 	if (dm_list_empty(allocatable_pvs)) {
    138 		log_error("No extents available for allocation");
    139 		return NULL;
    140 	}
    141 
    142 	return allocatable_pvs;
    143 }
    144 
    145 /*
    146  * Replace any LV segments on given PV with temporary mirror.
    147  * Returns list of LVs changed.
    148  */
    149 static int _insert_pvmove_mirrors(struct cmd_context *cmd,
    150 				  struct logical_volume *lv_mirr,
    151 				  struct dm_list *source_pvl,
    152 				  struct logical_volume *lv,
    153 				  struct dm_list *lvs_changed)
    154 
    155 {
    156 	struct pv_list *pvl;
    157 	uint32_t prev_le_count;
    158 
    159 	/* Only 1 PV may feature in source_pvl */
    160 	pvl = dm_list_item(source_pvl->n, struct pv_list);
    161 
    162 	prev_le_count = lv_mirr->le_count;
    163 	if (!insert_layer_for_segments_on_pv(cmd, lv, lv_mirr, PVMOVE,
    164 					     pvl, lvs_changed))
    165 		return_0;
    166 
    167 	/* check if layer was inserted */
    168 	if (lv_mirr->le_count - prev_le_count) {
    169 		lv->status |= LOCKED;
    170 
    171 		log_verbose("Moving %u extents of logical volume %s/%s",
    172 			    lv_mirr->le_count - prev_le_count,
    173 			    lv->vg->name, lv->name);
    174 	}
    175 
    176 	return 1;
    177 }
    178 
    179 /* Create new LV with mirror segments for the required copies */
    180 static struct logical_volume *_set_up_pvmove_lv(struct cmd_context *cmd,
    181 						struct volume_group *vg,
    182 						struct dm_list *source_pvl,
    183 						const char *lv_name,
    184 						struct dm_list *allocatable_pvs,
    185 						alloc_policy_t alloc,
    186 						struct dm_list **lvs_changed)
    187 {
    188 	struct logical_volume *lv_mirr, *lv;
    189 	struct lv_list *lvl;
    190 	uint32_t log_count = 0;
    191 	int lv_found = 0;
    192 
    193 	/* FIXME Cope with non-contiguous => splitting existing segments */
    194 	if (!(lv_mirr = lv_create_empty("pvmove%d", NULL,
    195 					LVM_READ | LVM_WRITE,
    196 					ALLOC_CONTIGUOUS, 0, vg))) {
    197 		log_error("Creation of temporary pvmove LV failed");
    198 		return NULL;
    199 	}
    200 
    201 	lv_mirr->status |= (PVMOVE | LOCKED);
    202 
    203 	if (!(*lvs_changed = dm_pool_alloc(cmd->mem, sizeof(**lvs_changed)))) {
    204 		log_error("lvs_changed list struct allocation failed");
    205 		return NULL;
    206 	}
    207 
    208 	dm_list_init(*lvs_changed);
    209 
    210 	/* Find segments to be moved and set up mirrors */
    211 	dm_list_iterate_items(lvl, &vg->lvs) {
    212 		lv = lvl->lv;
    213 		if ((lv == lv_mirr))
    214 			continue;
    215 		if (lv_name) {
    216 			if (strcmp(lv->name, lv_name))
    217 				continue;
    218 			lv_found = 1;
    219 		}
    220 		if (lv_is_origin(lv) || lv_is_cow(lv)) {
    221 			log_print("Skipping snapshot-related LV %s", lv->name);
    222 			continue;
    223 		}
    224 		if (lv->status & MIRRORED) {
    225 			log_print("Skipping mirror LV %s", lv->name);
    226 			continue;
    227 		}
    228 		if (lv->status & MIRROR_LOG) {
    229 			log_print("Skipping mirror log LV %s", lv->name);
    230 			continue;
    231 		}
    232 		if (lv->status & MIRROR_IMAGE) {
    233 			log_print("Skipping mirror image LV %s", lv->name);
    234 			continue;
    235 		}
    236 		if (lv->status & LOCKED) {
    237 			log_print("Skipping locked LV %s", lv->name);
    238 			continue;
    239 		}
    240 		if (!_insert_pvmove_mirrors(cmd, lv_mirr, source_pvl, lv,
    241 					    *lvs_changed))
    242 			return_NULL;
    243 	}
    244 
    245 	if (lv_name && !lv_found) {
    246 		log_error("Logical volume %s not found.", lv_name);
    247 		return NULL;
    248 	}
    249 
    250 	/* Is temporary mirror empty? */
    251 	if (!lv_mirr->le_count) {
    252 		log_error("No data to move for %s", vg->name);
    253 		return NULL;
    254 	}
    255 
    256 	if (!lv_add_mirrors(cmd, lv_mirr, 1, 1, 0, log_count,
    257 			    allocatable_pvs, alloc, MIRROR_BY_SEG)) {
    258 		log_error("Failed to convert pvmove LV to mirrored");
    259 		return_NULL;
    260 	}
    261 
    262 	if (!split_parent_segments_for_layer(cmd, lv_mirr)) {
    263 		log_error("Failed to split segments being moved");
    264 		return_NULL;
    265 	}
    266 
    267 	return lv_mirr;
    268 }
    269 
    270 static int _activate_lv(struct cmd_context *cmd, struct logical_volume *lv_mirr,
    271 			unsigned exclusive)
    272 {
    273 	if (exclusive)
    274 		return activate_lv_excl(cmd, lv_mirr);
    275 
    276 	return activate_lv(cmd, lv_mirr);
    277 }
    278 
    279 static int _update_metadata(struct cmd_context *cmd, struct volume_group *vg,
    280 			    struct logical_volume *lv_mirr,
    281 			    struct dm_list *lvs_changed, unsigned flags)
    282 {
    283 	unsigned exclusive = _pvmove_is_exclusive(cmd, vg);
    284 	unsigned first_time = (flags & PVMOVE_FIRST_TIME) ? 1 : 0;
    285 
    286 	log_verbose("Updating volume group metadata");
    287 	if (!vg_write(vg)) {
    288 		log_error("ABORTING: Volume group metadata update failed.");
    289 		return 0;
    290 	}
    291 
    292 	backup(vg);
    293 
    294 	/* Suspend lvs_changed */
    295 	if (!suspend_lvs(cmd, lvs_changed))
    296 		return_0;
    297 
    298 	/* Suspend mirrors on subsequent calls */
    299 	if (!first_time) {
    300 		if (!suspend_lv(cmd, lv_mirr)) {
    301 			stack;
    302 			resume_lvs(cmd, lvs_changed);
    303 			vg_revert(vg);
    304 			return 0;
    305 		}
    306 	}
    307 
    308 	/* Commit on-disk metadata */
    309 	if (!vg_commit(vg)) {
    310 		log_error("ABORTING: Volume group metadata update failed.");
    311 		if (!first_time)
    312 			resume_lv(cmd, lv_mirr);
    313 		resume_lvs(cmd, lvs_changed);
    314 		return 0;
    315 	}
    316 
    317 	/* Activate the temporary mirror LV */
    318 	/* Only the first mirror segment gets activated as a mirror */
    319 	/* FIXME: Add option to use a log */
    320 	if (first_time) {
    321 		if (!_activate_lv(cmd, lv_mirr, exclusive)) {
    322 			if (!test_mode())
    323 				log_error("ABORTING: Temporary mirror "
    324 					  "activation failed.  "
    325 					  "Run pvmove --abort.");
    326 			/* FIXME Resume using *original* metadata here! */
    327 			resume_lvs(cmd, lvs_changed);
    328 			return 0;
    329 		}
    330 	} else if (!resume_lv(cmd, lv_mirr)) {
    331 		log_error("Unable to reactivate logical volume \"%s\"",
    332 			  lv_mirr->name);
    333 		resume_lvs(cmd, lvs_changed);
    334 		return 0;
    335 	}
    336 
    337 	/* Unsuspend LVs */
    338 	if (!resume_lvs(cmd, lvs_changed)) {
    339 		log_error("Unable to resume logical volumes");
    340 		return 0;
    341 	}
    342 
    343 	return 1;
    344 }
    345 
    346 static int _set_up_pvmove(struct cmd_context *cmd, const char *pv_name,
    347 			  int argc, char **argv)
    348 {
    349 	const char *lv_name = NULL;
    350 	char *pv_name_arg;
    351 	struct volume_group *vg;
    352 	struct dm_list *source_pvl;
    353 	struct dm_list *allocatable_pvs;
    354 	alloc_policy_t alloc;
    355 	struct dm_list *lvs_changed;
    356 	struct physical_volume *pv;
    357 	struct logical_volume *lv_mirr;
    358 	unsigned first_time = 1;
    359 	unsigned exclusive;
    360 
    361 	pv_name_arg = argv[0];
    362 	argc--;
    363 	argv++;
    364 
    365 	/* Find PV (in VG) */
    366 	if (!(pv = find_pv_by_name(cmd, pv_name))) {
    367 		stack;
    368 		return EINVALID_CMD_LINE;
    369 	}
    370 
    371 	if (arg_count(cmd, name_ARG)) {
    372 		if (!(lv_name = _extract_lvname(cmd, pv_vg_name(pv),
    373 						arg_value(cmd, name_ARG)))) {
    374 			stack;
    375 			return EINVALID_CMD_LINE;
    376 		}
    377 
    378 		if (!validate_name(lv_name)) {
    379 			log_error("Logical volume name %s is invalid", lv_name);
    380 			return EINVALID_CMD_LINE;
    381 		}
    382 	}
    383 
    384 	/* Read VG */
    385 	log_verbose("Finding volume group \"%s\"", pv_vg_name(pv));
    386 
    387 	if (!(vg = _get_vg(cmd, pv_vg_name(pv)))) {
    388 		stack;
    389 		return ECMD_FAILED;
    390 	}
    391 
    392 	exclusive = _pvmove_is_exclusive(cmd, vg);
    393 
    394 	if ((lv_mirr = find_pvmove_lv(vg, pv_dev(pv), PVMOVE))) {
    395 		log_print("Detected pvmove in progress for %s", pv_name);
    396 		if (argc || lv_name)
    397 			log_error("Ignoring remaining command line arguments");
    398 
    399 		if (!(lvs_changed = lvs_using_lv(cmd, vg, lv_mirr))) {
    400 			log_error
    401 			    ("ABORTING: Failed to generate list of moving LVs");
    402 			unlock_vg(cmd, pv_vg_name(pv));
    403 			return ECMD_FAILED;
    404 		}
    405 
    406 		/* Ensure mirror LV is active */
    407 		if (!_activate_lv(cmd, lv_mirr, exclusive)) {
    408 			log_error
    409 			    ("ABORTING: Temporary mirror activation failed.");
    410 			unlock_vg(cmd, pv_vg_name(pv));
    411 			return ECMD_FAILED;
    412 		}
    413 
    414 		first_time = 0;
    415 	} else {
    416 		/* Determine PE ranges to be moved */
    417 		if (!(source_pvl = create_pv_list(cmd->mem, vg, 1,
    418 						  &pv_name_arg, 0))) {
    419 			stack;
    420 			unlock_vg(cmd, pv_vg_name(pv));
    421 			return ECMD_FAILED;
    422 		}
    423 
    424 		alloc = arg_uint_value(cmd, alloc_ARG, ALLOC_INHERIT);
    425 		if (alloc == ALLOC_INHERIT)
    426 			alloc = vg->alloc;
    427 
    428 		/* Get PVs we can use for allocation */
    429 		if (!(allocatable_pvs = _get_allocatable_pvs(cmd, argc, argv,
    430 							     vg, pv, alloc))) {
    431 			stack;
    432 			unlock_vg(cmd, pv_vg_name(pv));
    433 			return ECMD_FAILED;
    434 		}
    435 
    436 		if (!archive(vg)) {
    437 			unlock_vg(cmd, pv_vg_name(pv));
    438 			stack;
    439 			return ECMD_FAILED;
    440 		}
    441 
    442 		if (!(lv_mirr = _set_up_pvmove_lv(cmd, vg, source_pvl, lv_name,
    443 						  allocatable_pvs, alloc,
    444 						  &lvs_changed))) {
    445 			stack;
    446 			unlock_vg(cmd, pv_vg_name(pv));
    447 			return ECMD_FAILED;
    448 		}
    449 	}
    450 
    451 	/* Lock lvs_changed and activate (with old metadata) */
    452 	if (!activate_lvs(cmd, lvs_changed, exclusive)) {
    453 		stack;
    454 		unlock_vg(cmd, pv_vg_name(pv));
    455 		return ECMD_FAILED;
    456 	}
    457 
    458 	/* FIXME Presence of a mirror once set PVMOVE - now remove associated logic */
    459 	/* init_pvmove(1); */
    460 	/* vg->status |= PVMOVE; */
    461 
    462 	if (first_time) {
    463 		if (!_update_metadata
    464 		    (cmd, vg, lv_mirr, lvs_changed, PVMOVE_FIRST_TIME)) {
    465 			stack;
    466 			unlock_vg(cmd, pv_vg_name(pv));
    467 			return ECMD_FAILED;
    468 		}
    469 	}
    470 
    471 	/* LVs are all in status LOCKED */
    472 	unlock_vg(cmd, pv_vg_name(pv));
    473 
    474 	return ECMD_PROCESSED;
    475 }
    476 
    477 static int _finish_pvmove(struct cmd_context *cmd, struct volume_group *vg,
    478 			  struct logical_volume *lv_mirr,
    479 			  struct dm_list *lvs_changed)
    480 {
    481 	int r = 1;
    482 	struct dm_list lvs_completed;
    483 	struct lv_list *lvl;
    484 
    485 	/* Update metadata to remove mirror segments and break dependencies */
    486 	dm_list_init(&lvs_completed);
    487 	if (!lv_remove_mirrors(cmd, lv_mirr, 1, 0, NULL, PVMOVE) ||
    488 	    !remove_layers_for_segments_all(cmd, lv_mirr, PVMOVE,
    489 					    &lvs_completed)) {
    490 		log_error("ABORTING: Removal of temporary mirror failed");
    491 		return 0;
    492 	}
    493 
    494 	dm_list_iterate_items(lvl, &lvs_completed)
    495 		/* FIXME Assumes only one pvmove at a time! */
    496 		lvl->lv->status &= ~LOCKED;
    497 
    498 	/* Store metadata without dependencies on mirror segments */
    499 	if (!vg_write(vg)) {
    500 		log_error("ABORTING: Failed to write new data locations "
    501 			  "to disk.");
    502 		return 0;
    503 	}
    504 
    505 	/* Suspend LVs changed */
    506 	if (!suspend_lvs(cmd, lvs_changed)) {
    507 		log_error("Locking LVs to remove temporary mirror failed");
    508 		r = 0;
    509 	}
    510 
    511 	/* Suspend mirror LV to flush pending I/O */
    512 	if (!suspend_lv(cmd, lv_mirr)) {
    513 		log_error("Suspension of temporary mirror LV failed");
    514 		r = 0;
    515 	}
    516 
    517 	/* Store metadata without dependencies on mirror segments */
    518 	if (!vg_commit(vg)) {
    519 		log_error("ABORTING: Failed to write new data locations "
    520 			  "to disk.");
    521 		vg_revert(vg);
    522 		resume_lv(cmd, lv_mirr);
    523 		resume_lvs(cmd, lvs_changed);
    524 		return 0;
    525 	}
    526 
    527 	/* Release mirror LV.  (No pending I/O because it's been suspended.) */
    528 	if (!resume_lv(cmd, lv_mirr)) {
    529 		log_error("Unable to reactivate logical volume \"%s\"",
    530 			  lv_mirr->name);
    531 		r = 0;
    532 	}
    533 
    534 	/* Unsuspend LVs */
    535 	resume_lvs(cmd, lvs_changed);
    536 
    537 	/* Deactivate mirror LV */
    538 	if (!deactivate_lv(cmd, lv_mirr)) {
    539 		log_error("ABORTING: Unable to deactivate temporary logical "
    540 			  "volume \"%s\"", lv_mirr->name);
    541 		r = 0;
    542 	}
    543 
    544 	log_verbose("Removing temporary pvmove LV");
    545 	if (!lv_remove(lv_mirr)) {
    546 		log_error("ABORTING: Removal of temporary pvmove LV failed");
    547 		return 0;
    548 	}
    549 
    550 	/* Store it on disks */
    551 	log_verbose("Writing out final volume group after pvmove");
    552 	if (!vg_write(vg) || !vg_commit(vg)) {
    553 		log_error("ABORTING: Failed to write new data locations "
    554 			  "to disk.");
    555 		return 0;
    556 	}
    557 
    558 	/* FIXME backup positioning */
    559 	backup(vg);
    560 
    561 	return r;
    562 }
    563 
    564 static struct volume_group *_get_move_vg(struct cmd_context *cmd,
    565 					 const char *name)
    566 {
    567 	struct physical_volume *pv;
    568 
    569 	/* Reread all metadata in case it got changed */
    570 	if (!(pv = find_pv_by_name(cmd, name))) {
    571 		log_error("ABORTING: Can't reread PV %s", name);
    572 		/* What more could we do here? */
    573 		return NULL;
    574 	}
    575 
    576 	return _get_vg(cmd, pv_vg_name(pv));
    577 }
    578 
    579 static struct poll_functions _pvmove_fns = {
    580 	.get_copy_name_from_lv = get_pvmove_pvname_from_lv_mirr,
    581 	.get_copy_vg = _get_move_vg,
    582 	.get_copy_lv = find_pvmove_lv_from_pvname,
    583 	.update_metadata = _update_metadata,
    584 	.finish_copy = _finish_pvmove,
    585 };
    586 
    587 int pvmove_poll(struct cmd_context *cmd, const char *pv_name,
    588 		unsigned background)
    589 {
    590 	return poll_daemon(cmd, pv_name, background, PVMOVE, &_pvmove_fns,
    591 			   "Moved");
    592 }
    593 
    594 int pvmove(struct cmd_context *cmd, int argc, char **argv)
    595 {
    596 	char *pv_name = NULL;
    597 	char *colon;
    598 	int ret;
    599 
    600 	/* dm raid1 target must be present in every case */
    601 	if (!_pvmove_target_present(cmd, 0)) {
    602 		log_error("Required device-mapper target(s) not "
    603 			  "detected in your kernel");
    604 		return ECMD_FAILED;
    605 	}
    606 
    607 	if (argc) {
    608 		pv_name = argv[0];
    609 
    610 		/* Drop any PE lists from PV name */
    611 		if ((colon = strchr(pv_name, ':'))) {
    612 			if (!(pv_name = dm_pool_strndup(cmd->mem, pv_name,
    613 						     (unsigned) (colon -
    614 								 pv_name)))) {
    615 				log_error("Failed to clone PV name");
    616 				return ECMD_FAILED;
    617 			}
    618 		}
    619 
    620 		if (!arg_count(cmd, abort_ARG) &&
    621 		    (ret = _set_up_pvmove(cmd, pv_name, argc, argv)) !=
    622 		    ECMD_PROCESSED) {
    623 			stack;
    624 			return ret;
    625 		}
    626 	}
    627 
    628 	return pvmove_poll(cmd, pv_name,
    629 			   arg_count(cmd, background_ARG) ? 1U : 0);
    630 }
    631