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

Fixes for allocation of striped volumes.

This commit is contained in:
Alasdair Kergon 2001-12-07 21:17:12 +00:00
parent b6af4a0aab
commit b74c8033a2
6 changed files with 88 additions and 39 deletions

View File

@ -281,6 +281,8 @@ void export_lv(struct lv_disk *lvd, struct volume_group *vg,
lvd->lv_read_ahead = lv->read_ahead; lvd->lv_read_ahead = lv->read_ahead;
lvd->lv_stripes = list_item(lv->segments.n, lvd->lv_stripes = list_item(lv->segments.n,
struct stripe_segment)->stripes; struct stripe_segment)->stripes;
lvd->lv_stripesize = list_item(lv->segments.n,
struct stripe_segment)->stripe_size;
lvd->lv_size = lv->size; lvd->lv_size = lv->size;
lvd->lv_allocated_le = lv->le_count; lvd->lv_allocated_le = lv->le_count;
@ -314,8 +316,8 @@ int export_extents(struct disk_list *dl, int lv_num,
for (pe = 0; pe < (seg->len / seg->stripes); pe++) { for (pe = 0; pe < (seg->len / seg->stripes); pe++) {
ped = &dl->extents[pe + seg->area[s].pe]; ped = &dl->extents[pe + seg->area[s].pe];
ped->lv_num = lv_num; ped->lv_num = lv_num;
ped->le_num = seg->le + s + ped->le_num = seg->le + pe +
(seg->stripes * pe); s * (seg->len / seg->stripes);
} }
} }
} }

View File

@ -238,30 +238,55 @@ static int _read_linear(struct pool *mem, struct lv_map *lvm)
static int _read_stripes(struct pool *mem, struct lv_map *lvm) static int _read_stripes(struct pool *mem, struct lv_map *lvm)
{ {
uint32_t stripes = lvm->stripes, s; uint32_t stripes = lvm->stripes, s, le = 0, pe;
uint32_t stripe_len = lvm->lv->le_count / stripes;
struct stripe_segment *seg; struct stripe_segment *seg;
struct pe_specifier *pes; struct pe_specifier *pes;
while (le < lvm->lv->le_count) {
if (!(seg = _alloc_seg(mem, stripes))) { if (!(seg = _alloc_seg(mem, stripes))) {
stack; stack;
return 0; return 0;
} }
seg->lv = lvm->lv; seg->lv = lvm->lv;
seg->le = 0; seg->le = le;
seg->len = lvm->lv->le_count; seg->len = 0;
seg->stripe_size = lvm->stripe_size; seg->stripe_size = lvm->stripe_size;
seg->stripes = stripes; seg->stripes = stripes;
for (s = 0; s < stripes; s++) { seg->area[0].pv = lvm->map[le].pv;
pes = &lvm->map[s * stripe_len]; seg->area[0].pe = lvm->map[le].pe;
do
seg->len++;
while ((lvm->map[le + seg->len].pv == seg->area[0].pv) &&
(lvm->map[le + seg->len].pe == seg->area[0].pe +
seg->len));
for (s = 1; s < stripes; s++) {
pes = &lvm->map[le + s * seg->len];
seg->area[s].pv = pes->pv; seg->area[s].pv = pes->pv;
seg->area[s].pe = pes->pe; seg->area[s].pe = pes->pe;
for (pe = 0; pe < seg->len; pe++) {
if (lvm->map[le + s * seg->len + pe].pe !=
pes->pe + pe) {
log_error("Incompatible striping at LE"
" %d on %s",
le + s * seg->len + pe,
seg->lv->name);
return 0;
}
}
} }
seg->len *= stripes;
le += seg->len;
list_add(&lvm->lv->segments, &seg->list); list_add(&lvm->lv->segments, &seg->list);
}
return 1; return 1;
} }

View File

