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_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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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");
|
||||||
|
@ -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:
|
||||||
|
@ -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");
|
||||||
|
@ -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 ***********/
|
||||||
|
Loading…
Reference in New Issue
Block a user