]> sourceware.org Git - lvm2.git/blame - tools/vgreduce.c
spacing
[lvm2.git] / tools / vgreduce.c
CommitLineData
6e91eeef 1/*
67cdbd7e 2 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
ea0cdd28 3 * Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
6e91eeef 4 *
6606c3ae 5 * This file is part of LVM2.
6e91eeef 6 *
6606c3ae
AK
7 * This copyrighted material is made available to anyone wishing to use,
8 * modify, copy, or redistribute it subject to the terms and conditions
be684599 9 * of the GNU Lesser General Public License v.2.1.
6e91eeef 10 *
be684599 11 * You should have received a copy of the GNU Lesser General Public License
6606c3ae
AK
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
6e91eeef
AK
14 */
15
16#include "tools.h"
3fc3e48c 17#include "lv_alloc.h"
6e91eeef 18
8c5bcdab 19static int _remove_pv(struct volume_group *vg, struct pv_list *pvl, int silent)
a421f743 20{
08f1ddea 21 char uuid[64] __attribute__((aligned(8)));
a421f743
AK
22
23 if (vg->pv_count == 1) {
24 log_error("Volume Groups must always contain at least one PV");
25 return 0;
26 }
27
c51b9fff
AK
28 if (!id_write_format(&pvl->pv->id, uuid, sizeof(uuid)))
29 return_0;
a421f743
AK
30
31 log_verbose("Removing PV with UUID %s from VG %s", uuid, vg->name);
32
33 if (pvl->pv->pe_alloc_count) {
8c5bcdab
AK
34 if (!silent)
35 log_error("LVs still present on PV with UUID %s: "
36 "Can't remove from VG %s", uuid, vg->name);
a421f743
AK
37 return 0;
38 }
39
40 vg->free_count -= pvl->pv->pe_count;
41 vg->extent_count -= pvl->pv->pe_count;
0adfbfd5 42 del_pvl_from_vgs(vg, pvl);
84f48499 43 free_pv_fid(pvl->pv);
a421f743
AK
44
45 return 1;
46}
47
8c5bcdab
AK
48static int _consolidate_vg(struct cmd_context *cmd, struct volume_group *vg)
49{
50 struct pv_list *pvl;
51 struct lv_list *lvl;
52 int r = 1;
53
2c44337b 54 dm_list_iterate_items(lvl, &vg->lvs)
8c5bcdab
AK
55 if (lvl->lv->status & PARTIAL_LV) {
56 log_warn("WARNING: Partial LV %s needs to be repaired "
57 "or removed. ", lvl->lv->name);
58 r = 0;
59 }
60
61 if (!r) {
62 cmd->handles_missing_pvs = 1;
616c6208
PR
63 log_error("There are still partial LVs in VG %s.", vg->name);
64 log_error("To remove them unconditionally use: vgreduce --removemissing --force.");
8c5bcdab
AK
65 log_warn("Proceeding to remove empty missing PVs.");
66 }
67
2c44337b 68 dm_list_iterate_items(pvl, &vg->pvs) {
770dc81b 69 if (pvl->pv->dev && !is_missing_pv(pvl->pv))
8c5bcdab
AK
70 continue;
71 if (r && !_remove_pv(vg, pvl, 0))
72 return_0;
73 }
74
75 return r;
76}
77
a421f743
AK
78static int _make_vg_consistent(struct cmd_context *cmd, struct volume_group *vg)
79{
ed6ff5d2 80 struct lv_list *lvl;
a421f743 81 struct logical_volume *lv;
3fc3e48c 82
ed6ff5d2 83 cmd->partial_activation = 1;
3fc3e48c 84
ed6ff5d2
PR
85 restart:
86 vg_mark_partial_lvs(vg, 1);
532dae48 87
ed6ff5d2
PR
88 dm_list_iterate_items(lvl, &vg->lvs) {
89 lv = lvl->lv;
532dae48 90
ed6ff5d2
PR
91 /* Are any segments of this LV on missing PVs? */
92 if (lv->status & PARTIAL_LV) {
93 if (lv->status & MIRRORED) {
94 if (!mirror_remove_missing(cmd, lv, 1))
c51b9fff 95 return_0;
ed6ff5d2 96 goto restart;
079ac15e 97 }
3fc3e48c 98
ed6ff5d2
PR
99 if (arg_count(cmd, mirrorsonly_ARG) &&!(lv->status & MIRRORED)) {
100 log_error("Non-mirror-image LV %s found: can't remove.", lv->name);
101 continue;
3fc3e48c 102 }
3fc3e48c 103
ed6ff5d2
PR
104 if (!lv_is_visible(lv))
105 continue;
106 log_warn("Removing partial LV %s.", lv->name);
6fa41e8a 107 if (!lv_remove_with_dependencies(cmd, lv, DONT_PROMPT, 0))
ed6ff5d2
PR
108 return_0;
109 goto restart;
3fc3e48c
AK
110 }
111 }
112
ed6ff5d2
PR
113 _consolidate_vg(cmd, vg);
114
a421f743
AK
115 return 1;
116}
117
5a52dca9 118/* Or take pv_name instead? */
a421f743 119static int _vgreduce_single(struct cmd_context *cmd, struct volume_group *vg,
72b2cb61 120 struct physical_volume *pv,
08f1ddea 121 void *handle __attribute__((unused)))
5a52dca9
AK
122{
123 struct pv_list *pvl;
043b1362 124 struct volume_group *orphan_vg = NULL;
043b1362 125 int r = ECMD_FAILED;
1b8de4cb 126 const char *name = pv_dev_name(pv);
5a52dca9 127
ff77bb1a 128 if (pv_pe_alloc_count(pv)) {
5a52dca9
AK
129 log_error("Physical volume \"%s\" still in use", name);
130 return ECMD_FAILED;
131 }
132
133 if (vg->pv_count == 1) {
134 log_error("Can't remove final physical volume \"%s\" from "
135 "volume group \"%s\"", name, vg->name);
136 return ECMD_FAILED;
137 }
138
5a820745 139 if (!lock_vol(cmd, VG_ORPHANS, LCK_VG_WRITE)) {
6eb44b50
AK
140 log_error("Can't get lock for orphan PVs");
141 return ECMD_FAILED;
142 }
143
5a52dca9
AK
144 pvl = find_pv_in_vg(vg, name);
145
043b1362 146 if (!archive(vg))
651ff9b3 147 goto_bad;
6e91eeef 148
5a52dca9
AK
149 log_verbose("Removing \"%s\" from volume group \"%s\"", name, vg->name);
150
151 if (pvl)
11647ad0 152 del_pvl_from_vgs(vg, pvl);
5a52dca9 153
bb097a97 154 pv->vg_name = vg->fid->fmt->orphan_vg_name;
3fc3e48c 155 pv->status = ALLOCATABLE_PV;
15db9fcf 156
ff77bb1a 157 if (!dev_get_size(pv_dev(pv), &pv->size)) {
1b8de4cb 158 log_error("%s: Couldn't get size.", pv_dev_name(pv));
043b1362 159 goto bad;
15db9fcf
AK
160 }
161
ff77bb1a
DW
162 vg->free_count -= pv_pe_count(pv) - pv_pe_alloc_count(pv);
163 vg->extent_count -= pv_pe_count(pv);
5a52dca9 164
542ef24d 165 orphan_vg = vg_read_for_update(cmd, vg->fid->fmt->orphan_vg_name,
4c35d6de 166 NULL, 0);
542ef24d
DW
167
168 if (vg_read_error(orphan_vg))
043b1362 169 goto bad;
6eb44b50
AK
170
171 if (!vg_split_mdas(cmd, vg, orphan_vg) || !vg->pv_count) {
172 log_error("Cannot remove final metadata area on \"%s\" from \"%s\"",
173 name, vg->name);
043b1362 174 goto bad;
6eb44b50
AK
175 }
176
914c9723 177 if (!vg_write(vg) || !vg_commit(vg)) {
5a52dca9
AK
178 log_error("Removal of physical volume \"%s\" from "
179 "\"%s\" failed", name, vg->name);
043b1362 180 goto bad;
5a52dca9
AK
181 }
182
3b97e8d6 183 if (!pv_write(cmd, pv, 0)) {
5a52dca9
AK
184 log_error("Failed to clear metadata from physical "
185 "volume \"%s\" "
186 "after removal from \"%s\"", name, vg->name);
043b1362 187 goto bad;
5a52dca9
AK
188 }
189
190 backup(vg);
191
192 log_print("Removed \"%s\" from volume group \"%s\"", name, vg->name);
043b1362
MB
193 r = ECMD_PROCESSED;
194bad:
84f48499
PR
195 if (pvl)
196 free_pv_fid(pvl->pv);
077a6755 197 unlock_and_release_vg(cmd, orphan_vg, VG_ORPHANS);
043b1362 198 return r;
5a52dca9 199}
a421f743 200
60274aba 201int vgreduce(struct cmd_context *cmd, int argc, char **argv)
6e91eeef
AK
202{
203 struct volume_group *vg;
aec21154 204 const char *vg_name;
043b1362 205 int ret = ECMD_FAILED;
8c5bcdab
AK
206 int fixed = 1;
207 int repairing = arg_count(cmd, removemissing_ARG);
1f164ad9 208 int saved_ignore_suspended_devices = ignore_suspended_devices();
6e826bb6 209 int locked = 0;
6e91eeef 210
8c5bcdab 211 if (!argc && !repairing) {
6e91eeef
AK
212 log_error("Please give volume group name and "
213 "physical volume paths");
214 return EINVALID_CMD_LINE;
215 }
8c5bcdab 216
eae8784a 217 if (!argc) { /* repairing */
a421f743
AK
218 log_error("Please give volume group name");
219 return EINVALID_CMD_LINE;
220 }
221
8c5bcdab 222 if (arg_count(cmd, mirrorsonly_ARG) && !repairing) {
c9dcba6b
AK
223 log_error("--mirrorsonly requires --removemissing");
224 return EINVALID_CMD_LINE;
225 }
226
8c5bcdab 227 if (argc == 1 && !arg_count(cmd, all_ARG) && !repairing) {
6e91eeef
AK
228 log_error("Please enter physical volume paths or option -a");
229 return EINVALID_CMD_LINE;
230 }
231
6fda126d 232 if (argc > 1 && arg_count(cmd, all_ARG)) {
6e91eeef
AK
233 log_error("Option -a and physical volume paths mutually "
234 "exclusive");
235 return EINVALID_CMD_LINE;
236 }
237
8c5bcdab 238 if (argc > 1 && repairing) {
a421f743
AK
239 log_error("Please only specify the volume group");
240 return EINVALID_CMD_LINE;
241 }
242
9397354a 243 vg_name = skip_dev_dir(cmd, argv[0], NULL);
6e91eeef
AK
244 argv++;
245 argc--;
246
08907484 247 log_verbose("Finding volume group \"%s\"", vg_name);
7d0e6e80 248
19089ba3 249 if (repairing) {
1f164ad9 250 init_ignore_suspended_devices(1);
19089ba3
PR
251 cmd->handles_missing_pvs = 1;
252 }
1f164ad9 253
542ef24d
DW
254 vg = vg_read_for_update(cmd, vg_name, NULL, READ_ALLOW_EXPORTED);
255 if (vg_read_error(vg) == FAILED_ALLOCATION ||
256 vg_read_error(vg) == FAILED_NOTFOUND)
651ff9b3 257 goto_out;
6e91eeef 258
542ef24d
DW
259 /* FIXME We want to allow read-only VGs to be changed here? */
260 if (vg_read_error(vg) && vg_read_error(vg) != FAILED_READ_ONLY
261 && !arg_count(cmd, removemissing_ARG))
651ff9b3 262 goto_out;
dc4d7417 263
6e826bb6
ZK
264 locked = !vg_read_error(vg);
265
8c5bcdab 266 if (repairing) {
542ef24d 267 if (!vg_read_error(vg) && !vg_missing_pv_count(vg)) {
a421f743
AK
268 log_error("Volume group \"%s\" is already consistent",
269 vg_name);
043b1362
MB
270 ret = ECMD_PROCESSED;
271 goto out;
a421f743 272 }
f53c6aa6 273
077a6755 274 release_vg(vg);
542ef24d
DW
275 log_verbose("Trying to open VG %s for recovery...", vg_name);
276
277 vg = vg_read_for_update(cmd, vg_name, NULL,
278 READ_ALLOW_INCONSISTENT
279 | READ_ALLOW_EXPORTED);
280
6e826bb6 281 locked |= !vg_read_error(vg);
542ef24d
DW
282 if (vg_read_error(vg) && vg_read_error(vg) != FAILED_READ_ONLY
283 && vg_read_error(vg) != FAILED_INCONSISTENT)
651ff9b3 284 goto_out;
542ef24d 285
043b1362 286 if (!archive(vg))
651ff9b3 287 goto_out;
f53c6aa6 288
8c5bcdab 289 if (arg_count(cmd, force_ARG)) {
043b1362 290 if (!_make_vg_consistent(cmd, vg))
651ff9b3 291 goto_out;
8c5bcdab
AK
292 } else
293 fixed = _consolidate_vg(cmd, vg);
a421f743 294
914c9723 295 if (!vg_write(vg) || !vg_commit(vg)) {
a421f743
AK
296 log_error("Failed to write out a consistent VG for %s",
297 vg_name);
043b1362 298 goto out;
a421f743 299 }
a421f743
AK
300 backup(vg);
301
cd978f74 302 if (fixed) {
8c5bcdab
AK
303 log_print("Wrote out consistent volume group %s",
304 vg_name);
cd978f74
MB
305 ret = ECMD_PROCESSED;
306 } else
307 ret = ECMD_FAILED;
a421f743
AK
308
309 } else {
043b1362 310 if (!vg_check_status(vg, EXPORTED_VG | LVM_WRITE | RESIZEABLE_VG))
651ff9b3 311 goto_out;
a421f743
AK
312
313 /* FIXME: Pass private struct through to all these functions */
314 /* and update in batch here? */
21a98eda 315 ret = process_each_pv(cmd, argc, argv, vg, READ_FOR_UPDATE, 0, NULL,
a421f743
AK
316 _vgreduce_single);
317
318 }
043b1362 319out:
1f164ad9 320 init_ignore_suspended_devices(saved_ignore_suspended_devices);
6e826bb6
ZK
321 if (locked)
322 unlock_vg(cmd, vg_name);
323
324 release_vg(vg);
7d0e6e80
AK
325
326 return ret;
6e91eeef
AK
327
328/******* FIXME
329 log_error ("no empty physical volumes found in volume group \"%s\"", vg_name);
cc282870 330
6e91eeef
AK
331 log_verbose
332 ("volume group \"%s\" will be reduced by %d physical volume%s",
333 vg_name, np, np > 1 ? "s" : "");
08907484
HM
334 log_verbose ("reducing volume group \"%s\" by physical volume \"%s\"",
335 vg_name, pv_names[p]);
6e91eeef
AK
336
337 log_print
338 ("volume group \"%s\" %ssuccessfully reduced by physical volume%s:",
339 vg_name, error > 0 ? "NOT " : "", p > 1 ? "s" : "");
340 log_print("%s", pv_this[p]->pv_name);
341********/
342
343}
This page took 0.212826 seconds and 5 git commands to generate.