mirror of
git://sourceware.org/git/lvm2.git
synced 2025-03-11 20:58:50 +03:00
alloc: Correct existing use of positional fill.
Perform two allocation attempts with cling if maximise_cling is set, first with then without positional fill. Avoid segfaults from confusion between positional and sorted sequential allocation when number of stripes varies as reported here: https://www.redhat.com/archives/linux-lvm/2014-March/msg00001.html
This commit is contained in:
parent
1bf4c3a1fa
commit
8980592514
@ -1276,18 +1276,18 @@ static void _init_alloc_parms(struct alloc_handle *ah,
|
|||||||
* areas if the number of areas matches.
|
* areas if the number of areas matches.
|
||||||
*/
|
*/
|
||||||
if (alloc_parms->prev_lvseg &&
|
if (alloc_parms->prev_lvseg &&
|
||||||
((ah->area_count + ah->parity_count) == prev_lvseg->area_count))
|
((ah->area_count + ah->parity_count) == prev_lvseg->area_count)) {
|
||||||
alloc_parms->flags |= A_AREA_COUNT_MATCHES;
|
alloc_parms->flags |= A_AREA_COUNT_MATCHES;
|
||||||
|
|
||||||
/* Are there any preceding segments we must follow on from? */
|
/* Are there any preceding segments we must follow on from? */
|
||||||
if (alloc_parms->prev_lvseg &&
|
if (alloc_parms->alloc == ALLOC_CONTIGUOUS) {
|
||||||
(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;
|
alloc_parms->flags |= A_CONTIGUOUS_TO_LVSEG;
|
||||||
else if ((alloc_parms->alloc == ALLOC_CLING) ||
|
alloc_parms->flags |= A_POSITIONAL_FILL;
|
||||||
(alloc_parms->alloc == ALLOC_CLING_BY_TAGS))
|
} else if ((alloc_parms->alloc == ALLOC_CLING) ||
|
||||||
|
(alloc_parms->alloc == ALLOC_CLING_BY_TAGS)) {
|
||||||
alloc_parms->flags |= A_CLING_TO_LVSEG;
|
alloc_parms->flags |= A_CLING_TO_LVSEG;
|
||||||
|
alloc_parms->flags |= A_POSITIONAL_FILL;
|
||||||
|
}
|
||||||
} else
|
} else
|
||||||
/*
|
/*
|
||||||
* A cling allocation that follows a successful contiguous
|
* A cling allocation that follows a successful contiguous
|
||||||
@ -1916,7 +1916,7 @@ static area_use_t _check_pva(struct alloc_handle *ah, struct pv_area *pva, uint3
|
|||||||
if (!iteration_count && !log_iteration_count && alloc_parms->flags & (A_CONTIGUOUS_TO_LVSEG | A_CLING_TO_LVSEG | A_CLING_TO_ALLOCED)) {
|
if (!iteration_count && !log_iteration_count && alloc_parms->flags & (A_CONTIGUOUS_TO_LVSEG | A_CLING_TO_LVSEG | A_CLING_TO_ALLOCED)) {
|
||||||
/* Contiguous? */
|
/* Contiguous? */
|
||||||
if (((alloc_parms->flags & A_CONTIGUOUS_TO_LVSEG) ||
|
if (((alloc_parms->flags & A_CONTIGUOUS_TO_LVSEG) ||
|
||||||
(ah->maximise_cling && alloc_parms->prev_lvseg && (alloc_parms->flags & A_AREA_COUNT_MATCHES))) &&
|
(ah->maximise_cling && (alloc_parms->flags & A_AREA_COUNT_MATCHES))) &&
|
||||||
_check_contiguous(ah->cmd, alloc_parms->prev_lvseg, pva, alloc_state))
|
_check_contiguous(ah->cmd, alloc_parms->prev_lvseg, pva, alloc_state))
|
||||||
goto found;
|
goto found;
|
||||||
|
|
||||||
@ -1926,7 +1926,7 @@ static area_use_t _check_pva(struct alloc_handle *ah, struct pv_area *pva, uint3
|
|||||||
|
|
||||||
/* Cling to prev_lvseg? */
|
/* Cling to prev_lvseg? */
|
||||||
if (((alloc_parms->flags & A_CLING_TO_LVSEG) ||
|
if (((alloc_parms->flags & A_CLING_TO_LVSEG) ||
|
||||||
(ah->maximise_cling && alloc_parms->prev_lvseg && (alloc_parms->flags & A_AREA_COUNT_MATCHES))) &&
|
(ah->maximise_cling && (alloc_parms->flags & A_AREA_COUNT_MATCHES))) &&
|
||||||
_check_cling(ah, NULL, alloc_parms->prev_lvseg, pva, alloc_state))
|
_check_cling(ah, NULL, alloc_parms->prev_lvseg, pva, alloc_state))
|
||||||
/* If this PV is suitable, use this first area */
|
/* If this PV is suitable, use this first area */
|
||||||
goto found;
|
goto found;
|
||||||
@ -1940,7 +1940,7 @@ static area_use_t _check_pva(struct alloc_handle *ah, struct pv_area *pva, uint3
|
|||||||
if (!(alloc_parms->flags & A_CLING_BY_TAGS) || !ah->cling_tag_list_cn)
|
if (!(alloc_parms->flags & A_CLING_BY_TAGS) || !ah->cling_tag_list_cn)
|
||||||
return NEXT_PV;
|
return NEXT_PV;
|
||||||
|
|
||||||
if (alloc_parms->prev_lvseg && (alloc_parms->flags & A_AREA_COUNT_MATCHES)) {
|
if ((alloc_parms->flags & A_AREA_COUNT_MATCHES)) {
|
||||||
if (_check_cling(ah, ah->cling_tag_list_cn, alloc_parms->prev_lvseg, pva, alloc_state))
|
if (_check_cling(ah, ah->cling_tag_list_cn, alloc_parms->prev_lvseg, pva, alloc_state))
|
||||||
goto found;
|
goto found;
|
||||||
} else if (_check_cling_to_alloced(ah, ah->cling_tag_list_cn, pva, alloc_state))
|
} else if (_check_cling_to_alloced(ah, ah->cling_tag_list_cn, pva, alloc_state))
|
||||||
@ -2078,10 +2078,11 @@ static int _find_some_parallel_space(struct alloc_handle *ah,
|
|||||||
|
|
||||||
/* ix_offset holds the number of parallel allocations that must be contiguous/cling */
|
/* ix_offset holds the number of parallel allocations that must be contiguous/cling */
|
||||||
/* At most one of A_CONTIGUOUS_TO_LVSEG, A_CLING_TO_LVSEG or A_CLING_TO_ALLOCED may be set */
|
/* At most one of A_CONTIGUOUS_TO_LVSEG, A_CLING_TO_LVSEG or A_CLING_TO_ALLOCED may be set */
|
||||||
if (alloc_parms->flags & (A_CONTIGUOUS_TO_LVSEG | A_CLING_TO_LVSEG))
|
if (!(alloc_parms->flags & A_POSITIONAL_FILL))
|
||||||
|
ix_offset = 0;
|
||||||
|
else if (alloc_parms->flags & (A_CONTIGUOUS_TO_LVSEG | A_CLING_TO_LVSEG))
|
||||||
ix_offset = _stripes_per_mimage(alloc_parms->prev_lvseg) * alloc_parms->prev_lvseg->area_count;
|
ix_offset = _stripes_per_mimage(alloc_parms->prev_lvseg) * alloc_parms->prev_lvseg->area_count;
|
||||||
|
else if (alloc_parms->flags & A_CLING_TO_ALLOCED)
|
||||||
if (alloc_parms->flags & A_CLING_TO_ALLOCED)
|
|
||||||
ix_offset = ah->area_count;
|
ix_offset = ah->area_count;
|
||||||
|
|
||||||
if (alloc_parms->alloc == ALLOC_NORMAL || (alloc_parms->flags & A_CLING_TO_ALLOCED))
|
if (alloc_parms->alloc == ALLOC_NORMAL || (alloc_parms->flags & A_CLING_TO_ALLOCED))
|
||||||
@ -2089,7 +2090,9 @@ static int _find_some_parallel_space(struct alloc_handle *ah,
|
|||||||
alloc_parms->flags & A_CLING_TO_ALLOCED ? "" : "not ");
|
alloc_parms->flags & A_CLING_TO_ALLOCED ? "" : "not ");
|
||||||
|
|
||||||
if (alloc_parms->flags & A_POSITIONAL_FILL)
|
if (alloc_parms->flags & A_POSITIONAL_FILL)
|
||||||
log_debug_alloc("Preferred areas are filled positionally.");
|
log_debug_alloc("%u preferred area(s) to be filled positionally.", ix_offset);
|
||||||
|
else
|
||||||
|
log_debug_alloc("Areas to be sorted and filled sequentially.");
|
||||||
|
|
||||||
_clear_areas(alloc_state);
|
_clear_areas(alloc_state);
|
||||||
_reset_unreserved(pvms);
|
_reset_unreserved(pvms);
|
||||||
@ -2217,7 +2220,8 @@ static int _find_some_parallel_space(struct alloc_handle *ah,
|
|||||||
(ix + preferred_count >= devices_needed) &&
|
(ix + preferred_count >= devices_needed) &&
|
||||||
(ix + preferred_count < devices_needed + alloc_state->log_area_count_still_needed) && !log_iteration_count++));
|
(ix + preferred_count < devices_needed + alloc_state->log_area_count_still_needed) && !log_iteration_count++));
|
||||||
|
|
||||||
if (preferred_count < ix_offset && !(alloc_parms->flags & A_CLING_TO_ALLOCED))
|
/* Non-zero ix means at least one USE_AREA was returned */
|
||||||
|
if (preferred_count < ix_offset && !(alloc_parms->flags & A_CLING_TO_ALLOCED) && !ix)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (ix + preferred_count < devices_needed + alloc_state->log_area_count_still_needed)
|
if (ix + preferred_count < devices_needed + alloc_state->log_area_count_still_needed)
|
||||||
@ -2339,6 +2343,9 @@ static int _find_max_parallel_space_for_one_policy(struct alloc_handle *ah, stru
|
|||||||
return_0;
|
return_0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
* For ALLOC_CLING, if the number of areas matches and maximise_cling is
|
||||||
|
* set we allow two passes, first with A_POSITIONAL_FILL then without.
|
||||||
|
*
|
||||||
* If we didn't allocate anything this time with ALLOC_NORMAL and had
|
* If we didn't allocate anything this time with ALLOC_NORMAL and had
|
||||||
* A_CLING_TO_ALLOCED set, try again without it.
|
* A_CLING_TO_ALLOCED set, try again without it.
|
||||||
*
|
*
|
||||||
@ -2347,7 +2354,10 @@ static int _find_max_parallel_space_for_one_policy(struct alloc_handle *ah, stru
|
|||||||
* remain on the same disks where possible.
|
* remain on the same disks where possible.
|
||||||
*/
|
*/
|
||||||
if (old_allocated == alloc_state->allocated) {
|
if (old_allocated == alloc_state->allocated) {
|
||||||
if ((alloc_parms->alloc == ALLOC_NORMAL) && (alloc_parms->flags & A_CLING_TO_ALLOCED))
|
if (ah->maximise_cling && ((alloc_parms->alloc == ALLOC_CLING) || (alloc_parms->alloc == ALLOC_CLING_BY_TAGS)) &&
|
||||||
|
(alloc_parms->flags & A_CLING_TO_LVSEG) && (alloc_parms->flags & A_POSITIONAL_FILL))
|
||||||
|
alloc_parms->flags &= ~A_POSITIONAL_FILL;
|
||||||
|
else if ((alloc_parms->alloc == ALLOC_NORMAL) && (alloc_parms->flags & A_CLING_TO_ALLOCED))
|
||||||
alloc_parms->flags &= ~A_CLING_TO_ALLOCED;
|
alloc_parms->flags &= ~A_CLING_TO_ALLOCED;
|
||||||
else
|
else
|
||||||
break; /* Give up */
|
break; /* Give up */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user