2 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
3 * Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
5 * This file is part of LVM2.
7 * This copyrighted material is made available to anyone wishing to use,
8 * modify, copy, or redistribute it subject to the terms and conditions
9 * of the GNU Lesser General Public License v.2.1.
11 * You should have received a copy of the GNU Lesser General Public License
12 * along with this program; if not, write to the Free Software Foundation,
13 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 static struct volume_group *_vgmerge_vg_read(struct cmd_context *cmd,
21 struct volume_group *vg;
22 log_verbose("Checking for volume group \"%s\"", vg_name);
23 vg = vg_read_for_update(cmd, vg_name, NULL, 0);
24 if (vg_read_error(vg)) {
31 static int _vgmerge_single(struct cmd_context *cmd, const char *vg_name_to,
32 const char *vg_name_from)
34 struct pv_list *pvl, *tpvl;
35 struct volume_group *vg_to, *vg_from;
36 struct lv_list *lvl1, *lvl2;
38 int lock_vg_from_first = 0;
40 if (!strcmp(vg_name_to, vg_name_from)) {
41 log_error("Duplicate volume group name \"%s\"", vg_name_from);
45 if (strcmp(vg_name_to, vg_name_from) > 0)
46 lock_vg_from_first = 1;
48 if (lock_vg_from_first) {
49 vg_from = _vgmerge_vg_read(cmd, vg_name_from);
54 vg_to = _vgmerge_vg_read(cmd, vg_name_to);
57 unlock_and_free_vg(cmd, vg_from, vg_name_from);
61 vg_to = _vgmerge_vg_read(cmd, vg_name_to);
67 vg_from = _vgmerge_vg_read(cmd, vg_name_from);
70 unlock_and_free_vg(cmd, vg_to, vg_name_to);
75 if (!vgs_are_compatible(cmd, vg_from, vg_to))
78 /* FIXME List arg: vg_show_with_pv_and_lv(vg_to); */
80 if (!archive(vg_from) || !archive(vg_to))
83 drop_cached_metadata(vg_from);
85 /* Merge volume groups */
86 dm_list_iterate_items_safe(pvl, tpvl, &vg_from->pvs) {
87 del_pvl_from_vgs(vg_from, pvl);
88 add_pvl_to_vgs(vg_to, pvl);
89 pvl->pv->vg_name = dm_pool_strdup(cmd->mem, vg_to->name);
93 dm_list_iterate_items(lvl1, &vg_to->lvs) {
94 union lvid *lvid1 = &lvl1->lv->lvid;
95 char uuid[64] __attribute__((aligned(8)));
97 dm_list_iterate_items(lvl2, &vg_from->lvs) {
98 union lvid *lvid2 = &lvl2->lv->lvid;
100 if (id_equal(&lvid1->id[1], &lvid2->id[1])) {
101 if (!id_create(&lvid2->id[1])) {
102 log_error("Failed to generate new "
103 "random LVID for %s",
107 if (!id_write_format(&lvid2->id[1], uuid,
111 log_verbose("Changed LVID for %s to %s",
112 lvl2->lv->name, uuid);
117 dm_list_iterate_items(lvl1, &vg_from->lvs) {
118 lvl1->lv->vg = vg_to;
121 while (!dm_list_empty(&vg_from->lvs)) {
122 struct dm_list *lvh = vg_from->lvs.n;
124 dm_list_move(&vg_to->lvs, lvh);
127 while (!dm_list_empty(&vg_from->fid->metadata_areas_in_use)) {
128 struct dm_list *mdah = vg_from->fid->metadata_areas_in_use.n;
130 dm_list_move(&vg_to->fid->metadata_areas_in_use, mdah);
133 while (!dm_list_empty(&vg_from->fid->metadata_areas_ignored)) {
134 struct dm_list *mdah = vg_from->fid->metadata_areas_ignored.n;
136 dm_list_move(&vg_to->fid->metadata_areas_ignored, mdah);
139 vg_to->extent_count += vg_from->extent_count;
140 vg_to->free_count += vg_from->free_count;
142 /* store it on disks */
143 log_verbose("Writing out updated volume group");
144 if (!vg_write(vg_to) || !vg_commit(vg_to))
147 /* FIXME Remove /dev/vgfrom */
150 log_print("Volume group \"%s\" successfully merged into \"%s\"",
151 vg_from->name, vg_to->name);
154 if (lock_vg_from_first) {
155 unlock_and_free_vg(cmd, vg_to, vg_name_to);
156 unlock_and_free_vg(cmd, vg_from, vg_name_from);
158 unlock_and_free_vg(cmd, vg_from, vg_name_from);
159 unlock_and_free_vg(cmd, vg_to, vg_name_to);
164 int vgmerge(struct cmd_context *cmd, int argc, char **argv)
166 char *vg_name_to, *vg_name_from;
168 int ret = 0, ret_max = 0;
171 log_error("Please enter 2 or more volume groups to merge");
172 return EINVALID_CMD_LINE;
175 vg_name_to = skip_dev_dir(cmd, argv[0], NULL);
179 for (; opt < argc; opt++) {
180 vg_name_from = skip_dev_dir(cmd, argv[opt], NULL);
182 ret = _vgmerge_single(cmd, vg_name_to, vg_name_from);