[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[lvm-devel] [DRAFT] [PATCH] vgreduce --removemissing --force refactor



Hello,

this is just a heads-up patch for vgreduce. It is *not* intended to be
merged until the tests pass, which blocks on the _remove_mirror_images
fixes mentioned earlier. As you can see, it removes quite a lot of code,
so I am eager to get this through.

A quick "sanity" check on the patch would be appreciated, though.

Yours,
   Petr

Index: tools/vgreduce.c
===================================================================
RCS file: /cvs/lvm2/LVM2/tools/vgreduce.c,v
retrieving revision 1.105
diff -u -p -r1.105 vgreduce.c
--- tools/vgreduce.c	8 Dec 2010 20:50:51 -0000	1.105
+++ tools/vgreduce.c	16 Feb 2011 09:25:29 -0000
@@ -15,6 +15,7 @@
 
 #include "tools.h"
 #include "lv_alloc.h"
+#include "lvconvert.h"
 
 static int _remove_pv(struct volume_group *vg, struct pv_list *pvl, int silent)
 {
@@ -44,91 +45,6 @@ static int _remove_pv(struct volume_grou
 	return 1;
 }
 
-static int _remove_lv(struct cmd_context *cmd, struct logical_volume *lv,
-		      int *list_unsafe, struct dm_list *lvs_changed)
-{
-	struct lv_segment *snap_seg;
-	struct dm_list *snh, *snht;
-	struct logical_volume *cow;
-	struct lv_list *lvl;
-	struct lvinfo info;
-	int first = 1;
-
-	log_verbose("%s/%s has missing extents: removing (including "
-		    "dependencies)", lv->vg->name, lv->name);
-
-	/* FIXME Cope properly with stacked devices & snapshots. */
-
-	/* If snapshot device is missing, deactivate origin. */
-	if (lv_is_cow(lv) && (snap_seg = find_cow(lv))) {
-		log_verbose("Deactivating (if active) logical volume %s "
-			    "(origin of %s)", snap_seg->origin->name, lv->name);
-
-		if (!test_mode() && !deactivate_lv(cmd, snap_seg->origin)) {
-			log_error("Failed to deactivate LV %s",
-				  snap_seg->origin->name);
-			return 0;
-		}
-
-		/* Use the origin LV */
-		lv = snap_seg->origin;
-	}
-
-	/* Remove snapshot dependencies */
-	dm_list_iterate_safe(snh, snht, &lv->snapshot_segs) {
-		snap_seg = dm_list_struct_base(snh, struct lv_segment,
-					    origin_list);
-		cow = snap_seg->cow;
-
-		if (first && !test_mode() &&
-		    !deactivate_lv(cmd, snap_seg->origin)) {
-			log_error("Failed to deactivate LV %s",
-				  snap_seg->origin->name);
-			return 0;
-		}
-
-		*list_unsafe = 1;	/* May remove caller's lvht! */
-		if (!vg_remove_snapshot(cow))
-			return_0;
-		log_verbose("Removing LV %s from VG %s", cow->name,
-			    lv->vg->name);
-		if (!lv_remove(cow))
-			return_0;
-
-		first = 0;
-	}
-
-	/*
-	 * If LV is active, replace it with error segment
-	 * and add to list of LVs to be removed later.
-	 * Doesn't apply to snapshots/origins yet - they're already deactivated.
-	 */
-	/*
-	 * If the LV is a part of mirror segment,
-	 * the mirrored LV also should be cleaned up.
-	 * Clean-up is currently done by caller (_make_vg_consistent()).
-	 */
-	if ((lv_info(cmd, lv, 0, &info, 0, 0) && info.exists) ||
-	    find_mirror_seg(first_seg(lv))) {
-		if (!replace_lv_with_error_segment(lv))
-			return_0;
-
-		if (!(lvl = dm_pool_alloc(cmd->mem, sizeof(*lvl)))) {
-			log_error("lv_list alloc failed");
-			return 0;
-		}
-		lvl->lv = lv;
-		dm_list_add(lvs_changed, &lvl->list);
-	} else {
-		/* Remove LV immediately. */
-		log_verbose("Removing LV %s from VG %s", lv->name, lv->vg->name);
-		if (!lv_remove(lv))
-			return_0;
-	}
-
-	return 1;
-}
-
 static int _consolidate_vg(struct cmd_context *cmd, struct volume_group *vg)
 {
 	struct pv_list *pvl;
@@ -161,215 +77,40 @@ static int _consolidate_vg(struct cmd_co
 
 static int _make_vg_consistent(struct cmd_context *cmd, struct volume_group *vg)
 {
-	struct dm_list *pvh, *pvht;
-	struct dm_list *lvh, *lvht;
-	struct pv_list *pvl;
-	struct lv_list *lvl, *lvl2, *lvlt;
+	struct lv_list *lvl;
 	struct logical_volume *lv;
-	struct physical_volume *pv;
-	struct lv_segment *seg, *mirrored_seg;
-	unsigned s;
-	uint32_t mimages, remove_log;
-	int list_unsafe, only_mirror_images_found;
-	DM_LIST_INIT(lvs_changed);
-	only_mirror_images_found = 1;
-
-	/* Deactivate & remove necessary LVs */
-      restart_loop:
-	list_unsafe = 0;	/* Set if we delete a different list-member */
-
-	dm_list_iterate_safe(lvh, lvht, &vg->lvs) {
-		lv = dm_list_item(lvh, struct lv_list)->lv;
-
-		/* Are any segments of this LV on missing PVs? */
-		dm_list_iterate_items(seg, &lv->segments) {
-			for (s = 0; s < seg->area_count; s++) {
-				if (seg_type(seg, s) != AREA_PV)
-					continue;
-
-				/* FIXME Also check for segs on deleted LVs (incl pvmove) */
-
-				pv = seg_pv(seg, s);
-				if (!pv || !pv_dev(pv) ||
-				    is_missing_pv(pv)) {
-					if (arg_count(cmd, mirrorsonly_ARG) &&
-					    !(lv->status & MIRROR_IMAGE)) {
-						log_error("Non-mirror-image LV %s found: can't remove.", lv->name);
-						only_mirror_images_found = 0;
-						continue;
-					}
-					if (!_remove_lv(cmd, lv, &list_unsafe, &lvs_changed))
-						return_0;
-					if (list_unsafe)
-						goto restart_loop;
-				}
-			}
-		}
-	}
 
-	if (!only_mirror_images_found) {
-		log_error("Aborting because --mirrorsonly was specified.");
-		return 0;
-	}
-
-	/*
-	 * Remove missing PVs. FIXME: This duplicates _consolidate_vg above,
-	 * but we cannot use that right now, since the LV removal code in this
-	 * function leaves the VG in a "somewhat inconsistent" state and
-	 * _consolidate_vg doesn't like that -- specifically, mirrors are fixed
-	 * up *after* the PVs are removed. All this should be gradually
-	 * superseded by lvconvert --repair.
-	 */
-	dm_list_iterate_safe(pvh, pvht, &vg->pvs) {
-		pvl = dm_list_item(pvh, struct pv_list);
-		if (pvl->pv->dev && !is_missing_pv(pvl->pv))
-			continue;
-		if (!_remove_pv(vg, pvl, 0))
-			return_0;
-	}
-
-	/* FIXME Recovery.  For now people must clean up by hand. */
-
-	if (!dm_list_empty(&lvs_changed)) {
-		if (!vg_write(vg)) {
-			log_error("Failed to write out a consistent VG for %s",
-				  vg->name);
-			return 0;
-		}
-
-		if (!test_mode()) {
-			/* Suspend lvs_changed */
-			if (!suspend_lvs(cmd, &lvs_changed)) {
-				stack;
-				vg_revert(vg);
-				return 0;
-			}
-		}
-
-		if (!vg_commit(vg)) {
-			log_error("Failed to commit consistent VG for %s",
-				  vg->name);
-			vg_revert(vg);
-			return 0;
-		}
-
-		if (!test_mode()) {
-			if (!resume_lvs(cmd, &lvs_changed)) {
-				log_error("Failed to resume LVs using error segments.");
-				return 0;
-			}
-		}
+	cmd->partial_activation = 1;
 
-  lvs_changed_altered:
-		/* Remove lost mirror images from mirrors */
-		dm_list_iterate_items(lvl, &vg->lvs) {
-  mirrored_seg_altered:
-			mirrored_seg = first_seg(lvl->lv);
-			if (!seg_is_mirrored(mirrored_seg))
-				continue;
+ restart:
+	vg_mark_partial_lvs(vg);
 
-			mimages = mirrored_seg->area_count;
-			remove_log = 0;
-
-			for (s = 0; s < mirrored_seg->area_count; s++) {
-				dm_list_iterate_items_safe(lvl2, lvlt, &lvs_changed) {
-					if (seg_type(mirrored_seg, s) != AREA_LV ||
-					    lvl2->lv != seg_lv(mirrored_seg, s))
-						continue;
-					dm_list_del(&lvl2->list);
-					if (!shift_mirror_images(mirrored_seg, s))
-						return_0;
-					mimages--;	/* FIXME Assumes uniqueness */
-				}
-			}
+	dm_list_iterate_items(lvl, &vg->lvs) {
+		lv = lvl->lv;
 
-			if (mirrored_seg->log_lv) {
-				dm_list_iterate_items(seg, &mirrored_seg->log_lv->segments) {
-					/* FIXME: The second test shouldn't be required */
-					if ((seg->segtype ==
-					     get_segtype_from_string(vg->cmd, "error"))) {
-						log_print("The log device for %s/%s has failed.",
-							  vg->name, mirrored_seg->lv->name);
-						remove_log = 1;
-						break;
-					}
-					if (!strcmp(seg->segtype->name, "error")) {
-						log_print("Log device for %s/%s has failed.",
-							  vg->name, mirrored_seg->lv->name);
-						remove_log = 1;
-						break;
-					}
-				}
-			}
-
-			if ((mimages != mirrored_seg->area_count) || remove_log){
-				if (!reconfigure_mirror_images(mirrored_seg, mimages,
-							       NULL, remove_log))
+		/* Are any segments of this LV on missing PVs? */
+                if (lv->status & PARTIAL_LV) {
+			if (lv->status & MIRRORED) {
+				if (!mirror_remove_missing(cmd, lv))
 					return_0;
-
-				if (!vg_write(vg)) {
-					log_error("Failed to write out updated "
-						  "VG for %s", vg->name);
-					return 0;
-				}
-		
-				if (!vg_commit(vg)) {
-					log_error("Failed to commit updated VG "
-						  "for %s", vg->name);
-					vg_revert(vg);
-					return 0;
-				}
-
-				/* mirrored LV no longer has valid mimages.
-				 * So add it to lvs_changed for removal.
-				 * For this LV may be an area of other mirror,
-				 * restart the loop. */
-				if (!mimages) {
-					if (!_remove_lv(cmd, lvl->lv,
-						 &list_unsafe, &lvs_changed))
-						return_0;
-					goto lvs_changed_altered;
-				}
-
-				/* As a result of reconfigure_mirror_images(),
-				 * first_seg(lv) may now be different seg.
-				 * e.g. a temporary layer might be removed.
-				 * So check the mirrored_seg again. */
-				goto mirrored_seg_altered;
+				goto restart;
 			}
-		}
-
-		/* Deactivate error LVs */
-		if (!test_mode()) {
-			dm_list_iterate_items_safe(lvl, lvlt, &lvs_changed) {
-				log_verbose("Deactivating (if active) logical volume %s",
-					    lvl->lv->name);
-
-				if (!deactivate_lv(cmd, lvl->lv)) {
-					log_error("Failed to deactivate LV %s",
-						  lvl->lv->name);
-					/*
-					 * We failed to deactivate.
-					 * Probably because this was a mirror log.
-					 * Don't try to lv_remove it.
-					 * Continue work on others.
-					 */
-					dm_list_del(&lvl->list);
-				}
+			if (arg_count(cmd, mirrorsonly_ARG) &&
+			    !(lv->status & MIRRORED)) {
+				log_error("Non-mirror-image LV %s found: can't remove.", lv->name);
+				continue;
 			}
-		}
-
-		/* Remove remaining LVs */
-		dm_list_iterate_items(lvl, &lvs_changed) {
-			log_verbose("Removing LV %s from VG %s", lvl->lv->name,
-				    lvl->lv->vg->name);
-				/* Skip LVs already removed by mirror code */
-				if (find_lv_in_vg(vg, lvl->lv->name) &&
-				    !lv_remove(lvl->lv))
-					return_0;
+			if (!lv_is_visible(lv))
+				continue;
+			log_error("Removing: %s", lv->name);
+			if (!lv_remove_with_dependencies(cmd, lv, 1, 0))
+				return_0;
+			goto restart;
 		}
 	}
 
+	_consolidate_vg(cmd, vg);
+
 	return 1;
 }
 
-- 
id' Ash = Ash; id' Dust = Dust; id' _ = undefined

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]