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