]> sourceware.org Git - lvm2.git/blob - tools/vgmerge.c
Reinstate accidentally-deleted line.
[lvm2.git] / tools / vgmerge.c
1 /*
2 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
3 * Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
4 *
5 * This file is part of LVM2.
6 *
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.
10 *
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
14 */
15
16 #include "tools.h"
17
18 static struct volume_group *_vgmerge_vg_read(struct cmd_context *cmd,
19 const char *vg_name)
20 {
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)) {
25 release_vg(vg);
26 return NULL;
27 }
28 return vg;
29 }
30
31 static int _vgmerge_single(struct cmd_context *cmd, const char *vg_name_to,
32 const char *vg_name_from)
33 {
34 struct pv_list *pvl, *tpvl;
35 struct volume_group *vg_to, *vg_from;
36 struct lv_list *lvl1, *lvl2;
37 int r = ECMD_FAILED;
38 int lock_vg_from_first = 0;
39
40 if (!strcmp(vg_name_to, vg_name_from)) {
41 log_error("Duplicate volume group name \"%s\"", vg_name_from);
42 return ECMD_FAILED;
43 }
44
45 if (strcmp(vg_name_to, vg_name_from) > 0)
46 lock_vg_from_first = 1;
47
48 if (lock_vg_from_first) {
49 vg_from = _vgmerge_vg_read(cmd, vg_name_from);
50 if (!vg_from) {
51 stack;
52 return ECMD_FAILED;
53 }
54 vg_to = _vgmerge_vg_read(cmd, vg_name_to);
55 if (!vg_to) {
56 stack;
57 unlock_and_release_vg(cmd, vg_from, vg_name_from);
58 return ECMD_FAILED;
59 }
60 } else {
61 vg_to = _vgmerge_vg_read(cmd, vg_name_to);
62 if (!vg_to) {
63 stack;
64 return ECMD_FAILED;
65 }
66
67 vg_from = _vgmerge_vg_read(cmd, vg_name_from);
68 if (!vg_from) {
69 stack;
70 unlock_and_release_vg(cmd, vg_to, vg_name_to);
71 return ECMD_FAILED;
72 }
73 }
74
75 if (!vgs_are_compatible(cmd, vg_from, vg_to))
76 goto_bad;
77
78 /* FIXME List arg: vg_show_with_pv_and_lv(vg_to); */
79
80 if (!archive(vg_from) || !archive(vg_to))
81 goto_bad;
82
83 if (!drop_cached_metadata(vg_from))
84 stack;
85
86 /* Merge volume groups */
87 dm_list_iterate_items_safe(pvl, tpvl, &vg_from->pvs) {
88 del_pvl_from_vgs(vg_from, pvl);
89 add_pvl_to_vgs(vg_to, pvl);
90 pvl->pv->vg_name = dm_pool_strdup(cmd->mem, vg_to->name);
91 }
92
93 /* Fix up LVIDs */
94 dm_list_iterate_items(lvl1, &vg_to->lvs) {
95 union lvid *lvid1 = &lvl1->lv->lvid;
96 char uuid[64] __attribute__((aligned(8)));
97
98 dm_list_iterate_items(lvl2, &vg_from->lvs) {
99 union lvid *lvid2 = &lvl2->lv->lvid;
100
101 if (id_equal(&lvid1->id[1], &lvid2->id[1])) {
102 if (!id_create(&lvid2->id[1])) {
103 log_error("Failed to generate new "
104 "random LVID for %s",
105 lvl2->lv->name);
106 goto bad;
107 }
108 if (!id_write_format(&lvid2->id[1], uuid,
109 sizeof(uuid)))
110 goto_bad;
111
112 log_verbose("Changed LVID for %s to %s",
113 lvl2->lv->name, uuid);
114 }
115 }
116 }
117
118 dm_list_iterate_items(lvl1, &vg_from->lvs) {
119 lvl1->lv->vg = vg_to;
120 }
121
122 while (!dm_list_empty(&vg_from->lvs)) {
123 struct dm_list *lvh = vg_from->lvs.n;
124
125 dm_list_move(&vg_to->lvs, lvh);
126 }
127
128 while (!dm_list_empty(&vg_from->fid->metadata_areas_in_use)) {
129 struct dm_list *mdah = vg_from->fid->metadata_areas_in_use.n;
130
131 dm_list_move(&vg_to->fid->metadata_areas_in_use, mdah);
132 }
133
134 while (!dm_list_empty(&vg_from->fid->metadata_areas_ignored)) {
135 struct dm_list *mdah = vg_from->fid->metadata_areas_ignored.n;
136
137 dm_list_move(&vg_to->fid->metadata_areas_ignored, mdah);
138 }
139
140 vg_to->extent_count += vg_from->extent_count;
141 vg_to->free_count += vg_from->free_count;
142
143 /* store it on disks */
144 log_verbose("Writing out updated volume group");
145 if (!vg_write(vg_to) || !vg_commit(vg_to))
146 goto_bad;
147
148 /* FIXME Remove /dev/vgfrom */
149
150 backup(vg_to);
151 log_print("Volume group \"%s\" successfully merged into \"%s\"",
152 vg_from->name, vg_to->name);
153 r = ECMD_PROCESSED;
154 bad:
155 /*
156 * Note: as vg_to is referencing moved elements from vg_from
157 * the order of release_vg calls is mandatory.
158 */
159 unlock_and_release_vg(cmd, vg_to, vg_name_to);
160 unlock_and_release_vg(cmd, vg_from, vg_name_from);
161
162 return r;
163 }
164
165 int vgmerge(struct cmd_context *cmd, int argc, char **argv)
166 {
167 const char *vg_name_to, *vg_name_from;
168 int opt = 0;
169 int ret = 0, ret_max = 0;
170
171 if (argc < 2) {
172 log_error("Please enter 2 or more volume groups to merge");
173 return EINVALID_CMD_LINE;
174 }
175
176 vg_name_to = skip_dev_dir(cmd, argv[0], NULL);
177 argc--;
178 argv++;
179
180 for (; opt < argc; opt++) {
181 vg_name_from = skip_dev_dir(cmd, argv[opt], NULL);
182
183 ret = _vgmerge_single(cmd, vg_name_to, vg_name_from);
184 if (ret > ret_max)
185 ret_max = ret;
186 }
187
188 return ret_max;
189 }
This page took 0.043324 seconds and 5 git commands to generate.