1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-12-21 13:34:40 +03:00

add cling allocation policy

This commit is contained in:
Alasdair Kergon 2006-10-08 12:01:13 +00:00
parent 4a2ca1b998
commit de5c82a0d9
6 changed files with 91 additions and 15 deletions

View File

@ -1,5 +1,6 @@
Version 2.02.11 -
=====================================
Add cling allocation policy.
Change _check_contiguous() to use _for_each_pv().
Extend _for_each_pv() to allow termination without error.
Abstract _is_contiguous().

View File

@ -30,6 +30,7 @@ static struct {
} _policies[] = {
{
ALLOC_CONTIGUOUS, "contiguous"}, {
ALLOC_CLING, "cling"}, {
ALLOC_NORMAL, "normal"}, {
ALLOC_ANYWHERE, "anywhere"}, {
ALLOC_INHERIT, "inherit"}

View File

@ -772,6 +772,17 @@ struct pv_match {
int s; /* Area index of match */
};
/*
* Is PV area on the same PV?
*/
static int _is_same_pv(struct pv_segment *pvseg, struct pv_area *pva)
{
if (pvseg->pv != pva->map->pv)
return 0;
return 1;
}
/*
* Is PV area contiguous to PV segment?
*/
@ -786,9 +797,9 @@ static int _is_contiguous(struct pv_segment *pvseg, struct pv_area *pva)
return 1;
}
static int _is_contiguous_condition(struct cmd_context *cmd,
struct pv_segment *pvseg, uint32_t s,
void *data)
static int _is_condition(struct cmd_context *cmd,
struct pv_segment *pvseg, uint32_t s,
void *data)
{
struct pv_match *pvmatch = data;
@ -803,6 +814,34 @@ static int _is_contiguous_condition(struct cmd_context *cmd,
return 2; /* Finished */
}
/*
* Is pva on same PV as any existing areas?
*/
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_match pvmatch;
int r;
pvmatch.condition = _is_same_pv;
pvmatch.areas = areas;
pvmatch.areas_size = areas_size;
pvmatch.pva = pva;
/* 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,
_is_condition, &pvmatch)))
stack;
if (r != 2)
return 0;
return 1;
}
/*
* Is pva contiguous to any existing areas or on the same PV?
*/
@ -822,7 +861,7 @@ static int _check_contiguous(struct cmd_context *cmd,
if (!(r = _for_each_pv(cmd, prev_lvseg->lv,
prev_lvseg->le + prev_lvseg->len - 1, 1, NULL,
0, 0, -1, 1,
_is_contiguous_condition, &pvmatch)))
_is_condition, &pvmatch)))
stack;
if (r != 2)
@ -844,9 +883,9 @@ static int _find_parallel_space(struct alloc_handle *ah, alloc_policy_t alloc,
struct pv_area *pva;
struct pv_list *pvl;
unsigned already_found_one = 0;
unsigned contiguous = 0, contiguous_count = 0;
unsigned contiguous = 0, cling = 0, preferred_count = 0;
unsigned ix;
unsigned ix_offset = 0; /* Offset for non-contiguous allocations */
unsigned ix_offset = 0; /* Offset for non-preferred allocations */
uint32_t max_parallel; /* Maximum extents to allocate */
uint32_t next_le;
struct seg_pvs *spvs;
@ -856,9 +895,14 @@ static int _find_parallel_space(struct alloc_handle *ah, alloc_policy_t alloc,
/* FIXME Select log PV appropriately if there isn't one yet */
/* Are there any preceding segments we must follow on from? */
if ((alloc == ALLOC_CONTIGUOUS) && prev_lvseg) {
contiguous = 1;
if (prev_lvseg) {
ix_offset = prev_lvseg->area_count;
if ((alloc == ALLOC_CONTIGUOUS))
contiguous = 1;
else if ((alloc == ALLOC_CLING))
cling = 1;
else
ix_offset = 0;
}
/* FIXME This algorithm needs a lot of cleaning up! */
@ -867,6 +911,7 @@ static int _find_parallel_space(struct alloc_handle *ah, alloc_policy_t alloc,
/* ix holds the number of areas found on other PVs */
do {
ix = 0;
preferred_count = 0;
parallel_pvs = NULL;
max_parallel = needed;
@ -920,12 +965,23 @@ static int _find_parallel_space(struct alloc_handle *ah, alloc_policy_t alloc,
prev_lvseg,
pva, areas,
areas_size)) {
contiguous_count++;
preferred_count++;
goto next_pv;
}
continue;
}
if (cling) {
if (prev_lvseg &&
_check_cling(ah->cmd,
prev_lvseg,
pva, areas,
areas_size)) {
preferred_count++;
}
goto next_pv;
}
/* Is it big enough on its own? */
if (pva->count * ah->area_multiple <
max_parallel - *allocated &&
@ -949,7 +1005,7 @@ static int _find_parallel_space(struct alloc_handle *ah, alloc_policy_t alloc,
break;
}
if (contiguous && (contiguous_count < ix_offset))
if ((contiguous || cling) && (preferred_count < ix_offset))
break;
/* Only allocate log_area the first time around */
@ -1058,6 +1114,18 @@ static int _allocate(struct alloc_handle *ah,
(!can_split && (allocated != old_allocated)))
goto finished;
old_allocated = allocated;
if (!_find_parallel_space(ah, ALLOC_CLING, pvms, areas,
areas_size, can_split,
prev_lvseg, &allocated, new_extents)) {
stack;
goto out;
}
if ((allocated == new_extents) || (ah->alloc == ALLOC_CLING) ||
(!can_split && (allocated != old_allocated)))
goto finished;
old_allocated = allocated;
if (!_find_parallel_space(ah, ALLOC_NORMAL, pvms, areas,
areas_size, can_split,

View File

@ -82,6 +82,7 @@ typedef enum {
ALLOC_INVALID = 0,
ALLOC_INHERIT,
ALLOC_CONTIGUOUS,
ALLOC_CLING,
ALLOC_NORMAL,
ALLOC_ANYWHERE
} alloc_policy_t;

View File

@ -104,6 +104,8 @@ static char _alloc_policy_char(alloc_policy_t alloc)
switch (alloc) {
case ALLOC_CONTIGUOUS:
return 'c';
case ALLOC_CLING:
return 'C';
case ALLOC_NORMAL:
return 'n';
case ALLOC_ANYWHERE:

View File

@ -136,7 +136,7 @@ Characters allowed in tags are: A-Z a-z 0-9 _ + . -
Delete the tag \fBtag\fP from a PV, VG or LV, if it's present.
.TP
\fB--alloc AllocationPolicy\fP
The allocation policy to use: \fBcontiguous\fP, \fBnormal\fP, \fBanywhere\fP or \fBinherit\fP.
The allocation policy to use: \fBcontiguous\fP, \fBcling\fP, \fBnormal\fP, \fBanywhere\fP or \fBinherit\fP.
When a command needs to allocate physical extents from the volume group,
the allocation policy controls how they are chosen.
Each volume group and logical volume has an allocation policy.
@ -146,15 +146,18 @@ physical volume. The default for a logical volume is \fBinherit\fP
which applies the same policy as for the volume group. These policies can
be changed using \fBlvchange\fP (8) and \fBvgchange\fP (8) or over-ridden
on the command line of any command that performs allocation.
The \fBcontiguous\fP policy requires that new extents are adjacent to
existing extents. If there are sufficient free extents to satisfy
The \fBcontiguous\fP policy requires that new extents be placed adjacent
to existing extents.
The \fBcling\fP policy places new extents on the same physical
volume as existing extents in the same stripe of the Logical Volume.
If there are sufficient free extents to satisfy
an allocation request but \fBnormal\fP doesn't use them,
\fBanywhere\fP will - even if that reduces performance by
placing two stripes on the same physical volume.
.IP
N.B. The policies described above are not implemented fully yet.
In particular, \fBcontiguous\fP does not place new extents adjacent to existing
extents and \fBanywhere\fP is not implemented at all.
In particular, contiguous free space cannot be broken up to
satisfy allocation attempts.
.SH ENVIRONMENT VARIABLES
.TP
\fBLVM_SYSTEM_DIR\fP