1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-01-03 05:18:29 +03:00

Fix contiguous allocations with linear.

This commit is contained in:
Alasdair Kergon 2005-05-11 16:46:59 +00:00
parent fece730645
commit 0888dc43cf
4 changed files with 59 additions and 43 deletions

View File

@ -1,5 +1,6 @@
Version 2.01.11 - Version 2.01.11 -
============================== ==============================
Fix contiguous allocation policy with linear.
Cope with missing format1 PVs again. Cope with missing format1 PVs again.
Remove lists of free PV segments. Remove lists of free PV segments.
Simplify pv_maps code and remove slow bitset algorithm. Simplify pv_maps code and remove slow bitset algorithm.

View File

@ -103,6 +103,14 @@ static inline int list_end(struct list *head, struct list *elem)
return elem->n == head; return elem->n == head;
} }
/*
* Return last element of the list or NULL if empty
*/
static inline struct list *list_last(struct list *head)
{
return (list_empty(head) ? NULL : head->p);
}
/* /*
* Return the previous element of the list, or NULL if we've reached the start. * Return the previous element of the list, or NULL if we've reached the start.
*/ */

View File

@ -196,9 +196,8 @@ static int _alloc_parallel(struct logical_volume *lv,
uint32_t mirrors, struct segment_type *segtype) uint32_t mirrors, struct segment_type *segtype)
{ {
int r = 0; int r = 0;
struct list *pvmh;
struct pv_area **areas; struct pv_area **areas;
unsigned int pv_count = 0, ix; unsigned int pv_count, ix;
struct pv_map *pvm; struct pv_map *pvm;
size_t len; size_t len;
uint32_t area_count; uint32_t area_count;
@ -213,8 +212,7 @@ static int _alloc_parallel(struct logical_volume *lv,
else else
area_count = mirrors; area_count = mirrors;
list_iterate(pvmh, pvms) pv_count = list_size(pvms);
pv_count++;
/* allocate an array of pv_areas, one candidate per pv */ /* allocate an array of pv_areas, one candidate per pv */
len = sizeof(*areas) * pv_count; len = sizeof(*areas) * pv_count;
@ -226,9 +224,7 @@ static int _alloc_parallel(struct logical_volume *lv,
while (allocated != lv->le_count) { while (allocated != lv->le_count) {
ix = 0; ix = 0;
list_iterate(pvmh, pvms) { list_iterate_items(pvm, pvms) {
pvm = list_item(pvmh, struct pv_map);
if (list_empty(&pvm->areas)) if (list_empty(&pvm->areas))
continue; continue;
@ -341,39 +337,54 @@ static int _alloc_mirrored_area(struct logical_volume *lv, uint32_t *ix,
* can complete the allocation. * can complete the allocation.
*/ */
/*
* FIXME: subsequent lvextends may not be contiguous.
*/
static int _alloc_contiguous(struct logical_volume *lv, static int _alloc_contiguous(struct logical_volume *lv,
struct list *pvms, uint32_t allocated) struct list *pvms, uint32_t allocated)
{ {
struct list *tmp1;
struct pv_map *pvm; struct pv_map *pvm;
struct pv_area *pva; struct pv_area *pva;
struct lv_segment *prev_lvseg;
struct pv_segment *prev_pvseg = NULL;
uint32_t largest = 0;
list_iterate(tmp1, pvms) { /* So far the only case is exactly one area */
pvm = list_item(tmp1, struct pv_map); if ((prev_lvseg = list_item(list_last(&lv->segments), struct lv_segment)) &&
(prev_lvseg->area_count == 1) &&
(prev_lvseg->area[0].type == AREA_PV))
prev_pvseg = prev_lvseg->area[0].u.pv.pvseg;
if (list_empty(&pvm->areas)) list_iterate_items(pvm, pvms) {
if (prev_pvseg && (prev_pvseg->pv != pvm->pv))
continue; continue;
/* first item in the list is the biggest */ list_iterate_items(pva, &pvm->areas) {
pva = list_item(pvm->areas.n, struct pv_area); if (prev_pvseg &&
if (pva->count < lv->le_count) (prev_pvseg->pe + prev_pvseg->len != pva->start))
continue; continue;
if (!_alloc_linear_area(lv, &allocated, pvm, pva)) { if (pva->count > largest)
stack; largest = pva->count;
return 0;
/* first item in the list is the biggest */
if (pva->count < lv->le_count - allocated)
goto next_pv;
if (!_alloc_linear_area(lv, &allocated, pvm, pva)) {
stack;
return 0;
}
goto out;
} }
break; next_pv:
;
} }
out:
if (allocated != lv->le_count) { if (allocated != lv->le_count) {
log_error("Insufficient allocatable extents (%u) " log_error("Insufficient allocatable extents (%u) "
"for logical volume %s: %u required", "for logical volume %s: %u required",
allocated, lv->name, lv->le_count); largest, lv->name, lv->le_count - allocated);
return 0; return 0;
} }
@ -387,15 +398,12 @@ static int _alloc_mirrored(struct logical_volume *lv,
struct physical_volume *mirrored_pv, struct physical_volume *mirrored_pv,
uint32_t mirrored_pe) uint32_t mirrored_pe)
{ {
struct list *tmp1;
struct pv_map *pvm; struct pv_map *pvm;
struct pv_area *pva; struct pv_area *pva;
uint32_t max_found = 0; uint32_t max_found = 0;
/* Try each PV in turn */ /* Try each PV in turn */
list_iterate(tmp1, pvms) { list_iterate_items(pvm, pvms) {
pvm = list_item(tmp1, struct pv_map);
if (list_empty(&pvm->areas)) if (list_empty(&pvm->areas))
continue; continue;
@ -432,15 +440,11 @@ static int _alloc_mirrored(struct logical_volume *lv,
static int _alloc_next_free(struct logical_volume *lv, static int _alloc_next_free(struct logical_volume *lv,
struct list *pvms, uint32_t allocated) struct list *pvms, uint32_t allocated)
{ {
struct list *tmp1, *tmp2;
struct pv_map *pvm; struct pv_map *pvm;
struct pv_area *pva; struct pv_area *pva;
list_iterate(tmp1, pvms) { list_iterate_items(pvm, pvms) {
pvm = list_item(tmp1, struct pv_map); list_iterate_items(pva, &pvm->areas) {
list_iterate(tmp2, &pvm->areas) {
pva = list_item(tmp2, struct pv_area);
if (!_alloc_linear_area(lv, &allocated, pvm, pva) || if (!_alloc_linear_area(lv, &allocated, pvm, pva) ||
(allocated == lv->le_count)) (allocated == lv->le_count))
goto done; goto done;
@ -560,7 +564,7 @@ static int _allocate(struct logical_volume *lv,
* Iterate through the new segments, updating pe * Iterate through the new segments, updating pe
* counts in pv's. * counts in pv's.
*/ */
for (segh = lv->segments.p; segh != old_tail; segh = segh->p) { list_uniterate(segh, old_tail, &lv->segments) {
seg = list_item(segh, struct lv_segment); seg = list_item(segh, struct lv_segment);
_get_extents(seg); _get_extents(seg);
seg->status = status; seg->status = status;
@ -581,14 +585,11 @@ static int _allocate(struct logical_volume *lv,
static char *_generate_lv_name(struct volume_group *vg, const char *format, static char *_generate_lv_name(struct volume_group *vg, const char *format,
char *buffer, size_t len) char *buffer, size_t len)
{ {
struct list *lvh; struct lv_list *lvl;
struct logical_volume *lv;
int high = -1, i; int high = -1, i;
list_iterate(lvh, &vg->lvs) { list_iterate_items(lvl, &vg->lvs) {
lv = (list_item(lvh, struct lv_list)->lv); if (sscanf(lvl->lv->name, format, &i) != 1)
if (sscanf(lv->name, format, &i) != 1)
continue; continue;
if (i > high) if (i > high)
@ -822,14 +823,12 @@ uint32_t find_free_lvnum(struct logical_volume *lv)
{ {
int lvnum_used[MAX_RESTRICTED_LVS + 1]; int lvnum_used[MAX_RESTRICTED_LVS + 1];
uint32_t i = 0; uint32_t i = 0;
struct list *lvh;
struct lv_list *lvl; struct lv_list *lvl;
int lvnum; int lvnum;
memset(&lvnum_used, 0, sizeof(lvnum_used)); memset(&lvnum_used, 0, sizeof(lvnum_used));
list_iterate(lvh, &lv->vg->lvs) { list_iterate_items(lvl, &lv->vg->lvs) {
lvl = list_item(lvh, struct lv_list);
lvnum = lvnum_from_lvid(&lvl->lv->lvid); lvnum = lvnum_from_lvid(&lvl->lv->lvid);
if (lvnum <= MAX_RESTRICTED_LVS) if (lvnum <= MAX_RESTRICTED_LVS)
lvnum_used[lvnum] = 1; lvnum_used[lvnum] = 1;

View File

@ -103,6 +103,14 @@ static inline int list_end(struct list *head, struct list *elem)
return elem->n == head; return elem->n == head;
} }
/*
* Return last element of the list or NULL if empty
*/
static inline struct list *list_last(struct list *head)
{
return (list_empty(head) ? NULL : head->p);
}
/* /*
* Return the previous element of the list, or NULL if we've reached the start. * Return the previous element of the list, or NULL if we've reached the start.
*/ */