Home | History | Annotate | Line # | Download | only in tools
vgsplit.c revision 1.1.1.2
      1 /*	$NetBSD: vgsplit.c,v 1.1.1.2 2009/12/02 00:25:46 haad Exp $	*/
      2 
      3 /*
      4  * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
      5  * Copyright (C) 2004-2009 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 
     20 /* FIXME Why not (lv->vg == vg) ? */
     21 static int _lv_is_in_vg(struct volume_group *vg, struct logical_volume *lv)
     22 {
     23 	struct lv_list *lvl;
     24 
     25 	dm_list_iterate_items(lvl, &vg->lvs)
     26 		if (lv == lvl->lv)
     27 			 return 1;
     28 
     29 	return 0;
     30 }
     31 
     32 static int _move_one_lv(struct volume_group *vg_from,
     33 			 struct volume_group *vg_to,
     34 			 struct dm_list *lvh)
     35 {
     36 	struct logical_volume *lv = dm_list_item(lvh, struct lv_list)->lv;
     37 
     38 	dm_list_move(&vg_to->lvs, lvh);
     39 
     40 	if (lv_is_active(lv)) {
     41 		log_error("Logical volume \"%s\" must be inactive", lv->name);
     42 		return 0;
     43 	}
     44 
     45 	return 1;
     46 }
     47 
     48 static int _move_lvs(struct volume_group *vg_from, struct volume_group *vg_to)
     49 {
     50 	struct dm_list *lvh, *lvht;
     51 	struct logical_volume *lv;
     52 	struct lv_segment *seg;
     53 	struct physical_volume *pv;
     54 	struct volume_group *vg_with;
     55 	unsigned s;
     56 
     57 	dm_list_iterate_safe(lvh, lvht, &vg_from->lvs) {
     58 		lv = dm_list_item(lvh, struct lv_list)->lv;
     59 
     60 		if ((lv->status & SNAPSHOT))
     61 			continue;
     62 
     63 		if ((lv->status & MIRRORED))
     64 			continue;
     65 
     66 		/* Ensure all the PVs used by this LV remain in the same */
     67 		/* VG as each other */
     68 		vg_with = NULL;
     69 		dm_list_iterate_items(seg, &lv->segments) {
     70 			for (s = 0; s < seg->area_count; s++) {
     71 				/* FIXME Check AREA_LV too */
     72 				if (seg_type(seg, s) != AREA_PV)
     73 					continue;
     74 
     75 				pv = seg_pv(seg, s);
     76 				if (vg_with) {
     77 					if (!pv_is_in_vg(vg_with, pv)) {
     78 						log_error("Can't split Logical "
     79 							  "Volume %s between "
     80 							  "two Volume Groups",
     81 							  lv->name);
     82 						return 0;
     83 					}
     84 					continue;
     85 				}
     86 
     87 				if (pv_is_in_vg(vg_from, pv)) {
     88 					vg_with = vg_from;
     89 					continue;
     90 				}
     91 				if (pv_is_in_vg(vg_to, pv)) {
     92 					vg_with = vg_to;
     93 					continue;
     94 				}
     95 				log_error("Physical Volume %s not found",
     96 					  pv_dev_name(pv));
     97 				return 0;
     98 			}
     99 
    100 		}
    101 
    102 		if (vg_with == vg_from)
    103 			continue;
    104 
    105 		/* Move this LV */
    106 		if (!_move_one_lv(vg_from, vg_to, lvh))
    107 			return_0;
    108 	}
    109 
    110 	/* FIXME Ensure no LVs contain segs pointing at LVs in the other VG */
    111 
    112 	return 1;
    113 }
    114 
    115 /*
    116  * Move the hidden / internal "snapshotN" LVs.from 'vg_from' to 'vg_to'.
    117  */
    118 static int _move_snapshots(struct volume_group *vg_from,
    119 			   struct volume_group *vg_to)
    120 {
    121 	struct dm_list *lvh, *lvht;
    122 	struct logical_volume *lv;
    123 	struct lv_segment *seg;
    124 	int cow_from = 0;
    125 	int origin_from = 0;
    126 
    127 	dm_list_iterate_safe(lvh, lvht, &vg_from->lvs) {
    128 		lv = dm_list_item(lvh, struct lv_list)->lv;
    129 
    130 		if (!(lv->status & SNAPSHOT))
    131 			continue;
    132 
    133 		dm_list_iterate_items(seg, &lv->segments) {
    134 			cow_from = _lv_is_in_vg(vg_from, seg->cow);
    135 			origin_from = _lv_is_in_vg(vg_from, seg->origin);
    136 
    137 			if (cow_from && origin_from)
    138 				continue;
    139 			if ((!cow_from && origin_from) ||
    140 			     (cow_from && !origin_from)) {
    141 				log_error("Can't split snapshot %s between"
    142 					  " two Volume Groups", seg->cow->name);
    143 				return 0;
    144 			}
    145 
    146 			/*
    147 			 * At this point, the cow and origin should already be
    148 			 * in vg_to.
    149 			 */
    150 			if (_lv_is_in_vg(vg_to, seg->cow) &&
    151 			    _lv_is_in_vg(vg_to, seg->origin)) {
    152 				if (!_move_one_lv(vg_from, vg_to, lvh))
    153 					return_0;
    154 			}
    155 		}
    156 
    157 	}
    158 
    159 	return 1;
    160 }
    161 
    162 static int _move_mirrors(struct volume_group *vg_from,
    163 			 struct volume_group *vg_to)
    164 {
    165 	struct dm_list *lvh, *lvht;
    166 	struct logical_volume *lv;
    167 	struct lv_segment *seg;
    168 	unsigned s, seg_in, log_in;
    169 
    170 	dm_list_iterate_safe(lvh, lvht, &vg_from->lvs) {
    171 		lv = dm_list_item(lvh, struct lv_list)->lv;
    172 
    173 		if (!(lv->status & MIRRORED))
    174 			continue;
    175 
    176 		seg = first_seg(lv);
    177 
    178 		seg_in = 0;
    179 		for (s = 0; s < seg->area_count; s++)
    180 			if (_lv_is_in_vg(vg_to, seg_lv(seg, s)))
    181 			    seg_in++;
    182 
    183 		log_in = (!seg->log_lv || _lv_is_in_vg(vg_to, seg->log_lv));
    184 
    185 		if ((seg_in && seg_in < seg->area_count) ||
    186 		    (seg_in && seg->log_lv && !log_in) ||
    187 		    (!seg_in && seg->log_lv && log_in)) {
    188 			log_error("Can't split mirror %s between "
    189 				  "two Volume Groups", lv->name);
    190 			return 0;
    191 		}
    192 
    193 		if (seg_in == seg->area_count && log_in) {
    194 			if (!_move_one_lv(vg_from, vg_to, lvh))
    195 				return_0;
    196 		}
    197 	}
    198 
    199 	return 1;
    200 }
    201 
    202 /*
    203  * Create or open the destination of the vgsplit operation.
    204  * Returns
    205  * - non-NULL: VG handle w/VG lock held
    206  * - NULL: no VG lock held
    207  */
    208 static struct volume_group *_vgsplit_to(struct cmd_context *cmd,
    209 					const char *vg_name_to,
    210 					int *existing_vg)
    211 {
    212 	struct volume_group *vg_to = NULL;
    213 
    214 	log_verbose("Checking for new volume group \"%s\"", vg_name_to);
    215 	/*
    216 	 * First try to create a new VG.  If we cannot create it,
    217 	 * and we get FAILED_EXIST (we will not be holding a lock),
    218 	 * a VG must already exist with this name.  We then try to
    219 	 * read the existing VG - the vgsplit will be into an existing VG.
    220 	 *
    221 	 * Otherwise, if the lock was successful, it must be the case that
    222 	 * we obtained a WRITE lock and could not find the vgname in the
    223 	 * system.  Thus, the split will be into a new VG.
    224 	 */
    225 	vg_to = vg_create(cmd, vg_name_to);
    226 	if (vg_read_error(vg_to) == FAILED_LOCKING) {
    227 		log_error("Can't get lock for %s", vg_name_to);
    228 		vg_release(vg_to);
    229 		return NULL;
    230 	}
    231 	if (vg_read_error(vg_to) == FAILED_EXIST) {
    232 		*existing_vg = 1;
    233 		vg_release(vg_to);
    234 		vg_to = vg_read_for_update(cmd, vg_name_to, NULL, 0);
    235 
    236 		if (vg_read_error(vg_to)) {
    237 			vg_release(vg_to);
    238 			stack;
    239 			return NULL;
    240 		}
    241 
    242 	} else if (vg_read_error(vg_to) == SUCCESS) {
    243 		*existing_vg = 0;
    244 	}
    245 	return vg_to;
    246 }
    247 
    248 /*
    249  * Open the source of the vgsplit operation.
    250  * Returns
    251  * - non-NULL: VG handle w/VG lock held
    252  * - NULL: no VG lock held
    253  */
    254 static struct volume_group *_vgsplit_from(struct cmd_context *cmd,
    255 					  const char *vg_name_from)
    256 {
    257 	struct volume_group *vg_from;
    258 
    259 	log_verbose("Checking for volume group \"%s\"", vg_name_from);
    260 
    261 	vg_from = vg_read_for_update(cmd, vg_name_from, NULL, 0);
    262 	if (vg_read_error(vg_from)) {
    263 		vg_release(vg_from);
    264 		return NULL;
    265 	}
    266 	return vg_from;
    267 }
    268 
    269 /*
    270  * Has the user given an option related to a new vg as the split destination?
    271  */
    272 static int new_vg_option_specified(struct cmd_context *cmd)
    273 {
    274 	return(arg_count(cmd, clustered_ARG) ||
    275 	       arg_count(cmd, alloc_ARG) ||
    276 	       arg_count(cmd, maxphysicalvolumes_ARG) ||
    277 	       arg_count(cmd, maxlogicalvolumes_ARG));
    278 }
    279 
    280 int vgsplit(struct cmd_context *cmd, int argc, char **argv)
    281 {
    282 	struct vgcreate_params vp_new;
    283 	struct vgcreate_params vp_def;
    284 	char *vg_name_from, *vg_name_to;
    285 	struct volume_group *vg_to = NULL, *vg_from = NULL;
    286 	int opt;
    287 	int existing_vg = 0;
    288 	int r = ECMD_FAILED;
    289 	const char *lv_name;
    290 	int lock_vg_from_first = 1;
    291 
    292 	if ((arg_count(cmd, name_ARG) + argc) < 3) {
    293 		log_error("Existing VG, new VG and either physical volumes "
    294 			  "or logical volume required.");
    295 		return EINVALID_CMD_LINE;
    296 	}
    297 
    298 	if (arg_count(cmd, name_ARG) && (argc > 2)) {
    299 		log_error("A logical volume name cannot be given with "
    300 			  "physical volumes.");
    301 		return ECMD_FAILED;
    302 	}
    303 
    304 	if (arg_count(cmd, name_ARG))
    305 		lv_name = arg_value(cmd, name_ARG);
    306 	else
    307 		lv_name = NULL;
    308 
    309 	vg_name_from = skip_dev_dir(cmd, argv[0], NULL);
    310 	vg_name_to = skip_dev_dir(cmd, argv[1], NULL);
    311 	argc -= 2;
    312 	argv += 2;
    313 
    314 	if (!strcmp(vg_name_to, vg_name_from)) {
    315 		log_error("Duplicate volume group name \"%s\"", vg_name_from);
    316 		return ECMD_FAILED;
    317 	}
    318 
    319 	if (strcmp(vg_name_to, vg_name_from) < 0)
    320 		lock_vg_from_first = 0;
    321 
    322 	if (lock_vg_from_first) {
    323 		vg_from = _vgsplit_from(cmd, vg_name_from);
    324 		if (!vg_from) {
    325 			stack;
    326 			return ECMD_FAILED;
    327 		}
    328 		/*
    329 		 * Set metadata format of original VG.
    330 		 * NOTE: We must set the format before calling vg_create()
    331 		 * since vg_create() calls the per-format constructor.
    332 		 */
    333 		cmd->fmt = vg_from->fid->fmt;
    334 
    335 		vg_to = _vgsplit_to(cmd, vg_name_to, &existing_vg);
    336 		if (!vg_to) {
    337 			unlock_and_release_vg(cmd, vg_from, vg_name_from);
    338 			stack;
    339 			return ECMD_FAILED;
    340 		}
    341 	} else {
    342 		vg_to = _vgsplit_to(cmd, vg_name_to, &existing_vg);
    343 		if (!vg_to) {
    344 			stack;
    345 			return ECMD_FAILED;
    346 		}
    347 		vg_from = _vgsplit_from(cmd, vg_name_from);
    348 		if (!vg_from) {
    349 			unlock_and_release_vg(cmd, vg_to, vg_name_to);
    350 			stack;
    351 			return ECMD_FAILED;
    352 		}
    353 
    354 		if (cmd->fmt != vg_from->fid->fmt) {
    355 			/* In this case we don't know the vg_from->fid->fmt */
    356 			log_error("Unable to set new VG metadata type based on "
    357 				  "source VG format - use -M option.");
    358 			goto bad;
    359 		}
    360 	}
    361 
    362 	if (existing_vg) {
    363 		if (new_vg_option_specified(cmd)) {
    364 			log_error("Volume group \"%s\" exists, but new VG "
    365 				    "option specified", vg_name_to);
    366 			goto bad;
    367 		}
    368 		if (!vgs_are_compatible(cmd, vg_from,vg_to))
    369 			goto_bad;
    370 	} else {
    371 		vgcreate_params_set_defaults(&vp_def, vg_from);
    372 		vp_def.vg_name = vg_name_to;
    373 		if (vgcreate_params_set_from_args(cmd, &vp_new, &vp_def)) {
    374 			r = EINVALID_CMD_LINE;
    375 			goto_bad;
    376 		}
    377 
    378 		if (vgcreate_params_validate(cmd, &vp_new)) {
    379 			r = EINVALID_CMD_LINE;
    380 			goto_bad;
    381 		}
    382 
    383 		if (!vg_set_extent_size(vg_to, vp_new.extent_size) ||
    384 		    !vg_set_max_lv(vg_to, vp_new.max_lv) ||
    385 		    !vg_set_max_pv(vg_to, vp_new.max_pv) ||
    386 		    !vg_set_alloc_policy(vg_to, vp_new.alloc) ||
    387 		    !vg_set_clustered(vg_to, vp_new.clustered))
    388 			goto_bad;
    389 	}
    390 
    391 	/* Archive vg_from before changing it */
    392 	if (!archive(vg_from))
    393 		goto_bad;
    394 
    395 	/* Move PVs across to new structure */
    396 	for (opt = 0; opt < argc; opt++) {
    397 		if (!move_pv(vg_from, vg_to, argv[opt]))
    398 			goto_bad;
    399 	}
    400 
    401 	/* If an LV given on the cmdline, move used_by PVs */
    402 	if (lv_name && !move_pvs_used_by_lv(vg_from, vg_to, lv_name))
    403 		goto_bad;
    404 
    405 	/* Move required LVs across, checking consistency */
    406 	if (!(_move_lvs(vg_from, vg_to)))
    407 		goto_bad;
    408 
    409 	/* FIXME Separate the 'move' from the 'validation' to fix dev stacks */
    410 	/* Move required mirrors across */
    411 	if (!(_move_mirrors(vg_from, vg_to)))
    412 		goto_bad;
    413 
    414 	/* Move required snapshots across */
    415 	if (!(_move_snapshots(vg_from, vg_to)))
    416 		goto_bad;
    417 
    418 	/* Split metadata areas and check if both vgs have at least one area */
    419 	if (!(vg_split_mdas(cmd, vg_from, vg_to)) && vg_from->pv_count) {
    420 		log_error("Cannot split: Nowhere to store metadata for new Volume Group");
    421 		goto bad;
    422 	}
    423 
    424 	/* Set proper name for all PVs in new VG */
    425 	if (!vg_rename(cmd, vg_to, vg_name_to))
    426 		goto_bad;
    427 
    428 	/* store it on disks */
    429 	log_verbose("Writing out updated volume groups");
    430 
    431 	/*
    432 	 * First, write out the new VG as EXPORTED.  We do this first in case
    433 	 * there is a crash - we will still have the new VG information, in an
    434 	 * exported state.  Recovery after this point would be removal of the
    435 	 * new VG and redoing the vgsplit.
    436 	 * FIXME: recover automatically or instruct the user?
    437 	 */
    438 	vg_to->status |= EXPORTED_VG;
    439 
    440 	if (!archive(vg_to))
    441 		goto_bad;
    442 
    443 	if (!vg_write(vg_to) || !vg_commit(vg_to))
    444 		goto_bad;
    445 
    446 	backup(vg_to);
    447 
    448 	/*
    449 	 * Next, write out the updated old VG.  If we crash after this point,
    450 	 * recovery is a vgimport on the new VG.
    451 	 * FIXME: recover automatically or instruct the user?
    452 	 */
    453 	if (vg_from->pv_count) {
    454 		if (!vg_write(vg_from) || !vg_commit(vg_from))
    455 			goto_bad;
    456 
    457 		backup(vg_from);
    458 	}
    459 
    460 	/*
    461 	 * Finally, remove the EXPORTED flag from the new VG and write it out.
    462 	 */
    463 	if (!test_mode()) {
    464 		vg_release(vg_to);
    465 		vg_to = vg_read_for_update(cmd, vg_name_to, NULL,
    466 					   READ_ALLOW_EXPORTED);
    467 		if (vg_read_error(vg_to)) {
    468 			log_error("Volume group \"%s\" became inconsistent: "
    469 				  "please fix manually", vg_name_to);
    470 			goto bad;
    471 		}
    472 	}
    473 
    474 	vg_to->status &= ~EXPORTED_VG;
    475 
    476 	if (!vg_write(vg_to) || !vg_commit(vg_to))
    477 		goto_bad;
    478 
    479 	backup(vg_to);
    480 
    481 	log_print("%s volume group \"%s\" successfully split from \"%s\"",
    482 		  existing_vg ? "Existing" : "New",
    483 		  vg_to->name, vg_from->name);
    484 
    485 	r = ECMD_PROCESSED;
    486 
    487 bad:
    488 	if (lock_vg_from_first) {
    489 		unlock_and_release_vg(cmd, vg_to, vg_name_to);
    490 		unlock_and_release_vg(cmd, vg_from, vg_name_from);
    491 	} else {
    492 		unlock_and_release_vg(cmd, vg_from, vg_name_from);
    493 		unlock_and_release_vg(cmd, vg_to, vg_name_to);
    494 	}
    495 	return r;
    496 }
    497