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:
parent
b6af4a0aab
commit
b74c8033a2
@ -281,6 +281,8 @@ void export_lv(struct lv_disk *lvd, struct volume_group *vg,
|
||||
lvd->lv_read_ahead = lv->read_ahead;
|
||||
lvd->lv_stripes = list_item(lv->segments.n,
|
||||
struct stripe_segment)->stripes;
|
||||
lvd->lv_stripesize = list_item(lv->segments.n,
|
||||
struct stripe_segment)->stripe_size;
|
||||
|
||||
lvd->lv_size = lv->size;
|
||||
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++) {
|
||||
ped = &dl->extents[pe + seg->area[s].pe];
|
||||
ped->lv_num = lv_num;
|
||||
ped->le_num = seg->le + s +
|
||||
(seg->stripes * pe);
|
||||
ped->le_num = seg->le + pe +
|
||||
s * (seg->len / seg->stripes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
uint32_t stripes = lvm->stripes, s;
|
||||
uint32_t stripe_len = lvm->lv->le_count / stripes;
|
||||
uint32_t stripes = lvm->stripes, s, le = 0, pe;
|
||||
struct stripe_segment *seg;
|
||||
struct pe_specifier *pes;
|
||||
|
||||
while (le < lvm->lv->le_count) {
|
||||
if (!(seg = _alloc_seg(mem, stripes))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
seg->lv = lvm->lv;
|
||||
seg->le = 0;
|
||||
seg->len = lvm->lv->le_count;
|
||||
seg->le = le;
|
||||
seg->len = 0;
|
||||
seg->stripe_size = lvm->stripe_size;
|
||||
seg->stripes = stripes;
|
||||
|
||||
for (s = 0; s < stripes; s++) {
|
||||
pes = &lvm->map[s * stripe_len];
|
||||
seg->area[0].pv = lvm->map[le].pv;
|
||||
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].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);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,7 @@ static void _get_extents(struct stripe_segment *seg)
|
||||
struct physical_volume *pv;
|
||||
|
||||
for (s = 0; s < seg->stripes; s++) {
|
||||
pv = seg->area[s % seg->stripes].pv;
|
||||
pv = seg->area[s].pv;
|
||||
count = seg->len / seg->stripes;
|
||||
pv->pe_allocated += count;
|
||||
}
|
||||
@ -33,7 +33,7 @@ static void _put_extents(struct stripe_segment *seg)
|
||||
struct physical_volume *pv;
|
||||
|
||||
for (s = 0; s < seg->stripes; s++) {
|
||||
pv = seg->area[s % seg->stripes].pv;
|
||||
pv = seg->area[s].pv;
|
||||
count = seg->len / seg->stripes;
|
||||
|
||||
assert(pv->pe_allocated >= count);
|
||||
@ -54,7 +54,8 @@ static struct stripe_segment *_alloc_segment(struct pool *mem, int stripes)
|
||||
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)
|
||||
{
|
||||
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->len = per_area * stripes;
|
||||
seg->stripes = stripes;
|
||||
seg->stripe_size = stripe_size;
|
||||
|
||||
for (s = 0; s < stripes; 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 */
|
||||
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;
|
||||
goto out;
|
||||
}
|
||||
@ -175,7 +178,7 @@ static int _alloc_linear_area(struct logical_volume *lv, uint32_t *index,
|
||||
|
||||
count = pva->count;
|
||||
remaining = lv->le_count - *index;
|
||||
if (count < remaining)
|
||||
if (count > remaining)
|
||||
count = remaining;
|
||||
|
||||
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 1;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -387,6 +390,13 @@ struct logical_volume *lv_create(const char *name,
|
||||
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)))) {
|
||||
log_error("Failed to generate unique name for the new "
|
||||
"logical volume");
|
||||
|
@ -49,7 +49,11 @@ static int _set_allocated(struct hash_table *hash,
|
||||
}
|
||||
|
||||
/* 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);
|
||||
return 1;
|
||||
@ -60,9 +64,10 @@ static int _fill_bitsets(struct volume_group *vg, struct list *maps)
|
||||
struct list *lvh, *pvmh, *segh;
|
||||
struct logical_volume *lv;
|
||||
struct pv_map *pvm;
|
||||
uint32_t i, r = 0;
|
||||
uint32_t s, pe;
|
||||
struct hash_table *hash;
|
||||
struct stripe_segment *seg;
|
||||
int r = 0;
|
||||
|
||||
if (!(hash = hash_create(128))) {
|
||||
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) {
|
||||
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,
|
||||
seg->area[i % seg->stripes].pv,
|
||||
seg->area[i % seg->stripes].pe +
|
||||
(i / seg->stripes))) {
|
||||
seg->area[s].pv,
|
||||
seg->area[s].pe
|
||||
+ pe)) {
|
||||
stack;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
r = 1;
|
||||
|
||||
out:
|
||||
|
@ -212,7 +212,8 @@ int lvcreate(int argc, char **argv)
|
||||
}
|
||||
|
||||
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)) {
|
||||
log_verbose("Setting read ahead sectors");
|
||||
|
@ -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) {
|
||||
@ -333,7 +334,9 @@ int lvresize(int argc, char **argv)
|
||||
log_print("Extending logical volume %s to %s", lv_name, 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 ***********/
|
||||
|
Loading…
Reference in New Issue
Block a user