]>
Commit | Line | Data |
---|---|---|
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 |
18 | struct vgreduce_params { |
19 | int force; | |
20 | int fixed; | |
21 | int already_consistent; | |
22 | }; | |
23 | ||
8c5bcdab | 24 | static 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 |
53 | static 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 |
85 | static 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 | 134 | static 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 |
150 | static 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 | 175 | int 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 | 262 | out: |
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 | } |