xref: /dragonfly/contrib/lvm2/dist/tools/vgsplit.c (revision c37c9ab3)
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