All of lore.kernel.org
 help / color / mirror / Atom feed
From: agk@sourceware.org <agk@sourceware.org>
To: lvm-devel@redhat.com
Subject: LVM2 ./WHATS_NEW lib/metadata/lv_manip.c lib/m ...
Date: 25 Mar 2010 02:31:50 -0000	[thread overview]
Message-ID: <20100325023150.4496.qmail@sourceware.org> (raw)

CVSROOT:	/cvs/lvm2
Module name:	LVM2
Changes by:	agk at sourceware.org	2010-03-25 02:31:49

Modified files:
	.              : WHATS_NEW 
	lib/metadata   : lv_manip.c pv_map.h 

Log message:
	Introduce pv_area_used into allocation algorithm and add debug messages.
	
	This is the next preparatory step towards better --alloc anywhere
	support and is not intended to break anything that currently works so
	please report any problems - segfaults, bogus data in the new debug
	messages, or if the code now chooses bizarre allocation layouts.

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW.diff?cvsroot=lvm2&r1=1.1477&r2=1.1478
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/lv_manip.c.diff?cvsroot=lvm2&r1=1.212&r2=1.213
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/pv_map.h.diff?cvsroot=lvm2&r1=1.10&r2=1.11

--- LVM2/WHATS_NEW	2010/03/24 22:25:11	1.1477
+++ LVM2/WHATS_NEW	2010/03/25 02:31:48	1.1478
@@ -1,7 +1,8 @@
 Version 2.02.63 - 
 ================================
-  Add "monitoring" option to "activation" section of lvm.conf.
-  Add --monitor and --ignoremonitoring support to lvcreate.
+  Introduce pv_area_used into allocation algorithm and add debug messages.
+  Add activation/monitoring to lvm.conf.
+  Add --monitor and --ignoremonitoring to lvcreate.
   Allow dynamic extension of array of areas selected as allocation candidates.
   Export and use only valid cookie value in test suite.
   Remove const modifier for struct volume_group* from process_each_lv_in_vg().
--- LVM2/lib/metadata/lv_manip.c	2010/03/23 22:30:19	1.212
+++ LVM2/lib/metadata/lv_manip.c	2010/03/25 02:31:49	1.213
@@ -735,7 +735,7 @@
  * 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 *allocated,
+				struct pv_area_used *areas, uint32_t *allocated,
 				unsigned log_needs_allocating, uint32_t ix_log_offset)
 {
 	uint32_t area_len, len, remaining;
@@ -749,8 +749,8 @@
 
 	/* Reduce area_len to the smallest of the areas */
 	for (s = 0; s < ah->area_count; s++)
-		if (area_len > areas[s]->count)
-			area_len = areas[s]->count;
+		if (area_len > areas[s].used)
+			area_len = areas[s].used;
 
 	if (!(aa = dm_pool_alloc(ah->mem, sizeof(*aa) * total_area_count))) {
 		log_error("alloced_area allocation failed");
@@ -769,11 +769,15 @@
 			len = ah->log_len;
 		}
 
-		aa[s].pv = areas[s + ix_log_skip]->map->pv;
-		aa[s].pe = areas[s + ix_log_skip]->start;
+		aa[s].pv = areas[s + ix_log_skip].pva->map->pv;
+		aa[s].pe = areas[s + ix_log_skip].pva->start;
 		aa[s].len = len;
 
-		consume_pv_area(areas[s + ix_log_skip], len);
+		log_debug("Allocating parallel area %" PRIu32
+			  " on %s start PE %" PRIu32 " length %" PRIu32 ".",
+			  s, dev_name(aa[s].pv->dev), aa[s].pe, len);
+
+		consume_pv_area(areas[s + ix_log_skip].pva, len);
 
 		dm_list_add(&ah->alloced_areas[s], &aa[s].list);
 	}
