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

[linux-lvm] Re: [PATCH LVM2] (2/3) use _for_each_pv() from _check_contiguous()



Alasdair G Kergon wrote:
This patch rewrites _check_contiguous() to use _for_each_pv().
I think the existing FIXME got dropped and I suspect there are problems
with multiple levels of recursion.  (h->index++ ?)

I think the FIXME was intended for the case of stacked LV.
The index here is used to flatten the stacked LV to linear array
of PVs.
To complete it, we need to use the index in other places, too.

In _allocate(),
        /* Upper bound if none of the PVs in prev_lvseg is in pvms */
        /* FIXME Work size out properly */
        if (prev_lvseg)
                areas_size += prev_lvseg->area_count;

and in _find_parallel_space(),
        if (prev_lvseg) {
                ix_offset = prev_lvseg->area_count;

we can count the number of PVs constituting the last extent of
the prev_lvseg correctly by _for_each_pv().

What do you think about the attached patch?

It adds index calculation in _for_each_pv() (I replaced
'top_level_area_index' because it seemed aiming for similar
purpose) and fixes the 2 places above.
If you pass a pointer to counter, _for_each_pv() increments
the counter for each AREA_PV and passes the current number to
call back function. Upon return from the top level _for_each_pv(),
the counter should have the number of PVs in flattend LV.
As long as we use the same set of parameters for _for_each_pv(),
the counter value can be used as consistent index.

I also attached hypothetical metadata of stacked LV
(RAID0+1 and RAID10).

Thanks,
--
Jun'ichi Nomura, NEC Corporation of America
diff -X dontdiff -urp LVM2/lib/metadata/lv_manip.c LVM2.07.calcfix/lib/metadata/lv_manip.c
--- LVM2/lib/metadata/lv_manip.c	2006-10-09 21:06:56.000000000 -0400
+++ LVM2.07.calcfix/lib/metadata/lv_manip.c	2006-10-09 21:24:59.000000000 -0400
@@ -680,7 +680,7 @@ static int _alloc_parallel_area(struct a
 static int _for_each_pv(struct cmd_context *cmd, struct logical_volume *lv,
 			uint32_t le, uint32_t len, uint32_t *max_seg_len,
 			uint32_t first_area, uint32_t max_areas,
-			int top_level_area_index,
+			uint32_t *flattend_area_index,
 			int only_single_area_segments,
 			int (*fn)(struct cmd_context *cmd,
 				  struct pv_segment *peg, uint32_t s,
@@ -720,13 +720,19 @@ static int _for_each_pv(struct cmd_conte
 					       area_len, max_seg_len,
 					       only_single_area_segments ? 0 : 0,
 					       only_single_area_segments ? 1 : 0,
-					       top_level_area_index != -1 ? top_level_area_index : s,
+					       flattend_area_index,
 					       only_single_area_segments, fn,
 					       data)))
 				stack;
-		} else if (seg_type(seg, s) == AREA_PV)
-			if (!(r = fn(cmd, seg_pvseg(seg, s), top_level_area_index != -1 ? top_level_area_index : s, data)))
+		} else if (seg_type(seg, s) == AREA_PV) {
+			if (fn && !(r = fn(cmd, seg_pvseg(seg, s),
+					   flattend_area_index != NULL ?
+						*flattend_area_index : s,
+					   data)))
 				stack;
+			if (flattend_area_index)
+				(*flattend_area_index)++;
+		}
 		if (r != 1)
 			return r;
 	}
