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

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



This patch rewrites _check_contiguous() to use _for_each_pv().

_for_each_pv() is a generic iterator function to execute given
function on each PV constituting the specified range of LV.
Since _check_contiguous() tries to find contiguous PV segment from
the end of the existing LV segment, I gave the last one LE as
a iteration range of _for_each_pv().

To pass necessary parameters to _for_each_pv callback (_match_pv()),
this patch adds new struct pv_match_handle.

The patch doesn't fix any bug but is a preparation for later patch.
Also, the use like this is what _for_each_pv() is intended for, I think.

diffstat:
 lv_manip.c |   89 +++++++++++++++++++++++++++++++++++++++++++++----------------
 1 file changed, 66 insertions(+), 23 deletions(-)

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

diff -X ../dontdiff -urp LVM2.04-shrink-checkcontig-arg/lib/metadata/lv_manip.c LVM2.05.use_for_each_pv/lib/metadata/lv_manip.c
--- LVM2.04-shrink-checkcontig-arg/lib/metadata/lv_manip.c	2006-10-07 02:46:21.000000000 -0400
+++ LVM2.05.use_for_each_pv/lib/metadata/lv_manip.c	2006-10-07 02:49:12.000000000 -0400
@@ -24,6 +24,11 @@
 #include "display.h"
 #include "segtype.h"
 
+static int _for_each_pv(struct cmd_context *cmd, struct logical_volume *lv,
+			uint32_t le, uint32_t len, uint32_t *max_seg_len,
+			int (*fn)(struct cmd_context *cmd, struct pv_segment *peg, void *data),
+			void *data);
+
 /*
  * PVs used by a segment of an LV
  */
@@ -680,42 +685,80 @@ static int _comp_area(const void *l, con
 	return 0;
 }
 
+struct pv_match_handle {
+	/* function to check if pv_segment fits for the pv_area */
+	int (*cond)(struct pv_segment *, struct pv_area *);
+
+	struct pv_area *pva; /* pv_area to match */
+	int index; /* index of pv in flattened lv segment */
+	int matched; /* 1 if matching pv_segment is found */
+};
+
 /*
- * Is pva contiguous to any existing areas or on the same PV?
+ * (_for_each_pv callback)
+ * Check if the pv_segment fits for the pv_match_handle
  */
-static int _check_contiguous(struct lv_segment *prev_lvseg, struct pv_area *pva,
-			     struct pv_area **areas, uint32_t areas_size)
+static int _match_pv(struct cmd_context *cmd, struct pv_segment *peg,
+		     void *data)
 {
-	struct pv_segment *prev_pvseg;
-	struct lv_segment *lastseg;
-	uint32_t s;
+	struct pv_match_handle *h = (struct pv_match_handle *)data;
 
-	for (s = 0; s < prev_lvseg->area_count && s < areas_size; s++) {
-		if (seg_type(prev_lvseg, s) == AREA_LV) {
-			lastseg = list_item(list_last(&seg_lv(prev_lvseg, s)->segments), struct lv_segment);
-			/* FIXME For more areas supply flattened prev_lvseg to ensure consistency */
-			if (lastseg->area_count == 1 &&
-			    _check_contiguous(lastseg, pva, &areas[s], 1))
-				return 1;
-			continue;
-		}
+	h->index++;
+	if (h->cond && h->cond(peg, h->pva)) {
+		h->matched = 1;
+		return 0; /* to exit from for_each_pv loop */
+	}
 
-		if (!(prev_pvseg = seg_pvseg(prev_lvseg, s)))
-			continue; /* FIXME Broken */
+	return 1;
+}
 
-		if ((prev_pvseg->pv != pva->map->pv))
-			continue;
+static int _find_and_set_pv_area(struct lv_segment *prev_lvseg,
+				 struct pv_area *pva,
+				 struct pv_area **areas, uint32_t areas_size,
+				 int (*cond)(struct pv_segment *,
+					     struct pv_area *))
+{
+	struct pv_match_handle pmh;
+
+	pmh.cond = cond;
+	pmh.pva = pva;
+	pmh.index = -1;
+	pmh.matched = 0;
+
+	/* search through all PVs in the last extent of the LV */
+	_for_each_pv(NULL, prev_lvseg->lv,
+		     prev_lvseg->le + prev_lvseg->len - 1, 1,
+		     NULL, _match_pv, &pmh);
 
-		if (prev_pvseg->pe + prev_pvseg->len == pva->start) {
-			areas[s] = pva;
-			return 1;
-		}
+	if (pmh.matched && pmh.index >= 0 && pmh.index < areas_size) {
+		areas[pmh.index] = pva;
+		return 1;
 	}
 
 	return 0;
 }
 
 /*
+ * Is pva contiguous to any existing areas or on the same PV?
+ */
+static int is_contiguous(struct pv_segment *prev, struct pv_area *pva)
+{
+	if ((prev->pv == pva->map->pv) &&
+	    (prev->pe + prev->len == pva->start))
+		return 1;
+
+	return 0;
+}
+
+static int _check_contiguous(struct lv_segment *prev_lvseg, struct pv_area *pva,
+			     struct pv_area **areas, uint32_t areas_size)
+{
+	return _find_and_set_pv_area(prev_lvseg, pva, areas, areas_size,
+				     is_contiguous);
+}
+
+
+/*
  * Choose sets of parallel areas to use, respecting any constraints.
  */
 static int _find_parallel_space(struct alloc_handle *ah, alloc_policy_t alloc,

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