@@ -863,13 +867,13 @@
 
 static int _comp_area(const void *l, const void *r)
 {
-	const struct pv_area *lhs = *((const struct pv_area * const *) l);
-	const struct pv_area *rhs = *((const struct pv_area * const *) r);
+	const struct pv_area_used *lhs = *((const struct pv_area_used * const *) l);
+	const struct pv_area_used *rhs = *((const struct pv_area_used * const *) r);
 
-	if (lhs->count < rhs->count)
+	if (lhs->used < rhs->used)
 		return 1;
 
-	else if (lhs->count > rhs->count)
+	else if (lhs->used > rhs->used)
 		return -1;
 
 	return 0;
@@ -881,7 +885,7 @@
 struct pv_match {
 	int (*condition)(struct pv_segment *pvseg, struct pv_area *pva);
 
-	struct pv_area **areas;
+	struct pv_area_used *areas;
 	struct pv_area *pva;
 	uint32_t areas_size;
 	int s;	/* Area index of match */
@@ -924,7 +928,12 @@
 	if (s >= pvmatch->areas_size)
 		return 1;
 
-	pvmatch->areas[s] = pvmatch->pva;
+	/*
+	 * Only used for cling and contiguous policies so its safe to say all
+	 * the available space is used.
+	 */
+	pvmatch->areas[s].pva = pvmatch->pva;
+	pvmatch->areas[s].used = pvmatch->pva->count;
 
 	return 2;	/* Finished */
 }
@@ -934,7 +943,7 @@
  */
 static int _check_cling(struct cmd_context *cmd,
 			struct lv_segment *prev_lvseg, struct pv_area *pva,
-			struct pv_area **areas, uint32_t areas_size)
+			struct pv_area_used *areas, uint32_t areas_size)
 {
 	struct pv_match pvmatch;
 	int r;
@@ -962,7 +971,7 @@
  */
 static int _check_contiguous(struct cmd_context *cmd,
 			     struct lv_segment *prev_lvseg, struct pv_area *pva,
-			     struct pv_area **areas, uint32_t areas_size)
+			     struct pv_area_used *areas, uint32_t areas_size)
 {
 	struct pv_match pvmatch;
 	int r;
@@ -989,7 +998,7 @@
  * Choose sets of parallel areas to use, respecting any constraints.
  */
 static int _find_parallel_space(struct alloc_handle *ah, alloc_policy_t alloc,
-				struct dm_list *pvms, struct pv_area ***areas_ptr,
+				struct dm_list *pvms, struct pv_area_used **areas_ptr,
 				uint32_t *areas_size_ptr, unsigned can_split,
 				struct lv_segment *prev_lvseg,
 				uint32_t *allocated, uint32_t needed)
@@ -1005,6 +1014,7 @@
 	unsigned too_small_for_log_count; /* How many too small for log? */
 	uint32_t max_parallel;	/* Maximum extents to allocate */
 	uint32_t next_le;
+	uint32_t required;	/* Extents we're trying to obtain from a given area */
 	struct seg_pvs *spvs;
 	struct dm_list *parallel_pvs;
 	uint32_t free_pes;
@@ -1062,6 +1072,9 @@
 			}
 		}
 
+		log_needs_allocating = (ah->log_area_count &&
+					dm_list_empty(&ah->alloced_areas[ah->area_count])) ?  1 : 0;
+
 		/*
 		 * Put the smallest area of each PV that is at least the
 		 * size we need into areas array.  If there isn't one
@@ -1121,30 +1134,44 @@
 				      !(alloc == ALLOC_ANYWHERE))))
 					goto next_pv;
 
+				/*
+				 * Except with ALLOC_ANYWHERE, replace first area with this
+				 * one which is smaller but still big enough.
+				 */
 				if (!already_found_one ||
 				    alloc == ALLOC_ANYWHERE) {
 					ix++;
 					already_found_one = 1;
 				}
 
+				if (ix + ix_offset - 1 < ah->area_count)
+					required = (max_parallel - *allocated) / ah->area_multiple;
+				else
+					required = ah->log_len;
+
+				if (required > pva->count)
+					required = pva->count;
+
 				/* Expand areas array if needed after an area was split. */
 				if (ix + ix_offset > *areas_size_ptr) {
 					*areas_size_ptr *= 2;
 					*areas_ptr = dm_realloc(*areas_ptr, sizeof(**areas_ptr) * (*areas_size_ptr));
 				}
-				(*areas_ptr)[ix + ix_offset - 1] = pva;
+				(*areas_ptr)[ix + ix_offset - 1].pva = pva;
+				(*areas_ptr)[ix + ix_offset - 1].used = required;
+				log_debug("Trying allocation area %" PRIu32 " on %s start PE %" PRIu32
+					  " length %" PRIu32 " leaving %" PRIu32 ".",
+					  ix + ix_offset - 1, dev_name(pva->map->pv->dev), pva->start, required,
+					  pva->count - required);
 			}
 		next_pv:
-			if (ix >= *areas_size_ptr)
+			if (ix + ix_offset >= ah->area_count + (log_needs_allocating ? ah->log_area_count : 0))
 				break;
 		}
 
 		if ((contiguous || cling) && (preferred_count < ix_offset))
 			break;
 
-		log_needs_allocating = (ah->log_area_count &&
-					dm_list_empty(&ah->alloced_areas[ah->area_count])) ?  1 : 0;
-
 		if (ix + ix_offset < ah->area_count +
 		   (log_needs_allocating ? ah->log_area_count : 0))
 			break;
@@ -1166,7 +1193,7 @@
 			/* How many areas are too small for the log? */
 			while (too_small_for_log_count < ix_offset + ix &&
 			       (*((*areas_ptr) + ix_offset + ix - 1 -
-				  too_small_for_log_count))->count < ah->log_len)
+				  too_small_for_log_count)).used < ah->log_len)
 				too_small_for_log_count++;
 			ix_log_offset = ix_offset + ix - too_small_for_log_count - ah->log_area_count;
 		}
