Home | History | Annotate | Line # | Download | only in tools
      1      1.1  haad /*	$NetBSD: vgmerge.c,v 1.1.1.2 2009/12/02 00:25:57 haad Exp $	*/
      2      1.1  haad 
      3      1.1  haad /*
      4      1.1  haad  * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
      5  1.1.1.2  haad  * Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
      6      1.1  haad  *
      7      1.1  haad  * This file is part of LVM2.
      8      1.1  haad  *
      9      1.1  haad  * This copyrighted material is made available to anyone wishing to use,
     10      1.1  haad  * modify, copy, or redistribute it subject to the terms and conditions
     11      1.1  haad  * of the GNU Lesser General Public License v.2.1.
     12      1.1  haad  *
     13      1.1  haad  * You should have received a copy of the GNU Lesser General Public License
     14      1.1  haad  * along with this program; if not, write to the Free Software Foundation,
     15      1.1  haad  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
     16      1.1  haad  */
     17      1.1  haad 
     18      1.1  haad #include "tools.h"
     19      1.1  haad 
     20  1.1.1.2  haad static struct volume_group *_vgmerge_vg_read(struct cmd_context *cmd,
     21  1.1.1.2  haad 					     const char *vg_name)
     22  1.1.1.2  haad {
     23  1.1.1.2  haad 	struct volume_group *vg;
     24  1.1.1.2  haad 	log_verbose("Checking for volume group \"%s\"", vg_name);
     25  1.1.1.2  haad 	vg = vg_read_for_update(cmd, vg_name, NULL, 0);
     26  1.1.1.2  haad 	if (vg_read_error(vg)) {
     27  1.1.1.2  haad 		vg_release(vg);
     28  1.1.1.2  haad 		return NULL;
     29  1.1.1.2  haad 	}
     30  1.1.1.2  haad 	return vg;
     31  1.1.1.2  haad }
     32  1.1.1.2  haad 
     33      1.1  haad static int _vgmerge_single(struct cmd_context *cmd, const char *vg_name_to,
     34      1.1  haad 			   const char *vg_name_from)
     35      1.1  haad {
     36      1.1  haad 	struct volume_group *vg_to, *vg_from;
     37      1.1  haad 	struct lv_list *lvl1, *lvl2;
     38  1.1.1.2  haad 	int r = ECMD_FAILED;
     39  1.1.1.2  haad 	int lock_vg_from_first = 0;
     40      1.1  haad 
     41      1.1  haad 	if (!strcmp(vg_name_to, vg_name_from)) {
     42      1.1  haad 		log_error("Duplicate volume group name \"%s\"", vg_name_from);
     43      1.1  haad 		return ECMD_FAILED;
     44      1.1  haad 	}
     45      1.1  haad 
     46  1.1.1.2  haad 	if (strcmp(vg_name_to, vg_name_from) > 0)
     47  1.1.1.2  haad 		lock_vg_from_first = 1;
     48  1.1.1.2  haad 
     49  1.1.1.2  haad 	if (lock_vg_from_first) {
     50  1.1.1.2  haad 		vg_from = _vgmerge_vg_read(cmd, vg_name_from);
     51  1.1.1.2  haad 		if (!vg_from) {
     52  1.1.1.2  haad 			stack;
     53  1.1.1.2  haad 			return ECMD_FAILED;
     54  1.1.1.2  haad 		}
     55  1.1.1.2  haad 		vg_to = _vgmerge_vg_read(cmd, vg_name_to);
     56  1.1.1.2  haad 		if (!vg_to) {
     57  1.1.1.2  haad 			stack;
     58  1.1.1.2  haad 			unlock_and_release_vg(cmd, vg_from, vg_name_from);
     59  1.1.1.2  haad 			return ECMD_FAILED;
     60  1.1.1.2  haad 		}
     61  1.1.1.2  haad 	} else {
     62  1.1.1.2  haad 		vg_to = _vgmerge_vg_read(cmd, vg_name_to);
     63  1.1.1.2  haad 		if (!vg_to) {
     64  1.1.1.2  haad 			stack;
     65  1.1.1.2  haad 			return ECMD_FAILED;
     66  1.1.1.2  haad 		}
     67  1.1.1.2  haad 
     68  1.1.1.2  haad 		vg_from = _vgmerge_vg_read(cmd, vg_name_from);
     69  1.1.1.2  haad 		if (!vg_from) {
     70  1.1.1.2  haad 			stack;
     71  1.1.1.2  haad 			unlock_and_release_vg(cmd, vg_to, vg_name_to);
     72  1.1.1.2  haad 			return ECMD_FAILED;
     73  1.1.1.2  haad 		}
     74      1.1  haad 	}
     75      1.1  haad 
     76      1.1  haad 	if (!vgs_are_compatible(cmd, vg_from, vg_to))
     77      1.1  haad 		goto_bad;
     78      1.1  haad 
     79      1.1  haad 	/* FIXME List arg: vg_show_with_pv_and_lv(vg_to); */
     80      1.1  haad 
     81      1.1  haad 	if (!archive(vg_from) || !archive(vg_to))
     82      1.1  haad 		goto_bad;
     83      1.1  haad 
     84      1.1  haad 	drop_cached_metadata(vg_from);
     85      1.1  haad 
     86      1.1  haad 	/* Merge volume groups */
     87      1.1  haad 	while (!dm_list_empty(&vg_from->pvs)) {
     88      1.1  haad 		struct dm_list *pvh = vg_from->pvs.n;
     89      1.1  haad 		struct physical_volume *pv;
     90      1.1  haad 
     91      1.1  haad 		dm_list_move(&vg_to->pvs, pvh);
     92      1.1  haad 
     93      1.1  haad 		pv = dm_list_item(pvh, struct pv_list)->pv;
     94      1.1  haad 		pv->vg_name = dm_pool_strdup(cmd->mem, vg_to->name);
     95      1.1  haad 	}
     96      1.1  haad 	vg_to->pv_count += vg_from->pv_count;
     97      1.1  haad 
     98      1.1  haad 	/* Fix up LVIDs */
     99      1.1  haad 	dm_list_iterate_items(lvl1, &vg_to->lvs) {
    100      1.1  haad 		union lvid *lvid1 = &lvl1->lv->lvid;
    101      1.1  haad 		char uuid[64] __attribute((aligned(8)));
    102      1.1  haad 
    103      1.1  haad 		dm_list_iterate_items(lvl2, &vg_from->lvs) {
    104      1.1  haad 			union lvid *lvid2 = &lvl2->lv->lvid;
    105      1.1  haad 
    106      1.1  haad 			if (id_equal(&lvid1->id[1], &lvid2->id[1])) {
    107      1.1  haad 				if (!id_create(&lvid2->id[1])) {
    108      1.1  haad 					log_error("Failed to generate new "
    109      1.1  haad 						  "random LVID for %s",
    110      1.1  haad 						  lvl2->lv->name);
    111      1.1  haad 					goto bad;
    112      1.1  haad 				}
    113      1.1  haad 				if (!id_write_format(&lvid2->id[1], uuid,
    114      1.1  haad 						     sizeof(uuid)))
    115      1.1  haad 					goto_bad;
    116      1.1  haad 
    117      1.1  haad 				log_verbose("Changed LVID for %s to %s",
    118      1.1  haad 					    lvl2->lv->name, uuid);
    119      1.1  haad 			}
    120      1.1  haad 		}
    121      1.1  haad 	}
    122      1.1  haad 
    123      1.1  haad 	while (!dm_list_empty(&vg_from->lvs)) {
    124      1.1  haad 		struct dm_list *lvh = vg_from->lvs.n;
    125      1.1  haad 
    126      1.1  haad 		dm_list_move(&vg_to->lvs, lvh);
    127      1.1  haad 	}
    128      1.1  haad 
    129      1.1  haad 	while (!dm_list_empty(&vg_from->fid->metadata_areas)) {
    130      1.1  haad 		struct dm_list *mdah = vg_from->fid->metadata_areas.n;
    131      1.1  haad 
    132      1.1  haad 		dm_list_move(&vg_to->fid->metadata_areas, mdah);
    133      1.1  haad 	}
    134      1.1  haad 
    135      1.1  haad 	vg_to->extent_count += vg_from->extent_count;
    136      1.1  haad 	vg_to->free_count += vg_from->free_count;
    137      1.1  haad 
    138      1.1  haad 	/* store it on disks */
    139      1.1  haad 	log_verbose("Writing out updated volume group");
    140      1.1  haad 	if (!vg_write(vg_to) || !vg_commit(vg_to))
    141      1.1  haad 		goto_bad;
    142      1.1  haad 
    143      1.1  haad 	/* FIXME Remove /dev/vgfrom */
    144      1.1  haad 
    145      1.1  haad 	backup(vg_to);
    146      1.1  haad 	log_print("Volume group \"%s\" successfully merged into \"%s\"",
    147      1.1  haad 		  vg_from->name, vg_to->name);
    148  1.1.1.2  haad 	r = ECMD_PROCESSED;
    149  1.1.1.2  haad bad:
    150  1.1.1.2  haad 	if (lock_vg_from_first) {
    151  1.1.1.2  haad 		unlock_and_release_vg(cmd, vg_to, vg_name_to);
    152  1.1.1.2  haad 		unlock_and_release_vg(cmd, vg_from, vg_name_from);
    153  1.1.1.2  haad 	} else {
    154  1.1.1.2  haad 		unlock_and_release_vg(cmd, vg_from, vg_name_from);
    155  1.1.1.2  haad 		unlock_and_release_vg(cmd, vg_to, vg_name_to);
    156  1.1.1.2  haad 	}
    157  1.1.1.2  haad 	return r;
    158      1.1  haad }
    159      1.1  haad 
    160      1.1  haad int vgmerge(struct cmd_context *cmd, int argc, char **argv)
    161      1.1  haad {
    162      1.1  haad 	char *vg_name_to, *vg_name_from;
    163      1.1  haad 	int opt = 0;
    164      1.1  haad 	int ret = 0, ret_max = 0;
    165      1.1  haad 
    166      1.1  haad 	if (argc < 2) {
    167      1.1  haad 		log_error("Please enter 2 or more volume groups to merge");
    168      1.1  haad 		return EINVALID_CMD_LINE;
    169      1.1  haad 	}
    170      1.1  haad 
    171      1.1  haad 	vg_name_to = skip_dev_dir(cmd, argv[0], NULL);
    172      1.1  haad 	argc--;
    173      1.1  haad 	argv++;
    174      1.1  haad 
    175      1.1  haad 	for (; opt < argc; opt++) {
    176      1.1  haad 		vg_name_from = skip_dev_dir(cmd, argv[opt], NULL);
    177      1.1  haad 
    178      1.1  haad 		ret = _vgmerge_single(cmd, vg_name_to, vg_name_from);
    179      1.1  haad 		if (ret > ret_max)
    180      1.1  haad 			ret_max = ret;
    181      1.1  haad 	}
    182      1.1  haad 
    183      1.1  haad 	return ret_max;
    184      1.1  haad }
    185