commit 1bf4c3a1fabb6864564fdc42437db424bcfa06f4
Author: Alasdair G Kergon <agk@redhat.com>
Date:   Tue Apr 15 01:13:47 2014 +0100

    alloc: Introduce A_POSITIONAL_FILL.
    
    Set A_POSITIONAL_FILL if the array of areas is being filled
    positionally (with a slot corresponding to each 'leg') rather
    than sequentially (with all suitable areas found, to be sorted
    and selected from).

diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index 0e65847..46431a9 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -49,6 +49,8 @@ typedef enum {
 #define A_CAN_SPLIT		0x10
 #define A_AREA_COUNT_MATCHES	0x20	/* Existing lvseg has same number of areas as new segment */
 
+#define A_POSITIONAL_FILL	0x40	/* Slots are positional and filled using PREFERRED */
+
 /*
  * Constant parameters during a single allocation attempt.
  */
@@ -1280,6 +1282,7 @@ static void _init_alloc_parms(struct alloc_handle *ah,
 
 	/* Are there any preceding segments we must follow on from? */
 	if (alloc_parms->prev_lvseg && (alloc_parms->flags & A_AREA_COUNT_MATCHES)) {
+		alloc_parms->flags |= A_POSITIONAL_FILL;
 		if (alloc_parms->alloc == ALLOC_CONTIGUOUS)
 			alloc_parms->flags |= A_CONTIGUOUS_TO_LVSEG;
 		else if ((alloc_parms->alloc == ALLOC_CLING) || (alloc_parms->alloc == ALLOC_CLING_BY_TAGS))
@@ -1291,8 +1294,10 @@ static void _init_alloc_parms(struct alloc_handle *ah,
 		 * A cling allocation that follows a successful contiguous allocation
 		 * must use the same PVs (or else fail).
 		 */
-		if ((alloc_parms->alloc == ALLOC_CLING) || (alloc_parms->alloc == ALLOC_CLING_BY_TAGS))
+		if ((alloc_parms->alloc == ALLOC_CLING) || (alloc_parms->alloc == ALLOC_CLING_BY_TAGS)) {
 			alloc_parms->flags |= A_CLING_TO_ALLOCED;
+			alloc_parms->flags |= A_POSITIONAL_FILL;
+		}
 
 	if (alloc_parms->alloc == ALLOC_CLING_BY_TAGS)
 		alloc_parms->flags |= A_CLING_BY_TAGS;
@@ -1751,21 +1756,23 @@ static int _is_condition(struct cmd_context *cmd __attribute__((unused)),
 			 void *data)
 {
 	struct pv_match *pvmatch = data;
+	int positional = pvmatch->alloc_state->alloc_parms->flags & A_POSITIONAL_FILL;
 
-	if (pvmatch->alloc_state->areas[s].pva)
+	if (positional && pvmatch->alloc_state->areas[s].pva)
 		return 1;	/* Area already assigned */
 
 	if (!pvmatch->condition(pvmatch, pvseg, pvmatch->pva))
 		return 1;	/* Continue */
 
-	if (s >= pvmatch->alloc_state->areas_size)
+	if (positional && (s >= pvmatch->alloc_state->areas_size))
 		return 1;
 
 	/*
 	 * Only used for cling and contiguous policies (which only make one allocation per PV)
 	 * so it's safe to say all the available space is used.
 	 */
-	_reserve_required_area(pvmatch->alloc_state, pvmatch->pva, pvmatch->pva->count, s, 0);
+	if (positional)
+		_reserve_required_area(pvmatch->alloc_state, pvmatch->pva, pvmatch->pva->count, s, 0);
 
 	return 2;	/* Finished */
 }
@@ -1845,6 +1852,7 @@ static int _check_cling_to_alloced(struct alloc_handle *ah, const struct dm_conf
 {
 	unsigned s;
 	struct alloced_area *aa;
+	int positional = alloc_state->alloc_parms->flags & A_POSITIONAL_FILL;
 
 	/*
 	 * Ignore log areas.  They are always allocated whole as part of the
@@ -1854,12 +1862,13 @@ static int _check_cling_to_alloced(struct alloc_handle *ah, const struct dm_conf
 		return 0;
 
 	for (s = 0; s < ah->area_count; s++) {
-		if (alloc_state->areas[s].pva)
+		if (positional && alloc_state->areas[s].pva)
 			continue;	/* Area already assigned */
 		dm_list_iterate_items(aa, &ah->alloced_areas[s]) {
 			if ((!cling_tag_list_cn && (pva->map->pv == aa[0].pv)) ||
 			    (cling_tag_list_cn && _pvs_have_matching_tag(cling_tag_list_cn, pva->map->pv, aa[0].pv))) {
-				_reserve_required_area(alloc_state, pva, pva->count, s, 0);
+				if (positional)
+					_reserve_required_area(alloc_state, pva, pva->count, s, 0);
 				return 1;
 			}
 		}
@@ -1949,10 +1958,11 @@ static area_use_t _check_pva(struct alloc_handle *ah, struct pv_area *pva, uint3
 	     (already_found_one && alloc_parms->alloc != ALLOC_ANYWHERE)))
 		return NEXT_PV;
 
-	return USE_AREA;
-
 found:
-	return PREFERRED;
+	if (alloc_parms->flags & A_POSITIONAL_FILL)
+		return PREFERRED;
+
+	return USE_AREA;
 }
 
 /*
@@ -2078,6 +2088,9 @@ static int _find_some_parallel_space(struct alloc_handle *ah,
 		log_debug("Cling_to_allocated is %sset",
 			  alloc_parms->flags & A_CLING_TO_ALLOCED ? "" : "not ");
 
+	if (alloc_parms->flags & A_POSITIONAL_FILL)
+		log_debug("Preferred areas are filled positionally.");
+
 	_clear_areas(alloc_state);
 	_reset_unreserved(pvms);
 
@@ -2146,6 +2159,7 @@ static int _find_some_parallel_space(struct alloc_handle *ah,
 				 * There are two types of allocations, which can't be mixed at present:
 				 *
 				 * PREFERRED are stored immediately in a specific parallel slot.
+				 *   This is only used if the A_POSITIONAL_FILL flag is set.
 				 *   This requires the number of slots to match, so if comparing with
 				 *   prev_lvseg then A_AREA_COUNT_MATCHES must be set.
 				 *