@@ -734,7 +740,7 @@ static int _for_each_pv(struct cmd_conte
 	/* FIXME only_single_area_segments used as workaround to skip log LV - needs new param? */
 	if (!only_single_area_segments && seg_is_mirrored(seg) && seg->log_lv) {
 		if (!(r = _for_each_pv(cmd, seg->log_lv, 0, MIRROR_LOG_SIZE,
-				       NULL, 0, 0, 0, only_single_area_segments,
+				       NULL, 0, 0, NULL, only_single_area_segments,
 				       fn, data)))
 			stack;
 		if (r != 1)
@@ -832,7 +838,7 @@ static int _check_cling(struct cmd_conte
 	/* FIXME Cope with stacks by flattening */
 	if (!(r = _for_each_pv(cmd, prev_lvseg->lv,
 			       prev_lvseg->le + prev_lvseg->len - 1, 1, NULL,
-			       0, 0, -1, 1,
+			       0, 0, NULL, 1,
 			       _is_condition, &pvmatch)))
 		stack;
 
@@ -860,7 +866,7 @@ static int _check_contiguous(struct cmd_
 	/* FIXME Cope with stacks by flattening */
 	if (!(r = _for_each_pv(cmd, prev_lvseg->lv,
 			       prev_lvseg->le + prev_lvseg->len - 1, 1, NULL,
-			       0, 0, -1, 1,
+			       0, 0, NULL, 1,
 			       _is_condition, &pvmatch)))
 		stack;
 
@@ -885,7 +891,7 @@ static int _find_parallel_space(struct a
 	unsigned already_found_one = 0;
 	unsigned contiguous = 0, cling = 0, preferred_count = 0;
 	unsigned ix;
-	unsigned ix_offset = 0;	/* Offset for non-preferred allocations */
+	uint32_t ix_offset = 0;	/* Offset for non-preferred allocations */
 	uint32_t max_parallel;	/* Maximum extents to allocate */
 	uint32_t next_le;
 	struct seg_pvs *spvs;
@@ -896,7 +902,10 @@ static int _find_parallel_space(struct a
 
 	/* Are there any preceding segments we must follow on from? */
 	if (prev_lvseg) {
-		ix_offset = prev_lvseg->area_count;
+		if (!_for_each_pv(NULL, prev_lvseg->lv,
+				  prev_lvseg->le + prev_lvseg->len - 1, 1, NULL,
+				  0, 0, &ix_offset, 1, NULL, NULL))
+			return 0;
 		if ((alloc == ALLOC_CONTIGUOUS))
 			contiguous = 1;
 		else if ((alloc == ALLOC_CLING))
@@ -1092,9 +1101,14 @@ static int _allocate(struct alloc_handle
 	}
 
 	/* Upper bound if none of the PVs in prev_lvseg is in pvms */
-	/* FIXME Work size out properly */
-	if (prev_lvseg)
-		areas_size += prev_lvseg->area_count;
+	if (prev_lvseg) {
+		uint32_t prev_lvseg_areas;
+		if (!_for_each_pv(NULL, prev_lvseg->lv,
+				  prev_lvseg->le + prev_lvseg->len - 1, 1, NULL,
+				  0, 0, &prev_lvseg_areas, 1, NULL, NULL))
+			return 0;
+		areas_size += prev_lvseg_areas;
+	}
 
 	/* Allocate an array of pv_areas to hold the largest space on each PV */
 	if (!(areas = dm_malloc(sizeof(*areas) * areas_size))) {
@@ -1621,7 +1635,7 @@ struct list *build_parallel_areas_from_l
 		/* Find next segment end */
 		/* FIXME Unnecessary nesting! */
 		if (!_for_each_pv(cmd, lv, current_le, spvs->len, &spvs->len,
-				  0, 0, -1, 0, _add_pvs, (void *) spvs)) {
+				  0, 0, NULL, 0, _add_pvs, (void *) spvs)) {
 			stack;
 			return NULL;
 		}
# Generated by LVM2: Mon Oct  9 20:30:07 2006

contents = "Text Format Volume Group"
version = 1

description = "Created *before* executing 'lvextend -l+1 mvg2/lvol2'"

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 = 1160440207	# Mon Oct  9 20:30:07 2006

mvg2 {
	id = "AxZG1h-O6iz-YrBC-McFa-N252-NWZL-eLX1qy"
	seqno = 198
	status = ["RESIZEABLE", "READ", "WRITE"]
	extent_size = 8192		# 4 Megabytes
	max_lv = 0
	max_pv = 0

	physical_volumes {

		pv0 {
			id = "9EMez9-jHA3-FKBa-Ubtx-CkuB-WRlK-ZAIKiu"
			device = "/dev/sdc13"	# Hint only

			status = ["ALLOCATABLE"]
			dev_size = 3916160	# 1.86737 Gigabytes
			pe_start = 384
			pe_count = 478	# 1.86719 Gigabytes
		}

		pv1 {
			id = "CyCMk3-IJEW-v7FB-laN3-ZQAp-2Lia-MiA3H3"
			device = "/dev/sdc14"	# Hint only

			status = ["ALLOCATABLE"]
			dev_size = 3916160	# 1.86737 Gigabytes
			pe_start = 384
			pe_count = 478	# 1.86719 Gigabytes
		}
	}

	logical_volumes {

		lvol2 {
			id = "rqnWd1-o0ub-bQIv-x2Rw-o9Z6-KeSo-OAVWnf"
			status = ["READ", "WRITE", "VISIBLE"]
			segment_count = 1

			segment1 {
				start_extent = 0
				extent_count = 2	# 8 Megabytes

				type = "mirror"
				mirror_count = 2
				region_size = 1024

				mirrors = [
					"lvol2_mimage_0", 0,
					"lvol2_mimage_1", 0
				]
			}
		}

		lvol5 {
			id = "1ADDD2-16NG-HttH-0RN0-3ymb-P9Eg-TJBRjl"
			status = ["READ", "WRITE", "VISIBLE"]
			segment_count = 1

			segment1 {
				start_extent = 0
				extent_count = 2	# 8 Megabytes

				type = "striped"
				stripe_count = 2
				stripe_size = 128	# 64 Kilobytes

				stripes = [
					"lvol3", 0,
					"lvol4", 0
				]
			}
		}

		lvol0 {
			id = "1ADDD2-16NG-HttH-0RN0-3ymb-P9Eg-TJBRjs"
			status = ["READ", "WRITE"]
			segment_count = 1

			segment1 {
				start_extent = 0
				extent_count = 2	# 8 Megabytes

				type = "striped"
				stripe_count = 2
				stripe_size = 128	# 64 Kilobytes

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

		lvol1 {
			id = "1ADDD2-16NG-HttH-0RN0-3ymb-P9Eg-TJBRjk"
			status = ["READ", "WRITE"]
			segment_count = 1

			segment1 {
				start_extent = 0
				extent_count = 2	# 8 Megabytes

				type = "striped"
				stripe_count = 2
				stripe_size = 128	# 64 Kilobytes

				stripes = [
					"pv0", 1,
					"pv1", 1
				]
			}
		}

		lvol2_mimage_0 {
			id = "6TZMZW-n0cV-UNT8-w2lk-xMNH-3Ejm-quLPlS"
			status = ["READ", "WRITE"]
			segment_count = 1

			segment1 {
				start_extent = 0
				extent_count = 2	# 8 Megabytes

				type = "striped"
				stripe_count = 1	# linear

				stripes = [
					"lvol0", 0
				]
			}
		}

		lvol2_mimage_1 {
			id = "mBeAfD-xomg-HvnK-ifJY-tzCf-yAcs-IqNKdr"
			status = ["READ", "WRITE"]
			segment_count = 1

			segment1 {
				start_extent = 0
				extent_count = 2	# 8 Megabytes

				type = "striped"
				stripe_count = 1	# linear

				stripes = [
					"lvol1", 0
				]
			}
		}

		lvol3 {
			id = "rqnWd1-o0ub-bQIv-x2Rw-o9Z6-KeSo-OAVWng"
			status = ["READ", "WRITE"]
			segment_count = 1

			segment1 {
				start_extent = 0
				extent_count = 1	# 4 Megabytes

				type = "mirror"
				mirror_count = 2
				region_size = 1024

				mirrors = [
					"lvol3_mimage_0", 0,
					"lvol3_mimage_1", 0
				]
			}
		}

		lvol3_mimage_0 {
			id = "6TZMZW-n0cV-UNT8-w2lk-xMNH-3Ejm-quLPlT"
			status = ["READ", "WRITE"]
			segment_count = 1

			segment1 {
				start_extent = 0
				extent_count = 1	# 4 Megabytes

				type = "striped"
				stripe_count = 1	# linear

				stripes = [
					"pv0", 2
				]
			}
		}

		lvol3_mimage_1 {
			id = "mBeAfD-xomg-HvnK-ifJY-tzCf-yAcs-IqNKds"
			status = ["READ", "WRITE"]
			segment_count = 1

			segment1 {
				start_extent = 0
				extent_count = 1	# 4 Megabytes

				type = "striped"
				stripe_count = 1	# linear

				stripes = [
					"pv1", 2
				]
			}
		}

		lvol4 {
			id = "rqnWd1-o0ub-bQIv-x2Rw-o9Z6-KeSo-OAVWnh"
			status = ["READ", "WRITE"]
			segment_count = 1

			segment1 {
				start_extent = 0
				extent_count = 1	# 4 Megabytes

				type = "mirror"
				mirror_count = 2
				region_size = 1024

				mirrors = [
					"lvol4_mimage_0", 0,
					"lvol4_mimage_1", 0
				]
			}
		}

		lvol4_mimage_0 {
			id = "6TZMZW-n0cV-UNT8-w2lk-xMNH-3Ejm-quLPlU"
			status = ["READ", "WRITE"]
			segment_count = 1

			segment1 {
				start_extent = 0
				extent_count = 1	# 4 Megabytes

				type = "striped"
				stripe_count = 1	# linear

				stripes = [
					"pv0", 3
				]
			}
		}

		lvol4_mimage_1 {
			id = "mBeAfD-xomg-HvnK-ifJY-tzCf-yAcs-IqNKdt"
			status = ["READ", "WRITE"]
			segment_count = 1

			segment1 {
				start_extent = 0
				extent_count = 1	# 4 Megabytes

				type = "striped"
				stripe_count = 1	# linear

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

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