4 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
5 * Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
7 * This file is part of LVM2.
9 * This copyrighted material is made available to anyone wishing to use,
10 * modify, copy, or redistribute it subject to the terms and conditions
11 * of the GNU Lesser General Public License v.2.1.
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program; if not, write to the Free Software Foundation,
15 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 static int _remove_pv(struct volume_group
*vg
, struct pv_list
*pvl
, int silent
)
23 char uuid
[64] __attribute((aligned(8)));
25 if (vg
->pv_count
== 1) {
26 log_error("Volume Groups must always contain at least one PV");
30 if (!id_write_format(&pvl
->pv
->id
, uuid
, sizeof(uuid
)))
33 log_verbose("Removing PV with UUID %s from VG %s", uuid
, vg
->name
);
35 if (pvl
->pv
->pe_alloc_count
) {
37 log_error("LVs still present on PV with UUID %s: "
38 "Can't remove from VG %s", uuid
, vg
->name
);
42 vg
->free_count
-= pvl
->pv
->pe_count
;
43 vg
->extent_count
-= pvl
->pv
->pe_count
;
46 dm_list_del(&pvl
->list
);
51 static int _remove_lv(struct cmd_context
*cmd
, struct logical_volume
*lv
,
52 int *list_unsafe
, struct dm_list
*lvs_changed
)
54 struct lv_segment
*snap_seg
;
55 struct dm_list
*snh
, *snht
;
56 struct logical_volume
*cow
;
61 log_verbose("%s/%s has missing extents: removing (including "
62 "dependencies)", lv
->vg
->name
, lv
->name
);
64 /* FIXME Cope properly with stacked devices & snapshots. */
66 /* If snapshot device is missing, deactivate origin. */
67 if (lv_is_cow(lv
) && (snap_seg
= find_cow(lv
))) {
68 log_verbose("Deactivating (if active) logical volume %s "
69 "(origin of %s)", snap_seg
->origin
->name
, lv
->name
);
71 if (!test_mode() && !deactivate_lv(cmd
, snap_seg
->origin
)) {
72 log_error("Failed to deactivate LV %s",
73 snap_seg
->origin
->name
);
77 /* Use the origin LV */
78 lv
= snap_seg
->origin
;
81 /* Remove snapshot dependencies */
82 dm_list_iterate_safe(snh
, snht
, &lv
->snapshot_segs
) {
83 snap_seg
= dm_list_struct_base(snh
, struct lv_segment
,
87 if (first
&& !test_mode() &&
88 !deactivate_lv(cmd
, snap_seg
->origin
)) {
89 log_error("Failed to deactivate LV %s",
90 snap_seg
->origin
->name
);
94 *list_unsafe
= 1; /* May remove caller's lvht! */
95 if (!vg_remove_snapshot(cow
))
97 log_verbose("Removing LV %s from VG %s", cow
->name
,
106 * If LV is active, replace it with error segment
107 * and add to list of LVs to be removed later.
108 * Doesn't apply to snapshots/origins yet - they're already deactivated.
111 * If the LV is a part of mirror segment,
112 * the mirrored LV also should be cleaned up.
113 * Clean-up is currently done by caller (_make_vg_consistent()).
115 if ((lv_info(cmd
, lv
, &info
, 0, 0) && info
.exists
) ||
116 find_mirror_seg(first_seg(lv
))) {
117 if (!replace_lv_with_error_segment(lv
))
120 if (!(lvl
= dm_pool_alloc(cmd
->mem
, sizeof(*lvl
)))) {
121 log_error("lv_list alloc failed");
125 dm_list_add(lvs_changed
, &lvl
->list
);
127 /* Remove LV immediately. */
128 log_verbose("Removing LV %s from VG %s", lv
->name
, lv
->vg
->name
);
136 static int _consolidate_vg(struct cmd_context
*cmd
, struct volume_group
*vg
)
142 dm_list_iterate_items(lvl
, &vg
->lvs
)
143 if (lvl
->lv
->status
& PARTIAL_LV
) {
144 log_warn("WARNING: Partial LV %s needs to be repaired "
145 "or removed. ", lvl
->lv
->name
);
150 cmd
->handles_missing_pvs
= 1;
151 log_warn("WARNING: There are still partial LVs in VG %s.", vg
->name
);
152 log_warn("To remove them unconditionally use: vgreduce --removemissing --force.");
153 log_warn("Proceeding to remove empty missing PVs.");
156 dm_list_iterate_items(pvl
, &vg
->pvs
) {
157 if (pvl
->pv
->dev
&& !(pvl
->pv
->status
& MISSING_PV
))
159 if (r
&& !_remove_pv(vg
, pvl
, 0))
166 static int _make_vg_consistent(struct cmd_context
*cmd
, struct volume_group
*vg
)
168 struct dm_list
*pvh
, *pvht
;
169 struct dm_list
*lvh
, *lvht
;
171 struct lv_list
*lvl
, *lvl2
, *lvlt
;
172 struct logical_volume
*lv
;
173 struct physical_volume
*pv
;
174 struct lv_segment
*seg
, *mirrored_seg
;
176 uint32_t mimages
, remove_log
;
177 int list_unsafe
, only_mirror_images_found
;
178 DM_LIST_INIT(lvs_changed
);
179 only_mirror_images_found
= 1;
181 /* Deactivate & remove necessary LVs */
183 list_unsafe
= 0; /* Set if we delete a different list-member */
185 dm_list_iterate_safe(lvh
, lvht
, &vg
->lvs
) {
186 lv
= dm_list_item(lvh
, struct lv_list
)->lv
;
188 /* Are any segments of this LV on missing PVs? */
189 dm_list_iterate_items(seg
, &lv
->segments
) {
190 for (s
= 0; s
< seg
->area_count
; s
++) {
191 if (seg_type(seg
, s
) != AREA_PV
)
194 /* FIXME Also check for segs on deleted LVs (incl pvmove) */
197 if (!pv
|| !pv_dev(pv
) ||
198 (pv
->status
& MISSING_PV
)) {
199 if (arg_count(cmd
, mirrorsonly_ARG
) &&
200 !(lv
->status
& MIRROR_IMAGE
)) {
201 log_error("Non-mirror-image LV %s found: can't remove.", lv
->name
);
202 only_mirror_images_found
= 0;
205 if (!_remove_lv(cmd
, lv
, &list_unsafe
, &lvs_changed
))
214 if (!only_mirror_images_found
) {
215 log_error("Aborting because --mirrorsonly was specified.");
220 * Remove missing PVs. FIXME: This duplicates _consolidate_vg above,
221 * but we cannot use that right now, since the LV removal code in this
222 * function leaves the VG in a "somewhat inconsistent" state and
223 * _consolidate_vg doesn't like that -- specifically, mirrors are fixed
224 * up *after* the PVs are removed. All this should be gradually
225 * superseded by lvconvert --repair.
227 dm_list_iterate_safe(pvh
, pvht
, &vg
->pvs
) {
228 pvl
= dm_list_item(pvh
, struct pv_list
);
231 if (!_remove_pv(vg
, pvl
, 0))
235 /* FIXME Recovery. For now people must clean up by hand. */
237 if (!dm_list_empty(&lvs_changed
)) {
239 log_error("Failed to write out a consistent VG for %s",
245 /* Suspend lvs_changed */
246 if (!suspend_lvs(cmd
, &lvs_changed
)) {
253 if (!vg_commit(vg
)) {
254 log_error("Failed to commit consistent VG for %s",
261 if (!resume_lvs(cmd
, &lvs_changed
)) {
262 log_error("Failed to resume LVs using error segments.");
268 /* Remove lost mirror images from mirrors */
269 dm_list_iterate_items(lvl
, &vg
->lvs
) {
270 mirrored_seg_altered
:
271 mirrored_seg
= first_seg(lvl
->lv
);
272 if (!seg_is_mirrored(mirrored_seg
))
275 mimages
= mirrored_seg
->area_count
;
278 for (s
= 0; s
< mirrored_seg
->area_count
; s
++) {
279 dm_list_iterate_items_safe(lvl2
, lvlt
, &lvs_changed
) {
280 if (seg_type(mirrored_seg
, s
) != AREA_LV
||
281 lvl2
->lv
!= seg_lv(mirrored_seg
, s
))
283 dm_list_del(&lvl2
->list
);
284 if (!shift_mirror_images(mirrored_seg
, s
))
286 mimages
--; /* FIXME Assumes uniqueness */
290 if (mirrored_seg
->log_lv
) {
291 dm_list_iterate_items(seg
, &mirrored_seg
->log_lv
->segments
) {
292 /* FIXME: The second test shouldn't be required */
294 get_segtype_from_string(vg
->cmd
, "error"))) {
295 log_print("The log device for %s/%s has failed.",
296 vg
->name
, mirrored_seg
->lv
->name
);
300 if (!strcmp(seg
->segtype
->name
, "error")) {
301 log_print("Log device for %s/%s has failed.",
302 vg
->name
, mirrored_seg
->lv
->name
);
309 if ((mimages
!= mirrored_seg
->area_count
) || remove_log
){
310 if (!reconfigure_mirror_images(mirrored_seg
, mimages
,
315 log_error("Failed to write out updated "
316 "VG for %s", vg
->name
);
320 if (!vg_commit(vg
)) {
321 log_error("Failed to commit updated VG "
327 /* mirrored LV no longer has valid mimages.
328 * So add it to lvs_changed for removal.
329 * For this LV may be an area of other mirror,
330 * restart the loop. */
332 if (!_remove_lv(cmd
, lvl
->lv
,
333 &list_unsafe
, &lvs_changed
))
335 goto lvs_changed_altered
;
338 /* As a result of reconfigure_mirror_images(),
339 * first_seg(lv) may now be different seg.
340 * e.g. a temporary layer might be removed.
341 * So check the mirrored_seg again. */
342 goto mirrored_seg_altered
;
346 /* Deactivate error LVs */
348 dm_list_iterate_items_safe(lvl
, lvlt
, &lvs_changed
) {
349 log_verbose("Deactivating (if active) logical volume %s",
352 if (!deactivate_lv(cmd
, lvl
->lv
)) {
353 log_error("Failed to deactivate LV %s",
356 * We failed to deactivate.
357 * Probably because this was a mirror log.
358 * Don't try to lv_remove it.
359 * Continue work on others.
361 dm_list_del(&lvl
->list
);
366 /* Remove remaining LVs */
367 dm_list_iterate_items(lvl
, &lvs_changed
) {
368 log_verbose("Removing LV %s from VG %s", lvl
->lv
->name
,
370 /* Skip LVs already removed by mirror code */
371 if (find_lv_in_vg(vg
, lvl
->lv
->name
) &&
380 /* Or take pv_name instead? */
381 static int _vgreduce_single(struct cmd_context
*cmd
, struct volume_group
*vg
,
382 struct physical_volume
*pv
,
383 void *handle
__attribute((unused
)))
386 struct volume_group
*orphan_vg
= NULL
;
388 const char *name
= pv_dev_name(pv
);
390 if (pv_pe_alloc_count(pv
)) {
391 log_error("Physical volume \"%s\" still in use", name
);
395 if (vg
->pv_count
== 1) {
396 log_error("Can't remove final physical volume \"%s\" from "
397 "volume group \"%s\"", name
, vg
->name
);
401 if (!lock_vol(cmd
, VG_ORPHANS
, LCK_VG_WRITE
)) {
402 log_error("Can't get lock for orphan PVs");
406 pvl
= find_pv_in_vg(vg
, name
);
411 log_verbose("Removing \"%s\" from volume group \"%s\"", name
, vg
->name
);
414 dm_list_del(&pvl
->list
);
416 pv
->vg_name
= vg
->fid
->fmt
->orphan_vg_name
;
417 pv
->status
= ALLOCATABLE_PV
;
419 if (!dev_get_size(pv_dev(pv
), &pv
->size
)) {
420 log_error("%s: Couldn't get size.", pv_dev_name(pv
));
425 vg
->free_count
-= pv_pe_count(pv
) - pv_pe_alloc_count(pv
);
426 vg
->extent_count
-= pv_pe_count(pv
);
428 orphan_vg
= vg_read_for_update(cmd
, vg
->fid
->fmt
->orphan_vg_name
,
431 if (vg_read_error(orphan_vg
))
434 if (!vg_split_mdas(cmd
, vg
, orphan_vg
) || !vg
->pv_count
) {
435 log_error("Cannot remove final metadata area on \"%s\" from \"%s\"",
440 if (!vg_write(vg
) || !vg_commit(vg
)) {
441 log_error("Removal of physical volume \"%s\" from "
442 "\"%s\" failed", name
, vg
->name
);
446 if (!pv_write(cmd
, pv
, NULL
, INT64_C(-1))) {
447 log_error("Failed to clear metadata from physical "
449 "after removal from \"%s\"", name
, vg
->name
);
455 log_print("Removed \"%s\" from volume group \"%s\"", name
, vg
->name
);
458 unlock_and_release_vg(cmd
, orphan_vg
, VG_ORPHANS
);
462 int vgreduce(struct cmd_context
*cmd
, int argc
, char **argv
)
464 struct volume_group
*vg
;
466 int ret
= ECMD_FAILED
;
468 int repairing
= arg_count(cmd
, removemissing_ARG
);
469 int saved_ignore_suspended_devices
= ignore_suspended_devices();
471 if (!argc
&& !repairing
) {
472 log_error("Please give volume group name and "
473 "physical volume paths");
474 return EINVALID_CMD_LINE
;
477 if (!argc
&& repairing
) {
478 log_error("Please give volume group name");
479 return EINVALID_CMD_LINE
;
482 if (arg_count(cmd
, mirrorsonly_ARG
) && !repairing
) {
483 log_error("--mirrorsonly requires --removemissing");
484 return EINVALID_CMD_LINE
;
487 if (argc
== 1 && !arg_count(cmd
, all_ARG
) && !repairing
) {
488 log_error("Please enter physical volume paths or option -a");
489 return EINVALID_CMD_LINE
;
492 if (argc
> 1 && arg_count(cmd
, all_ARG
)) {
493 log_error("Option -a and physical volume paths mutually "
495 return EINVALID_CMD_LINE
;
498 if (argc
> 1 && repairing
) {
499 log_error("Please only specify the volume group");
500 return EINVALID_CMD_LINE
;
503 vg_name
= skip_dev_dir(cmd
, argv
[0], NULL
);
507 log_verbose("Finding volume group \"%s\"", vg_name
);
510 init_ignore_suspended_devices(1);
511 cmd
->handles_missing_pvs
= 1;
514 vg
= vg_read_for_update(cmd
, vg_name
, NULL
, READ_ALLOW_EXPORTED
);
515 if (vg_read_error(vg
) == FAILED_ALLOCATION
||
516 vg_read_error(vg
) == FAILED_NOTFOUND
)
519 /* FIXME We want to allow read-only VGs to be changed here? */
520 if (vg_read_error(vg
) && vg_read_error(vg
) != FAILED_READ_ONLY
521 && !arg_count(cmd
, removemissing_ARG
))
525 if (!vg_read_error(vg
) && !vg_missing_pv_count(vg
)) {
526 log_error("Volume group \"%s\" is already consistent",
528 ret
= ECMD_PROCESSED
;
533 log_verbose("Trying to open VG %s for recovery...", vg_name
);
535 vg
= vg_read_for_update(cmd
, vg_name
, NULL
,
536 READ_ALLOW_INCONSISTENT
537 | READ_ALLOW_EXPORTED
);
539 if (vg_read_error(vg
) && vg_read_error(vg
) != FAILED_READ_ONLY
540 && vg_read_error(vg
) != FAILED_INCONSISTENT
)
546 if (arg_count(cmd
, force_ARG
)) {
547 if (!_make_vg_consistent(cmd
, vg
))
550 fixed
= _consolidate_vg(cmd
, vg
);
552 if (!vg_write(vg
) || !vg_commit(vg
)) {
553 log_error("Failed to write out a consistent VG for %s",
560 log_print("Wrote out consistent volume group %s",
562 ret
= ECMD_PROCESSED
;
567 if (!vg_check_status(vg
, EXPORTED_VG
| LVM_WRITE
| RESIZEABLE_VG
))
570 /* FIXME: Pass private struct through to all these functions */
571 /* and update in batch here? */
572 ret
= process_each_pv(cmd
, argc
, argv
, vg
, READ_FOR_UPDATE
, 0, NULL
,
577 init_ignore_suspended_devices(saved_ignore_suspended_devices
);
578 unlock_and_release_vg(cmd
, vg
, vg_name
);
583 log_error ("no empty physical volumes found in volume group \"%s\"", vg_name);
586 ("volume group \"%s\" will be reduced by %d physical volume%s",
587 vg_name, np, np > 1 ? "s" : "");
588 log_verbose ("reducing volume group \"%s\" by physical volume \"%s\"",
589 vg_name, pv_names[p]);
592 ("volume group \"%s\" %ssuccessfully reduced by physical volume%s:",
593 vg_name, error > 0 ? "NOT " : "", p > 1 ? "s" : "");
594 log_print("%s", pv_this[p]->pv_name);