All of lore.kernel.org
 help / color / mirror / Atom feed
* [linux-lvm] [PATCH LVM2 0/2] fix alloc anywhere and addition of disklog
@ 2006-09-22 22:27 Jun'ichi Nomura
  2006-09-22 22:31 ` [linux-lvm] [PATCH LVM2 1/2] fix mirror allocation Jun'ichi Nomura
  2006-09-22 22:33 ` [linux-lvm] [PATCH LVM2 2/2] fix lvconvert to setup mirror constraints Jun'ichi Nomura
  0 siblings, 2 replies; 3+ messages in thread
From: Jun'ichi Nomura @ 2006-09-22 22:27 UTC (permalink / raw)
  To: linux-lvm, Alasdair Kergon, Jonathan Brassow

[-- Attachment #1: Type: text/plain, Size: 1350 bytes --]

Hi,

Following patches will fix 2 problems:
  - 'lvcreate --alloc anywhere' cannot allocates log
    on the same PV with mimage. This prevents us to create a mirror LV
    on a VG with 2 PVs.
  - 'lvconvert' from corelog allocates log from the same PV
    with other image. It spoils redundancy.
(See attached metadata for examples)

This patch does the following changes:
  (1/2) fix-mirror-alloc-anywhere.patch
          - split log specific parts from _find_parallel_space() and
            _alloc_parallel_area()
          - determine log PV before doing other allocation
          - use constraints correctly
             * log allocation should avoid all PVs used by other parts of the LV
             * other allocation should avoid log PV and parallel PVs of
               corresponding lv segment (unchanged)
  (2/2) fix-lvconvert-allocate-disklog.patch
          - lvconvert to setup constraints properly

The 2nd patch itself is trivial and depends on the 1st patch for
the allocation logic to work correctly.

The patch has no effects on non-mirror allocation.
The patch was tested on the combinations of following scenarios:
  - normal or anywhere allocation policy
  - creation, corelog to disklog conversion, or linear to mirror conversion
  - VG with 2 PVs or more than 2 PVs

Thanks,
-- 
Jun'ichi Nomura, NEC Corporation of America

[-- Attachment #2: testvg0-lvconvert-corelog.vg --]
[-- Type: text/plain, Size: 1985 bytes --]

# Generated by LVM2: Fri Sep 15 01:52:07 2006

contents = "Text Format Volume Group"
version = 1

description = "Created *before* executing 'lvconvert -m 1 testvg0/lv0'"

creation_host = "tetsuo.lab"	# Linux tetsuo.lab 2.6.9-42.ELsmp #1 SMP Wed Jul 12 23:27:17 EDT 2006 i686
creation_time = 1158299527	# Fri Sep 15 01:52:07 2006

testvg0 {
	id = "a5E2Nr-71Z7-YhaJ-PPto-QJaO-UwVR-Xux2tO"
	seqno = 2
	status = ["RESIZEABLE", "READ", "WRITE"]
	extent_size = 8192		# 4 Megabytes
	max_lv = 0
	max_pv = 0

	physical_volumes {

		pv0 {
			id = "1W9Pf5-JK1B-1zdo-qayI-lIch-4rPc-Dr6X8J"
			device = "/dev/dm-0"	# Hint only

			status = ["ALLOCATABLE"]
			pe_start = 384
			pe_count = 4	# 16 Megabytes
		}

		pv1 {
			id = "hMbR7i-RqtC-PpKK-2iZD-CMnX-yytR-S2mrH6"
			device = "/dev/dm-1"	# Hint only

			status = ["ALLOCATABLE"]
			pe_start = 384
			pe_count = 4	# 16 Megabytes
		}

		pv2 {
			id = "guSc2r-Tw4k-akM5-tjZ5-6V9m-hwCB-faY10J"
			device = "/dev/dm-2"	# Hint only

			status = ["ALLOCATABLE"]
			pe_start = 384
			pe_count = 4	# 16 Megabytes
		}
	}

	logical_volumes {

		lv0 {
			id = "y13S23-cGCp-NcJU-45vy-yQuz-v231-lNkFi1"
			status = ["READ", "WRITE", "VISIBLE"]
			segment_count = 1

			segment1 {
				start_extent = 0
				extent_count = 1	# 4 Megabytes

				type = "mirror"
				mirror_count = 2
				region_size = 1024

				mirrors = [
					"lv0_mimage_0", 0,
					"lv0_mimage_1", 0
				]
			}
		}

		lv0_mimage_0 {
			id = "vi2BZp-1W9W-T42S-AX6w-kIqC-bMtn-bOtxdQ"
			status = ["READ", "WRITE"]
			segment_count = 1

			segment1 {
				start_extent = 0
				extent_count = 1	# 4 Megabytes

				type = "striped"
				stripe_count = 1	# linear

				stripes = [
					"pv0", 0
				]
			}
		}

		lv0_mimage_1 {
			id = "G0SqFV-YW3K-C33U-zl2I-PvG8-QGus-i0ivzn"
			status = ["READ", "WRITE"]
			segment_count = 1

			segment1 {
				start_extent = 0
				extent_count = 1	# 4 Megabytes

				type = "striped"
				stripe_count = 1	# linear

				stripes = [
					"pv1", 0
				]
			}
		}
	}
}

[-- Attachment #3: testvg0-lvcreate-anywhere.vg --]
[-- Type: text/plain, Size: 883 bytes --]

# Generated by LVM2: Fri Sep 15 01:53:14 2006

contents = "Text Format Volume Group"
version = 1

description = "Created *before* executing 'lvcreate -l1 -m1 -n lv0 testvg0'"

creation_host = "tetsuo.lab"	# Linux tetsuo.lab 2.6.9-42.ELsmp #1 SMP Wed Jul 12 23:27:17 EDT 2006 i686
creation_time = 1158299594	# Fri Sep 15 01:53:14 2006

testvg0 {
	id = "UxVVG5-H6xQ-VSBn-2RLF-xKKX-R0e6-XIRZ7j"
	seqno = 1
	status = ["RESIZEABLE", "READ", "WRITE"]
	extent_size = 8192		# 4 Megabytes
	max_lv = 0
	max_pv = 0

	physical_volumes {

		pv0 {
			id = "b3vmJK-Ez6R-ZemQ-7IMp-Xid3-PXXu-pqzIEc"
			device = "/dev/dm-0"	# Hint only

			status = ["ALLOCATABLE"]
			pe_start = 384
			pe_count = 4	# 16 Megabytes
		}

		pv1 {
			id = "UkeYvg-AR5E-soSC-PImG-upyk-O11S-fkfANu"
			device = "/dev/dm-1"	# Hint only

			status = ["ALLOCATABLE"]
			pe_start = 384
			pe_count = 4	# 16 Megabytes
		}
	}

}

^ permalink raw reply	[flat|nested] 3+ messages in thread

* [linux-lvm] [PATCH LVM2 1/2] fix mirror allocation
  2006-09-22 22:27 [linux-lvm] [PATCH LVM2 0/2] fix alloc anywhere and addition of disklog Jun'ichi Nomura
@ 2006-09-22 22:31 ` Jun'ichi Nomura
  2006-09-22 22:33 ` [linux-lvm] [PATCH LVM2 2/2] fix lvconvert to setup mirror constraints Jun'ichi Nomura
  1 sibling, 0 replies; 3+ messages in thread
From: Jun'ichi Nomura @ 2006-09-22 22:31 UTC (permalink / raw)
  To: linux-lvm, Alasdair Kergon, Jonathan Brassow

[-- Attachment #1: Type: text/plain, Size: 323 bytes --]

This patch fixes this problem
  - 'lvcreate --alloc anywhere' cannot allocates log
    on the same PV with mimage. This prevents us to create a mirror LV
    on a VG with 2 PVs.
and also fixes other potential problems of mirror allocation
not avoiding PVs properly.

Thanks,
-- 
Jun'ichi Nomura, NEC Corporation of America

[-- Attachment #2: fix-mirror-alloc-anywhere.patch --]
[-- Type: text/x-patch, Size: 7038 bytes --]

diff -X dontdiff -urp LVM2/lib/metadata/lv_manip.c LVM2.fixed/lib/metadata/lv_manip.c
--- LVM2/lib/metadata/lv_manip.c	2006-08-29 21:27:56.000000000 -0400
+++ LVM2.fixed/lib/metadata/lv_manip.c	2006-09-23 02:54:32.000000000 -0400
@@ -573,13 +573,28 @@ static int _setup_alloced_segments(struc
 }
 
 /*
+ * allocate log area from given pv_area
+ */
+static int _alloc_log_area(struct alloc_handle *ah, uint32_t log_extents,
+			   struct pv_area *log_area)
+{
+	if (log_area) {
+		ah->log_area.pv = log_area->map->pv;
+		ah->log_area.pe = log_area->start;
+		ah->log_area.len = log_extents;
+		consume_pv_area(log_area, ah->log_area.len);
+	}
+
+	return 1;
+}
+
+/*
  * This function takes a list of pv_areas and adds them to allocated_areas.
  * If the complete area is not needed then it gets split.
  * The part used is removed from the pv_map so it can't be allocated twice.
  */
 static int _alloc_parallel_area(struct alloc_handle *ah, uint32_t needed,
-				struct pv_area **areas,
-				uint32_t *ix, struct pv_area *log_area)
+				struct pv_area **areas, uint32_t *ix)
 {
 	uint32_t area_len, smallest, remaining;
 	uint32_t s;
@@ -593,8 +608,7 @@ static int _alloc_parallel_area(struct a
 	if (area_len > smallest)
 		area_len = smallest;
 
-	if (!(aa = dm_pool_alloc(ah->mem, sizeof(*aa) *
-			      (ah->area_count + (log_area ? 1 : 0))))) {
+	if (!(aa = dm_pool_alloc(ah->mem, sizeof(*aa) * ah->area_count))) {
 		log_error("alloced_area allocation failed");
 		return 0;
 	}
@@ -611,13 +625,6 @@ static int _alloc_parallel_area(struct a
 	for (s = 0; s < ah->area_count; s++)
 		consume_pv_area(areas[s], area_len);
 
-	if (log_area) {
-		ah->log_area.pv = log_area->map->pv;
-		ah->log_area.pe = log_area->start;
-		ah->log_area.len = 1;	/* FIXME Calculate & check this */
-		consume_pv_area(log_area, ah->log_area.len);
-	}
-
 	*ix += area_len * ah->area_multiple;
 
 	return 1;
@@ -679,6 +686,102 @@ static int _check_contiguous(struct lv_s
 }
 
 /*
+ * returns 1 if given pv is found in the list of pvs.
+ *
+ * The list of PVs can be given in either or both of 2 ways:
+ *    by parallel_areas list in allocation handle
+ * and/or
+ *    by list of struct pv_list
+ */
+static int is_pv_parallel(struct physical_volume* pv,
+			  struct alloc_handle *ah, struct list *list)
+{
+	struct seg_pvs *spvs;
+	struct pv_list *pvl;
+
+	if (ah && ah->parallel_areas) {
+		list_iterate_items(spvs, ah->parallel_areas)
+			list_iterate_items(pvl, &spvs->pvs)
+				if (pv == pvl->pv)
+					return 1;
+	}
+
+	if (list) {
+		list_iterate_items(pvl, list)
+			if (pv == pvl->pv)
+				return 1;
+	}
+
+	return 0;
+}
+
+/*
+ * find smallest area fit to the log size
+ * avoiding all PVs in ah->parallel_areas
+ */
+/*
+ * FIXME _find_log_space and _find_parallel_space should be merged into
+ * single generic function.
+ */
+static int _find_log_space(struct alloc_handle *ah, alloc_policy_t alloc,
+				struct list *pvms, struct pv_area **areas,
+				uint32_t areas_size, uint32_t log_extents) 
+{
+	struct pv_map *pvm;
+	struct pv_area *pva;
+	unsigned already_found_one = 0;
+	unsigned ix = 0;
+
+	/*
+	 * Put the smallest area of each PV that is at least the
+	 * size we need into areas array.
+	 */
+	list_iterate_items(pvm, pvms) {
+		if (list_empty(&pvm->areas))
+			continue;	/* Next PV */
+
+		if (alloc != ALLOC_ANYWHERE) {
+			if (is_pv_parallel(pvm->pv, ah, NULL))
+				continue;
+		}
+
+		already_found_one = 0;
+		/* First area in each list is the largest */
+		list_iterate_items(pva, &pvm->areas) {
+			/* Is it big enough on its own? */
+			if (pva->count < log_extents)
+				break;
+
+			if (!already_found_one) {
+				ix++;
+				already_found_one = 1;
+			}
+
+			areas[ix - 1] = pva;
+		}
+
+		if (ix >= areas_size)
+			break;
+	}
+
+	/* Not found enough area */
+	if (ix < ah->log_count)
+		return 0;
+
+	/* sort the areas so we allocate from the biggest */
+	if (ix > 1)
+		qsort(areas, ix, sizeof(*areas), _comp_area);
+
+	/* use smallest area as log_area */
+	if (!_alloc_log_area(ah, log_extents, *(areas + ix - 1))) {
+		stack;
+		return 0;
+	}
+
+	return 1;
+}
+
+/*
  * Choose sets of parallel areas to use, respecting any constraints.
  */
 static int _find_parallel_space(struct alloc_handle *ah, alloc_policy_t alloc,
@@ -689,7 +792,6 @@ static int _find_parallel_space(struct a
 {
 	struct pv_map *pvm;
 	struct pv_area *pva;
-	struct pv_list *pvl;
 	unsigned already_found_one = 0;
 	unsigned contiguous = 0, contiguous_count = 0;
 	unsigned ix;
@@ -700,7 +802,6 @@ static int _find_parallel_space(struct a
 	struct list *parallel_pvs;
 
 	/* FIXME Do calculations on free extent counts before selecting space */
-	/* FIXME Select log PV appropriately if there isn't one yet */
 
 	/* Are there any preceding segments we must follow on from? */
 	if ((alloc == ALLOC_CONTIGUOUS) && prev_lvseg) {
@@ -708,6 +809,12 @@ static int _find_parallel_space(struct a
 		ix_offset = prev_lvseg->area_count;
 	}
 
+	/* Allocate log first */
+	if (ah->log_count && ah->log_area.len == 0)
+		/* FIXME Assuming log size = 1, Calculate correctly */
+		if (!_find_log_space(ah, alloc, pvms, areas, areas_size, 1))
+			return 0;
+
 	/* FIXME This algorithm needs a lot of cleaning up! */
 	/* FIXME anywhere doesn't find all space yet */
 	/* ix_offset holds the number of allocations that must be contiguous */
@@ -758,10 +865,8 @@ static int _find_parallel_space(struct a
 					continue;	/* Next PV */
 
 				/* Avoid PVs used by existing parallel areas */
-				if (parallel_pvs)
-					list_iterate_items(pvl, parallel_pvs)
-						if (pvm->pv == pvl->pv)
-							goto next_pv;
+				if (is_pv_parallel(pvm->pv, NULL, parallel_pvs))
+					goto next_pv;
 			}
 
 			already_found_one = 0;
@@ -781,7 +886,7 @@ static int _find_parallel_space(struct a
 
 				/* Is it big enough on its own? */
 				if ((pva->count < (max_parallel - *allocated) / ah->area_multiple) &&
-				    ((!can_split && !ah->log_count) ||
+				    (!can_split ||
 				     (already_found_one &&
 				      !(alloc == ALLOC_ANYWHERE))))
 					goto next_pv;
@@ -804,11 +909,7 @@ static int _find_parallel_space(struct a
 		if (contiguous && (contiguous_count < ix_offset))
 			break;
 
-		/* Only allocate log_area the first time around */
-		if (ix + ix_offset < ah->area_count +
-			    ((ah->log_count && !ah->log_area.len) ?
-				ah->log_count : 0))
-			/* FIXME With ALLOC_ANYWHERE, need to split areas */
+		if (ix + ix_offset < ah->area_count)
 			break;
 
 		/* sort the areas so we allocate from the biggest */
@@ -816,13 +917,7 @@ static int _find_parallel_space(struct a
 			qsort(areas + ix_offset, ix, sizeof(*areas),
 			      _comp_area);
 
-		/* First time around, use smallest area as log_area */
-		/* FIXME decide which PV to use at top of function instead */
-		if (!_alloc_parallel_area(ah, max_parallel, areas,
-					  allocated,
-					  (ah->log_count && !ah->log_area.len) ?
-						*(areas + ix_offset + ix - 1) :
-						NULL)) {
+		if (!_alloc_parallel_area(ah, max_parallel, areas, allocated)) {
 			stack;
 			return 0;
 		}

^ permalink raw reply	[flat|nested] 3+ messages in thread

* [linux-lvm] [PATCH LVM2 2/2] fix lvconvert to setup mirror constraints
  2006-09-22 22:27 [linux-lvm] [PATCH LVM2 0/2] fix alloc anywhere and addition of disklog Jun'ichi Nomura
  2006-09-22 22:31 ` [linux-lvm] [PATCH LVM2 1/2] fix mirror allocation Jun'ichi Nomura
@ 2006-09-22 22:33 ` Jun'ichi Nomura
  1 sibling, 0 replies; 3+ messages in thread
From: Jun'ichi Nomura @ 2006-09-22 22:33 UTC (permalink / raw)
  To: linux-lvm, Alasdair Kergon, Jonathan Brassow

[-- Attachment #1: Type: text/plain, Size: 263 bytes --]

This patch fixes this problem:
  - 'lvconvert' from corelog allocates log from the same PV
    with other image. It spoils redundancy.

The patch depends on fix-mirror-alloc-anywhere.patch posted formerly.

Thanks,
-- 
Jun'ichi Nomura, NEC Corporation of America

[-- Attachment #2: fix-lvconvert-allocate-disklog.patch --]
[-- Type: text/x-patch, Size: 953 bytes --]

diff -X dontdiff -urp LVM2/tools/lvconvert.c LVM2.fixed/tools/lvconvert.c
--- LVM2/tools/lvconvert.c	2006-08-30 05:57:31.000000000 -0400
+++ LVM2.fixed/tools/lvconvert.c	2006-09-15 00:00:33.000000000 -0400
@@ -281,15 +281,10 @@ static int lvconvert_mirrors(struct cmd_
 			if (lp->mirrors == existing_mirrors) {
 				if (!seg->log_lv && !arg_count(cmd, corelog_ARG)) {
 					/* No disk log present, add one. */
-					/* FIXME: Why doesn't this work?  Without
-					   it, we will probably put the log on the
-					   same device as a mirror leg.
-					  if (!(parallel_areas = build_parallel_areas_from_lv(cmd, lv))) {
-					  stack;
-					  return 0;
-					  }
-					*/
-					parallel_areas = NULL;
+					if (!(parallel_areas = build_parallel_areas_from_lv(cmd, lv))) {
+						stack;
+						return 0;
+					}
 					if (!lv_mirror_percent(cmd, lv, 0, &sync_percent, NULL)) {
 						log_error("Unable to determine mirror sync status.");
 						return 0;

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2006-09-22 22:33 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-09-22 22:27 [linux-lvm] [PATCH LVM2 0/2] fix alloc anywhere and addition of disklog Jun'ichi Nomura
2006-09-22 22:31 ` [linux-lvm] [PATCH LVM2 1/2] fix mirror allocation Jun'ichi Nomura
2006-09-22 22:33 ` [linux-lvm] [PATCH LVM2 2/2] fix lvconvert to setup mirror constraints Jun'ichi Nomura

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.