Home | History | Annotate | Line # | Download | only in tools
vgmerge.c revision 1.1
      1  1.1  haad /*	$NetBSD: vgmerge.c,v 1.1 2008/12/22 00:19:09 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  haad  * Copyright (C) 2004-2007 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  haad static int _vgmerge_single(struct cmd_context *cmd, const char *vg_name_to,
     21  1.1  haad 			   const char *vg_name_from)
     22  1.1  haad {
     23  1.1  haad 	struct volume_group *vg_to, *vg_from;
     24  1.1  haad 	struct lv_list *lvl1, *lvl2;
     25  1.1  haad 
     26  1.1  haad 	if (!strcmp(vg_name_to, vg_name_from)) {
     27  1.1  haad 		log_error("Duplicate volume group name \"%s\"", vg_name_from);
     28  1.1  haad 		return ECMD_FAILED;
     29  1.1  haad 	}
     30  1.1  haad 
     31  1.1  haad 	log_verbose("Checking for volume group \"%s\"", vg_name_to);
     32  1.1  haad 	if (!(vg_to = vg_lock_and_read(cmd, vg_name_to, NULL, LCK_VG_WRITE,
     33  1.1  haad 				       CLUSTERED | EXPORTED_VG | LVM_WRITE,
     34  1.1  haad 				       CORRECT_INCONSISTENT | FAIL_INCONSISTENT)))
     35  1.1  haad 		 return ECMD_FAILED;
     36  1.1  haad 
     37  1.1  haad 	log_verbose("Checking for volume group \"%s\"", vg_name_from);
     38  1.1  haad 	if (!(vg_from = vg_lock_and_read(cmd, vg_name_from, NULL,
     39  1.1  haad 					 LCK_VG_WRITE | LCK_NONBLOCK,
     40  1.1  haad 					 CLUSTERED | EXPORTED_VG | LVM_WRITE,
     41  1.1  haad 					 CORRECT_INCONSISTENT | FAIL_INCONSISTENT))) {
     42  1.1  haad 		unlock_vg(cmd, vg_name_to);
     43  1.1  haad 		return ECMD_FAILED;
     44  1.1  haad 	}
     45  1.1  haad 
     46  1.1  haad 	if (!vgs_are_compatible(cmd, vg_from, vg_to))
     47  1.1  haad 		goto_bad;
     48  1.1  haad 
     49  1.1  haad 	/* FIXME List arg: vg_show_with_pv_and_lv(vg_to); */
     50  1.1  haad 
     51  1.1  haad 	if (!archive(vg_from) || !archive(vg_to))
     52  1.1  haad 		goto_bad;
     53  1.1  haad 
     54  1.1  haad 	drop_cached_metadata(vg_from);
     55  1.1  haad 
     56  1.1  haad 	/* Merge volume groups */
     57  1.1  haad 	while (!dm_list_empty(&vg_from->pvs)) {
     58  1.1  haad 		struct dm_list *pvh = vg_from->pvs.n;
     59  1.1  haad 		struct physical_volume *pv;
     60  1.1  haad 
     61  1.1  haad 		dm_list_move(&vg_to->pvs, pvh);
     62  1.1  haad 
     63  1.1  haad 		pv = dm_list_item(pvh, struct pv_list)->pv;
     64  1.1  haad 		pv->vg_name = dm_pool_strdup(cmd->mem, vg_to->name);
     65  1.1  haad 	}
     66  1.1  haad 	vg_to->pv_count += vg_from->pv_count;
     67  1.1  haad 
     68  1.1  haad 	/* Fix up LVIDs */
     69  1.1  haad 	dm_list_iterate_items(lvl1, &vg_to->lvs) {
     70  1.1  haad 		union lvid *lvid1 = &lvl1->lv->lvid;
     71  1.1  haad 		char uuid[64] __attribute((aligned(8)));
     72  1.1  haad 
     73  1.1  haad 		dm_list_iterate_items(lvl2, &vg_from->lvs) {
     74  1.1  haad 			union lvid *lvid2 = &lvl2->lv->lvid;
     75  1.1  haad 
     76  1.1  haad 			if (id_equal(&lvid1->id[1], &lvid2->id[1])) {
     77  1.1  haad 				if (!id_create(&lvid2->id[1])) {
     78  1.1  haad 					log_error("Failed to generate new "
     79  1.1  haad 						  "random LVID for %s",
     80  1.1  haad 						  lvl2->lv->name);
     81  1.1  haad 					goto bad;
     82  1.1  haad 				}
     83  1.1  haad 				if (!id_write_format(&lvid2->id[1], uuid,
     84  1.1  haad 						     sizeof(uuid)))
     85  1.1  haad 					goto_bad;
     86  1.1  haad 
     87  1.1  haad 				log_verbose("Changed LVID for %s to %s",
     88  1.1  haad 					    lvl2->lv->name, uuid);
     89  1.1  haad 			}
     90  1.1  haad 		}
     91  1.1  haad 	}
     92  1.1  haad 
     93  1.1  haad 	while (!dm_list_empty(&vg_from->lvs)) {
     94  1.1  haad 		struct dm_list *lvh = vg_from->lvs.n;
     95  1.1  haad 
     96  1.1  haad 		dm_list_move(&vg_to->lvs, lvh);
     97  1.1  haad 	}
     98  1.1  haad 
     99  1.1  haad 	while (!dm_list_empty(&vg_from->fid->metadata_areas)) {
    100  1.1  haad 		struct dm_list *mdah = vg_from->fid->metadata_areas.n;
    101  1.1  haad 
    102  1.1  haad 		dm_list_move(&vg_to->fid->metadata_areas, mdah);
    103  1.1  haad 	}
    104  1.1  haad 
    105  1.1  haad 	vg_to->lv_count += vg_from->lv_count;
    106  1.1  haad 	vg_to->snapshot_count += vg_from->snapshot_count;
    107  1.1  haad 
    108  1.1  haad 	vg_to->extent_count += vg_from->extent_count;
    109  1.1  haad 	vg_to->free_count += vg_from->free_count;
    110  1.1  haad 
    111  1.1  haad 	/* store it on disks */
    112  1.1  haad 	log_verbose("Writing out updated volume group");
    113  1.1  haad 	if (!vg_write(vg_to) || !vg_commit(vg_to))
    114  1.1  haad 		goto_bad;
    115  1.1  haad 
    116  1.1  haad 	/* FIXME Remove /dev/vgfrom */
    117  1.1  haad 
    118  1.1  haad 	backup(vg_to);
    119  1.1  haad 
    120  1.1  haad 	unlock_vg(cmd, vg_name_from);
    121  1.1  haad 	unlock_vg(cmd, vg_name_to);
    122  1.1  haad 
    123  1.1  haad 	log_print("Volume group \"%s\" successfully merged into \"%s\"",
    124  1.1  haad 		  vg_from->name, vg_to->name);
    125  1.1  haad 	return ECMD_PROCESSED;
    126  1.1  haad 
    127  1.1  haad       bad:
    128  1.1  haad 	unlock_vg(cmd, vg_name_from);
    129  1.1  haad 	unlock_vg(cmd, vg_name_to);
    130  1.1  haad 	return ECMD_FAILED;
    131  1.1  haad }
    132  1.1  haad 
    133  1.1  haad int vgmerge(struct cmd_context *cmd, int argc, char **argv)
    134  1.1  haad {
    135  1.1  haad 	char *vg_name_to, *vg_name_from;
    136  1.1  haad 	int opt = 0;
    137  1.1  haad 	int ret = 0, ret_max = 0;
    138  1.1  haad 
    139  1.1  haad 	if (argc < 2) {
    140  1.1  haad 		log_error("Please enter 2 or more volume groups to merge");
    141  1.1  haad 		return EINVALID_CMD_LINE;
    142  1.1  haad 	}
    143  1.1  haad 
    144  1.1  haad 	vg_name_to = skip_dev_dir(cmd, argv[0], NULL);
    145  1.1  haad 	argc--;
    146  1.1  haad 	argv++;
    147  1.1  haad 
    148  1.1  haad 	for (; opt < argc; opt++) {
    149  1.1  haad 		vg_name_from = skip_dev_dir(cmd, argv[opt], NULL);
    150  1.1  haad 
    151  1.1  haad 		ret = _vgmerge_single(cmd, vg_name_to, vg_name_from);
    152  1.1  haad 		if (ret > ret_max)
    153  1.1  haad 			ret_max = ret;
    154  1.1  haad 	}
    155  1.1  haad 
    156  1.1  haad 	return ret_max;
    157  1.1  haad }
    158