@ -21,7 +21,7 @@ static void _get_extents(struct stripe_segment *seg)
struct physical_volume *pv; struct physical_volume *pv;
for (s = 0; s < seg->stripes; s++) { for (s = 0; s < seg->stripes; s++) {
pv = seg->area[s % seg->stripes].pv; pv = seg->area[s].pv;
count = seg->len / seg->stripes; count = seg->len / seg->stripes;
pv->pe_allocated += count; pv->pe_allocated += count;
} }
@ -33,7 +33,7 @@ static void _put_extents(struct stripe_segment *seg)
struct physical_volume *pv; struct physical_volume *pv;
for (s = 0; s < seg->stripes; s++) { for (s = 0; s < seg->stripes; s++) {
pv = seg->area[s % seg->stripes].pv; pv = seg->area[s].pv;
count = seg->len / seg->stripes; count = seg->len / seg->stripes;
assert(pv->pe_allocated >= count); assert(pv->pe_allocated >= count);
@ -54,7 +54,8 @@ static struct stripe_segment *_alloc_segment(struct pool *mem, int stripes)
return seg; return seg;
} }
static int _alloc_stripe_area(struct logical_volume *lv, int stripes, static int _alloc_stripe_area(struct logical_volume *lv, uint32_t stripes,
uint32_t stripe_size,
struct pv_area **areas, uint32_t *index) struct pv_area **areas, uint32_t *index)
{ {
uint32_t count = lv->le_count - *index; uint32_t count = lv->le_count - *index;
@ -75,6 +76,7 @@ static int _alloc_stripe_area(struct logical_volume *lv, int stripes,
seg->le = *index; seg->le = *index;
seg->len = per_area * stripes; seg->len = per_area * stripes;
seg->stripes = stripes; seg->stripes = stripes;
seg->stripe_size = stripe_size;
for (s = 0; s < stripes; s++) { for (s = 0; s < stripes; s++) {
struct pv_area *pva = areas[s]; struct pv_area *pva = areas[s];
@ -147,7 +149,8 @@ static int _alloc_striped(struct logical_volume *lv,
/* sort the areas so we allocate from the biggest */ /* sort the areas so we allocate from the biggest */
qsort(areas, index, sizeof(*areas), _comp_area); qsort(areas, index, sizeof(*areas), _comp_area);
if (!_alloc_stripe_area(lv, stripes, areas, &allocated)) { if (!_alloc_stripe_area(lv, stripes, stripe_size, areas,
&allocated)) {
stack; stack;
goto out; goto out;
} }
@ -175,7 +178,7 @@ static int _alloc_linear_area(struct logical_volume *lv, uint32_t *index,
count = pva->count; count = pva->count;
remaining = lv->le_count - *index; remaining = lv->le_count - *index;
if (count < remaining) if (count > remaining)
count = remaining; count = remaining;
if (!(seg = _alloc_segment(lv->vg->cmd->mem, 1))) { if (!(seg = _alloc_segment(lv->vg->cmd->mem, 1))) {
@ -272,7 +275,7 @@ static int _alloc_simple(struct logical_volume *lv,
return 0; return 0;
} }
return 0; return 1;
} }
/* /*
@ -387,6 +390,13 @@ struct logical_volume *lv_create(const char *name,
return NULL; return NULL;
} }
if (stripes > list_size(acceptable_pvs)) {
log_error("Number of stripes (%u) must not exceed "
"number of physical volumes (%d)", stripes,
list_size(acceptable_pvs));
return NULL;
}
if (!name && !(name = _generate_lv_name(vg, dname, sizeof(dname)))) { if (!name && !(name = _generate_lv_name(vg, dname, sizeof(dname)))) {
log_error("Failed to generate unique name for the new " log_error("Failed to generate unique name for the new "
"logical volume"); "logical volume");

View File

@ -49,7 +49,11 @@ static int _set_allocated(struct hash_table *hash,
} }
/* sanity check */ /* sanity check */
assert(!bit(pvm->allocated_extents, pe)); if (bit(pvm->allocated_extents, pe)) {
log_error("Physical extent %d of %s referenced by more than "
"one logical volume", pe, dev_name(pv->dev));
return 0;
}
bit_set(pvm->allocated_extents, pe); bit_set(pvm->allocated_extents, pe);
return 1; return 1;
@ -60,9 +64,10 @@ static int _fill_bitsets(struct volume_group *vg, struct list *maps)
struct list *lvh, *pvmh, *segh; struct list *lvh, *pvmh, *segh;
struct logical_volume *lv; struct logical_volume *lv;
struct pv_map *pvm; struct pv_map *pvm;
uint32_t i, r = 0; uint32_t s, pe;
struct hash_table *hash; struct hash_table *hash;
struct stripe_segment *seg; struct stripe_segment *seg;
int r = 0;
if (!(hash = hash_create(128))) { if (!(hash = hash_create(128))) {
log_err("Couldn't create hash table for pv maps."); log_err("Couldn't create hash table for pv maps.");
@ -85,17 +90,20 @@ static int _fill_bitsets(struct volume_group *vg, struct list *maps)
list_iterate (segh, &lv->segments) { list_iterate (segh, &lv->segments) {
seg = list_item(segh, struct stripe_segment); seg = list_item(segh, struct stripe_segment);
for (i = 0; i < seg->len; i++) { for (s = 0; s < seg->stripes; s++) {
for (pe = 0; pe < (seg->len / seg->stripes);
pe++) {
if (!_set_allocated(hash, if (!_set_allocated(hash,
seg->area[i % seg->stripes].pv, seg->area[s].pv,
seg->area[i % seg->stripes].pe + seg->area[s].pe
(i / seg->stripes))) { + pe)) {
stack; stack;
goto out; goto out;
} }
} }
} }
} }
}
r = 1; r = 1;
out: out:

View File

@ -212,7 +212,8 @@ int lvcreate(int argc, char **argv)
} }
if (!(lv = lv_create(lv_name, status, stripes, stripesize, extents, if (!(lv = lv_create(lv_name, status, stripes, stripesize, extents,
vg, pvh))) return ECMD_FAILED; vg, pvh)))
return ECMD_FAILED;
if (arg_count(readahead_ARG)) { if (arg_count(readahead_ARG)) {
log_verbose("Setting read ahead sectors"); log_verbose("Setting read ahead sectors");

View File

@ -296,7 +296,8 @@ int lvresize(int argc, char **argv)
} }
} }
lv_reduce(lv, lv->le_count - extents); if (!lv_reduce(lv, lv->le_count - extents))
return ECMD_FAILED;
} }
if (resize == LV_EXTEND && argc) { if (resize == LV_EXTEND && argc) {
@ -333,7 +334,9 @@ int lvresize(int argc, char **argv)
log_print("Extending logical volume %s to %s", lv_name, dummy); log_print("Extending logical volume %s to %s", lv_name, dummy);
dbg_free(dummy); dbg_free(dummy);
lv_extend(lv, stripes, stripesize, extents - lv->le_count, pvh); if (!lv_extend(lv, stripes, stripesize, extents - lv->le_count,
pvh))
return ECMD_FAILED;
} }
/********* FIXME Suspend lv ***********/ /********* FIXME Suspend lv ***********/