]> sourceware.org Git - lvm2.git/blame - tools/vgreduce.c
metadata: use lv_hash in segment-specific metadata parsing
[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 12 * along with this program; if not, write to the Free Software Foundation,
fcbef05a 13 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
6e91eeef
AK
14 */
15
16#include "tools.h"
17
5dc2ed0c
DT
18struct vgreduce_params {
19 int force;
20 int fixed;
21 int already_consistent;
22};
23
8c5bcdab 24static int _remove_pv(struct volume_group *vg, struct pv_list *pvl, int silent)
a421f743 25{
08f1ddea 26 char uuid[64] __attribute__((aligned(8)));
a421f743
AK
27
28 if (vg->pv_count == 1) {
1a4f13eb 29 log_error("Volume Groups must always contain at least one PV.");
a421f743
AK
30 return 0;
31 }
32
c51b9fff
AK
33 if (!id_write_format(&pvl->pv->id, uuid, sizeof(uuid)))
34 return_0;
a421f743 35
1a4f13eb 36 log_verbose("Removing PV with UUID %s from VG %s.", uuid, vg->name);
a421f743
AK
37
38 if (pvl->pv->pe_alloc_count) {
8c5bcdab
AK
39 if (!silent)
40 log_error("LVs still present on PV with UUID %s: "
1a4f13eb 41 "Can't remove from VG %s.", uuid, vg->name);
a421f743
AK
42 return 0;
43 }
44
45 vg->free_count -= pvl->pv->pe_count;
46 vg->extent_count -= pvl->pv->pe_count;
0adfbfd5 47 del_pvl_from_vgs(vg, pvl);
84f48499 48 free_pv_fid(pvl->pv);
a421f743
AK
49
50 return 1;
51}
52
8c5bcdab
AK
53static int _consolidate_vg(struct cmd_context *cmd, struct volume_group *vg)
54{
55 struct pv_list *pvl;
56 struct lv_list *lvl;
57 int r = 1;
58
2c44337b 59 dm_list_iterate_items(lvl, &vg->lvs)
e04a0184 60 if (lv_is_partial(lvl->lv)) {
8c5bcdab
AK
61 log_warn("WARNING: Partial LV %s needs to be repaired "
62 "or removed. ", lvl->lv->name);
63 r = 0;
64 }
65
66 if (!r) {
67 cmd->handles_missing_pvs = 1;
616c6208
PR
68 log_error("There are still partial LVs in VG %s.", vg->name);
69 log_error("To remove them unconditionally use: vgreduce --removemissing --force.");
d53bfae2
HZ
70 log_error("To remove them unconditionally from mirror LVs use: vgreduce"
71 " --removemissing --mirrorsonly --force.");
c10028dd 72 log_warn("WARNING: Proceeding to remove empty missing PVs.");
8c5bcdab
AK
73 }
74
2c44337b 75 dm_list_iterate_items(pvl, &vg->pvs) {
770dc81b 76 if (pvl->pv->dev && !is_missing_pv(pvl->pv))
8c5bcdab
AK
77 continue;
78 if (r && !_remove_pv(vg, pvl, 0))
79 return_0;
80 }
81
82 return r;
83}
84
a421f743
AK
85static int _make_vg_consistent(struct cmd_context *cmd, struct volume_group *vg)
86{
ed6ff5d2 87 struct lv_list *lvl;
a421f743 88 struct logical_volume *lv;
3fc3e48c 89
ed6ff5d2 90 cmd->partial_activation = 1;
3fc3e48c 91
ed6ff5d2
PR
92 restart:
93 vg_mark_partial_lvs(vg, 1);
532dae48 94
ed6ff5d2
PR
95 dm_list_iterate_items(lvl, &vg->lvs) {
96 lv = lvl->lv;
532dae48 97
ed6ff5d2 98 /* Are any segments of this LV on missing PVs? */
e04a0184 99 if (lv_is_partial(lv)) {
845852d6
JB
100 if (seg_is_raid(first_seg(lv))) {
101 if (!lv_raid_remove_missing(lv))
102 return_0;
103 goto restart;
104 }
105
979be63f 106 if (lv_is_mirror(lv)) {
ed6ff5d2 107 if (!mirror_remove_missing(cmd, lv, 1))
c51b9fff 108 return_0;
ed6ff5d2 109 goto restart;
079ac15e 110 }
3fc3e48c 111
7e671e5d 112 if (arg_is_set(cmd, mirrorsonly_ARG) && !lv_is_mirrored(lv)) {
ed6ff5d2
PR
113 log_error("Non-mirror-image LV %s found: can't remove.", lv->name);
114 continue;
3fc3e48c 115 }
3fc3e48c 116
ed6ff5d2
PR
117 if (!lv_is_visible(lv))
118 continue;
c10028dd
ZK
119
120 log_warn("WARNING: Removing partial LV %s.", display_lvname(lv));
121
6fa41e8a 122 if (!lv_remove_with_dependencies(cmd, lv, DONT_PROMPT, 0))
ed6ff5d2
PR
123 return_0;
124 goto restart;
3fc3e48c
AK
125 }
126 }
127
ed6ff5d2
PR
128 _consolidate_vg(cmd, vg);
129
a421f743
AK
130 return 1;
131}
132
5a52dca9 133/* Or take pv_name instead? */
a421f743 134static int _vgreduce_single(struct cmd_context *cmd, struct volume_group *vg,
72b2cb61 135 struct physical_volume *pv,
51d96a17 136 struct processing_handle *handle __attribute__((unused)))
5a52dca9 137{
e458fc9a 138 int r;
fd417db2 139
b4402bd8 140 if (!vg_check_status(vg, LVM_WRITE | RESIZEABLE_VG))
e458fc9a
DT
141 return ECMD_FAILED;
142
143 r = vgreduce_single(cmd, vg, pv, 1);
fe474e14 144 if (!r)
5a52dca9 145 return ECMD_FAILED;
5a52dca9 146
fe474e14
TA
147 return ECMD_PROCESSED;
148}
5a52dca9 149
5dc2ed0c
DT
150static int _vgreduce_repair_single(struct cmd_context *cmd, const char *vg_name,
151 struct volume_group *vg, struct processing_handle *handle)
152{
153 struct vgreduce_params *vp = (struct vgreduce_params *) handle->custom_handle;
154
155 if (!vg_missing_pv_count(vg)) {
156 vp->already_consistent = 1;
157 return ECMD_PROCESSED;
158 }
159
5dc2ed0c
DT
160 if (vp->force) {
161 if (!_make_vg_consistent(cmd, vg))
162 return_ECMD_FAILED;
163 vp->fixed = 1;
164 } else
165 vp->fixed = _consolidate_vg(cmd, vg);
166
167 if (!vg_write(vg) || !vg_commit(vg)) {
168 log_error("Failed to write out a consistent VG for %s", vg_name);
169 return ECMD_FAILED;
170 }
171
5dc2ed0c
DT
172 return ECMD_PROCESSED;
173}
174
60274aba 175int vgreduce(struct cmd_context *cmd, int argc, char **argv)
6e91eeef 176{
5dc2ed0c
DT
177 struct processing_handle *handle;
178 struct vgreduce_params vp = { 0 };
aec21154 179 const char *vg_name;
7e671e5d 180 int repairing = arg_is_set(cmd, removemissing_ARG);
1f164ad9 181 int saved_ignore_suspended_devices = ignore_suspended_devices();
5dc2ed0c 182 int ret;
6e91eeef 183
8c5bcdab 184 if (!argc && !repairing) {
6e91eeef 185 log_error("Please give volume group name and "
1a4f13eb 186 "physical volume paths.");
6e91eeef
AK
187 return EINVALID_CMD_LINE;
188 }
8c5bcdab 189
eae8784a 190 if (!argc) { /* repairing */
1a4f13eb 191 log_error("Please give volume group name.");
a421f743
AK
192 return EINVALID_CMD_LINE;
193 }
194
7e671e5d 195 if (arg_is_set(cmd, mirrorsonly_ARG) && !repairing) {
1a4f13eb 196 log_error("--mirrorsonly requires --removemissing.");
c9dcba6b
AK
197 return EINVALID_CMD_LINE;
198 }
199
7e671e5d 200 if (argc == 1 && !arg_is_set(cmd, all_ARG) && !repairing) {
1a4f13eb 201 log_error("Please enter physical volume paths or option -a.");
6e91eeef
AK
202 return EINVALID_CMD_LINE;
203 }
204
7e671e5d 205 if (argc > 1 && arg_is_set(cmd, all_ARG)) {
6e91eeef 206 log_error("Option -a and physical volume paths mutually "
1a4f13eb 207 "exclusive.");
6e91eeef
AK
208 return EINVALID_CMD_LINE;
209 }
210
8c5bcdab 211 if (argc > 1 && repairing) {
1a4f13eb 212 log_error("Please only specify the volume group.");
a421f743
AK
213 return EINVALID_CMD_LINE;
214 }
215
9397354a 216 vg_name = skip_dev_dir(cmd, argv[0], NULL);
6e91eeef
AK
217 argv++;
218 argc--;
219
8c87dda1 220 if (!lock_global(cmd, "ex"))
029f51e1 221 return_ECMD_FAILED;
029f51e1 222
6620dc94
DT
223 clear_hint_file(cmd);
224
f752a953 225 if (!(handle = init_processing_handle(cmd, NULL))) {
5dc2ed0c
DT
226 log_error("Failed to initialize processing handle.");
227 return ECMD_FAILED;
228 }
229 handle->custom_handle = &vp;
230
231 if (!repairing) {
e458fc9a
DT
232 /* FIXME: Pass private struct through to all these functions */
233 /* and update in batch afterwards? */
9a8c36b8 234
8c87dda1 235 ret = process_each_pv(cmd, argc, argv, vg_name, 0, READ_FOR_UPDATE,
9a8c36b8
DT
236 handle, _vgreduce_single);
237
5dc2ed0c
DT
238 goto out;
239 }
e458fc9a 240
5dc2ed0c
DT
241 /*
242 * VG repair (removemissing)
243 */
7d0e6e80 244
5dc2ed0c 245 vp.force = arg_count(cmd, force_ARG);
1f164ad9 246
5dc2ed0c 247 cmd->handles_missing_pvs = 1;
6e91eeef 248
5dc2ed0c 249 init_ignore_suspended_devices(1);
dc4d7417 250
b4402bd8 251 process_each_vg(cmd, 0, NULL, vg_name, NULL, READ_FOR_UPDATE,
8cfc3854 252 0, handle, &_vgreduce_repair_single);
6e826bb6 253
5dc2ed0c 254 if (vp.already_consistent) {
1a4f13eb 255 log_print_unless_silent("Volume group \"%s\" is already consistent.", vg_name);
e458fc9a 256 ret = ECMD_PROCESSED;
5dc2ed0c 257 } else if (vp.fixed) {
1a4f13eb 258 log_print_unless_silent("Wrote out consistent volume group %s.", vg_name);
e458fc9a
DT
259 ret = ECMD_PROCESSED;
260 } else
261 ret = ECMD_FAILED;
043b1362 262out:
1f164ad9 263 init_ignore_suspended_devices(saved_ignore_suspended_devices);
a23655ab 264 destroy_processing_handle(cmd, handle);
7d0e6e80
AK
265
266 return ret;
6e91eeef 267}
This page took 0.290742 seconds and 6 git commands to generate.