@@ -1197,7 +1224,7 @@
 		     unsigned can_split,
 		     struct dm_list *allocatable_pvs)
 {
-	struct pv_area **areas;
+	struct pv_area_used *areas;
 	uint32_t allocated = lv ? lv->le_count : 0;
 	uint32_t old_allocated;
 	struct lv_segment *prev_lvseg = NULL;
@@ -1206,12 +1233,16 @@
 	uint32_t areas_size;
 	alloc_policy_t alloc;
 	struct alloced_area *aa;
+	unsigned log_allocated;
 
 	if (allocated >= ah->new_extents && !ah->log_area_count) {
 		log_error("_allocate called with no work to do!");
 		return 1;
 	}
 
+	if (!ah->log_area_count)
+		log_allocated = 1;
+
 	if (ah->alloc == ALLOC_CONTIGUOUS)
 		can_split = 0;
 
@@ -1252,6 +1283,11 @@
 	/* Attempt each defined allocation policy in turn */
 	for (alloc = ALLOC_CONTIGUOUS; alloc < ALLOC_INHERIT; alloc++) {
 		old_allocated = allocated;
+		log_debug("Trying allocation using %s policy.  "
+			  "Need %" PRIu32 " extents for %" PRIu32 " parallel areas and %" PRIu32 " log extents.",
+			  get_alloc_string(alloc),
+			  (ah->new_extents - allocated) / ah->area_multiple,
+			  ah->area_count, log_allocated ? 0 : ah->log_area_count);
 		if (!_find_parallel_space(ah, alloc, pvms, &areas,
 					  &areas_size, can_split,
 					  prev_lvseg, &allocated, ah->new_extents))
@@ -1259,6 +1295,9 @@
 		if ((allocated == ah->new_extents) || (ah->alloc == alloc) ||
 		    (!can_split && (allocated != old_allocated)))
 			break;
+		/* Log is always allocated the first time anything is allocated. */
+		if (old_allocated != allocated)
+			log_allocated = 1;
 	}
 
 	if (allocated != ah->new_extents) {
--- LVM2/lib/metadata/pv_map.h	2008/11/03 22:14:29	1.10
+++ LVM2/lib/metadata/pv_map.h	2010/03/25 02:31:49	1.11
@@ -34,6 +34,18 @@
 	struct dm_list list;		/* pv_map.areas */
 };
 
+/*
+ * When building up a potential group of "parallel" extent ranges during
+ * an allocation attempt, track the maximum number of extents that may
+ * need to be used as a particular parallel area.  Several of these
+ * structs may reference the same pv_area, but 'used' may differ between
+ * them.
+ */
+struct pv_area_used {
+	struct pv_area *pva;
+	uint32_t used;
+};
+
 struct pv_map {
 	struct physical_volume *pv;
 	struct dm_list areas;		/* struct pv_areas */
@@ -49,6 +61,7 @@
 			    struct dm_list *allocatable_pvs);
 
 void consume_pv_area(struct pv_area *area, uint32_t to_go);
+void reinsert_reduced_pv_area(struct pv_area *pva);
 
 uint32_t pv_maps_size(struct dm_list *pvms);
 



             reply	other threads:[~2010-03-25  2:31 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-03-25  2:31 agk [this message]
  -- strict thread matches above, loose matches on Subject: below --
2012-02-23 17:36 LVM2 ./WHATS_NEW lib/metadata/lv_manip.c lib/m jbrassow
2012-02-23  3:57 jbrassow
2012-02-15 15:18 zkabelac
2012-02-08 13:05 zkabelac
2012-02-01  2:10 agk
2011-10-22 16:42 zkabelac
2011-09-06 18:49 agk
2011-08-18 19:41 jbrassow
2011-08-11  3:29 jbrassow
2011-06-23 14:01 jbrassow
2011-04-09 19:05 zkabelac
2011-01-24 14:19 agk
2011-01-11 17:05 jbrassow
2010-10-14 20:03 jbrassow
2010-04-23 19:27 snitzer
2010-04-09  1:00 agk
2010-03-25 21:19 agk
2010-01-08 22:32 jbrassow
2010-01-11 13:34 ` Zdenek Kabelac
2009-05-13 21:29 mbroz
2009-05-13 21:28 mbroz
2009-04-21 14:32 mbroz
2009-04-07 10:20 mbroz
2008-03-28 19:08 wysochanski
2008-01-26  0:25 agk
2008-01-18 22:00 agk
2007-12-20 18:55 agk
2007-08-28 16:14 wysochanski
2007-08-03 21:22 wysochanski
2006-12-13  3:39 agk
2006-10-23 15:54 agk

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20100325023150.4496.qmail@sourceware.org \
    --to=agk@sourceware.org \
    --cc=lvm-devel@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.