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

o Sync up todays work on converting to the segmented representation of

logical volumes.  It includes:

   format1 changes.

   metadata.h changes.

   lv_manip.c changed (striped allocation still not done though).

   activate.c changes.

Nothing has been near a compiler as yet.

Alasdair can you look at changing display.c to use to output the mappings
in a more segment oriented format please ?

I haven't put the span list into struct physical_volume to represent allocated
extents.  I think the burden of maintaining it for things like lv_extend may
out weigh it's uses.
This commit is contained in:
Joe Thornber 2001-11-27 16:37:33 +00:00
parent 52dc213926
commit 0bab65915d
8 changed files with 513 additions and 238 deletions

View File

@ -26,6 +26,7 @@ SOURCES=\
format1/disk-rep.c \
format1/format1.c \
format1/import-export.c \
format1/import-extents.c \
format1/layout.c \
format1/vg_number.c \
log/log.c \

View File

@ -84,40 +84,33 @@ int lv_open_count(struct logical_volume *lv)
}
/*
* Creates a target for the next contiguous run of
* extents.
* Emit a target for a given segment.
*/
static int _emit_target(struct dm_task *dmt, struct logical_volume *lv,
unsigned int *ple)
static int _emit_target(struct dm_task *dmt, struct stripe_segment *seg)
{
char params[1024];
unsigned int le = *ple;
uint64_t esize = lv->vg->extent_size;
int i, count = 0;
struct pe_specifier *pes, *first = NULL;
uint32_t s, stripes = seg->stripes;
int w, tw;
for (i = le; i < lv->le_count; i++) {
pes = lv->map + i;
for (w = 0, s = 0; s < stripes; s++, w += tw) {
tw = snprintf(params + w, sizeof(params) - w,
"%s %" PRIu64 "%s",
dev_name(seg->area[s].pv->dev),
(seg->area[s].pv->pe_start +
(esize * seg->area[s].pe)),
s == (stripes - 1) ? "" : " ");
if (!first)
first = pes;
/*
* check that we're still contiguous.
*/
else if ((pes->pv != first->pv) ||
(pes->pe != first->pe + count))
break;
count++;
if (tw < 0) {
log_err("Insufficient space to write target "
"parameters.");
return 0;
}
}
snprintf(params, sizeof(params), "%s %" PRIu64,
dev_name(first->pv->dev),
first->pv->pe_start + (esize * first->pe));
if (!dm_task_add_target(dmt, esize * le, esize * count,
"linear", params)) {
if (!dm_task_add_target(dmt, esize * le, esize * seg->len,
stripes == 1 ? "linear" : "striped",
params)) {
stack;
return 0;
}
@ -129,19 +122,18 @@ static int _emit_target(struct dm_task *dmt, struct logical_volume *lv,
int _load(struct logical_volume *lv, int task)
{
int r = 0;
uint32_t le = 0;
struct dm_task *dmt;
struct list *segh;
struct stripe_segment *seg;
if (!(dmt = _setup_task(lv, task))) {
stack;
return 0;
}
/*
* Merge adjacent extents.
*/
while (le < lv->le_count) {
if (!_emit_target(dmt, lv, &le)) {
list_iterate(segh, &lv->segments) {
seg = list_item(segh, struct stripe_segment);
if (!_emit_target(dmt, seg)) {
log_error("Unable to activate logical volume '%s'",
lv->name);
goto out;
@ -285,4 +277,3 @@ int lvs_in_vg_opened(struct volume_group *vg)
return count;
}

View File

@ -36,28 +36,6 @@ static char *_create_lv_name(struct pool *mem, const char *full_name)
return pool_strdup(mem, ptr);
}
static int _fill_lv_array(struct logical_volume **lvs,
struct volume_group *vg, struct disk_list *dl)
{
struct list *lvh;
struct logical_volume *lv;
int i = 0;
list_iterate(lvh, &dl->lvds) {
struct lvd_list *ll = list_item(lvh, struct lvd_list);
if (!(lv = find_lv(vg, ll->lvd.lv_name))) {
stack;
return 0;
}
lvs[i] = lv;
i++;
}
return 1;
}
int import_pv(struct pool *mem, struct device *dev,
struct physical_volume *pv, struct pv_disk *pvd)
{
@ -81,6 +59,9 @@ int import_pv(struct pool *mem, struct device *dev,
pv->pe_start = pvd->pe_start;
pv->pe_count = pvd->pe_total;
pv->pe_allocated = pvd->pe_allocated;
init_list(&pv->allocated);
return 1;
}
@ -268,12 +249,12 @@ int import_lv(struct pool *mem, struct logical_volume *lv, struct lv_disk *lvd)
lv->size = lvd->lv_size;
lv->le_count = lvd->lv_allocated_le;
len = sizeof(struct pe_specifier) * lv->le_count;
if (!(lv->map = pool_alloc(mem, len))) {
list_init(&lv->segments);
if (!lv->segments) {
stack;
return 0;
}
memset(lv->map, 0, len);
return 1;
}
@ -323,71 +304,34 @@ void export_lv(struct lv_disk *lvd, struct volume_group *vg,
lvd->lv_allocation |= LV_CONTIGUOUS;
}
int import_extents(struct pool *mem, struct volume_group *vg, struct list *pvds)
{
struct disk_list *dl;
struct logical_volume *lv, *lvs[MAX_LV];
struct physical_volume *pv;
struct pe_disk *e;
int i;
uint32_t lv_num, le;
struct list *pvdh;
list_iterate(pvdh, pvds) {
dl = list_item(pvdh, struct disk_list);
pv = _find_pv(vg, dl->dev);
e = dl->extents;
/* build an array of lv's for this pv */
if (!_fill_lv_array(lvs, vg, dl)) {
stack;
return 0;
}
for (i = 0; i < dl->pvd.pe_total; i++) {
lv_num = e[i].lv_num;
if (lv_num == UNMAPPED_EXTENT)
continue;
else if(lv_num > dl->pvd.lv_cur) {
log_err("invalid lv in extent map\n");
return 0;
} else {
lv_num--;
lv = lvs[lv_num];
le = e[i].le_num;
if (le >= lv->le_count) {
log_err("logical extent number "
"out of bounds");
return 0;
}
lv->map[le].pv = pv;
lv->map[le].pe = i;
}
}
}
return 1;
}
int export_extents(struct disk_list *dl, int lv_num,
struct logical_volume *lv,
struct physical_volume *pv)
{
struct list *segh;
struct pe_disk *ped;
int le;
struct stripe_segment *seg;
uint32_t pe;
struct span *pes;
for (le = 0; le < lv->le_count; le++) {
if (lv->map[le].pv == pv) {
ped = &dl->extents[lv->map[le].pe];
ped->lv_num = lv_num;
ped->le_num = le;
list_iterate (segh, &lv->segments) {
seg = list_item(segh, struct stripe_segment);
for (a = 0; a < seg->stripes; a++) {
if (seg->areas[a].pv != pv)
continue; /* not our pv */
pes = seg->areas[a].pes;
for (pe = 0; pe < pe->len; pe++) {
ped = &dl->extents[pe + pes->start];
ped->lv_num = lv_num;
ped->le_num = seg->le + a +
(seg->stripes * pe);
}
}
}
return 1;
}

View File

@ -0,0 +1,278 @@
/*
* Copyright (C) 2001 Sistina Software (UK) Limited.
*
* This file is released under the LGPL.
*/
#include "metadata.h"
#include "hash.h"
#include "dbg_malloc.h"
/*
* After much thought I have decided it is easier,
* and probably no less efficient, to convert the
* pe->le map to a full le->pe map, and then
* process this to get the segments form that
* we're after. Any code which goes directly from
* the pe->le map to segments would be gladly
* accepted, if it is less complicated than this
* file.
*/
struct pe_specifier {
struct physical_volume *pv;
uint32_t pe;
};
struct lv_map {
struct logical_volume *lv;
struct pe_specifier *map;
};
static struct hash_table *
_create_lv_maps(struct pool *mem, struct volume_group *vg)
{
struct hash_table *maps = hash_create(32);
struct list *llh;
struct lv_list *ll;
struct lv_map *lvm;
if (!maps) {
log_err("Unable to create hash table for holding "
"extent maps.");
return NULL;
}
list_iterate (llh, &vg->lvs) {
ll = list_item(llh, struct lv_list);
if (!(lvm = pool_alloc(mem, sizeof(*lvm)))) {
stack;
goto bad;
}
lvm->lv = ll->lv;
if (!(lvm->map = pool_zalloc(sizeof(*lvm->map)
* ll->lv->le_count))) {
stack;
goto bad;
}
if (!hash_insert(maps, ll->lv->name, lvm)) {
stack;
goto bad;
}
}
return maps;
bad:
hash_destroy(maps);
return NULL;
}
static int _fill_lv_array(struct lv_map **lvs,
struct hash_table *maps, struct disk_list *dl)
{
struct list *lvh;
struct lv_map *lvm;
int i = 0;
list_iterate(lvh, &dl->lvds) {
struct lvd_list *ll = list_item(lvh, struct lvd_list);
if (!(lvm = hash_lookup(maps, ll->lvd.lv_name))) {
log_err("Physical volume (%s) contains an "
"unknown logical volume (%s).",
dev_name(dl->dev), ll->lvd.lv_name);
return 0;
}
lvs[i++] = lvm;
}
return 1;
}
static int _fill_maps(struct hash_table *maps, struct list *pvds)
{
struct list *pvdh;
struct lv_map *map;
list_iterate(pvdh, pvds) {
dl = list_item(pvdh, struct disk_list);
pv = find_pv(vg, dl->dev);
e = dl->extents;
/* build an array of lv's for this pv */
if (!_fill_lv_array(lvs, vg, dl)) {
stack;
return 0;
}
for (i = 0; i < dl->pvd.pe_total; i++) {
lv_num = e[i].lv_num;
if (lv_num == UNMAPPED_EXTENT)
continue;
else if(lv_num > dl->pvd.lv_cur) {
log_err("invalid lv in extent map");
return 0;
} else {
lv_num--;
lvm = lvs[lv_num];
le = e[i].le_num;
if (le >= lvm->lv->le_count) {
log_err("logical extent number "
"out of bounds");
return 0;
}
lvm->map[le].pv = pv;
lvm->map[le].pe = i;
}
}
}
return 1;
}
static int _check_single_map(struct lv_map *lvm)
{
uint32_t i;
for (i = 0; i < lvm->lv->le_count; i++) {
if (!lvm->map[i].pv) {
log_err("Logical volume (%s) contains an incomplete "
"mapping table.", lvm->lv->name);
return 0;
}
}
return 1;
}
static int _check_maps_are_complete(struct hash_table *maps)
{
struct hash_node *n;
for (n = hash_get_first(maps); n; n = hash_get_next(maps, n)) {
lvm = (struct lv_map *) hash_get_data(maps, n);
if (!_check_single_map(lvm)) {
stack;
return 0;
}
}
return 1;
}
static int _same_segment(struct stripe_segment *seg, struct lv_map *lvm,
uint32_t count)
{
uint32_t s;
uint32_t le = seg->le + (count * seg->stripes);
for (s = 0; s < stripes; s++) {
if ((lvm->map[le + s].pv != seg->area[s].pv) ||
(lvm->map[le + s].pe != seg->area[s].pe + count))
return 0;
}
return 1;
}
static int _build_segments(struct pool *mem, struct lv_map *lvm)
{
uint32_t stripes = lvm->lv->stripes;
uint32_t le;
struct stripe_segment *seg;
size_t len;
len = sizeof(*seg) * (stripes * sizeof(seg->area[0]));
for (le = 0; le < lvm->lv->le_count;) {
if (!(seg = pool_zalloc(mem, len))) {
stack;
return 0;
}
seg->lv = lvm->lv;
seg->le = le;
seg->len = 0;
seg->stripe_size = lvm->stripe_size;
seg->stripes = stripes;
for (s = 0; s < stripes; s++) {
seg->area[s].pv = lvm->map[le + s].pv;
seg->area[s].pe = lvm->map[le + s].pe;
}
count = 1;
do {
le += stripes;
seg->len += stripes;
} while (_same_segment(seg, lvm, count++));
list_add(&lvm->lv->segments, seg);
}
return 1;
}
static int _build_all_segments(struct pool *mem, struct hash_table *maps)
{
struct hash_node *n;
struct lv_map *lvm;
for (n = hash_get_first(maps); n; n = hash_get_next(maps, n)) {
lvm = (struct lv_map *) hash_get_data(maps, n);
if (!_build_segments(mem, lvm)) {
stack;
return 0;
}
}
return 1;
}
int import_extents(struct pool *mem, struct volume_group *vg,
struct list *pvds)
{
int r = 0;
struct pool *scratch = pool_create(10 * 1024);
struct hash_table *maps;
if (!scratch) {
stack;
return 0;
}
if (!(maps = _create_lv_maps(scratch, vg))) {
log_err("Couldn't allocate logical volume maps.");
goto out;
}
if (!_fill_maps(maps, pvds)) {
log_err("Couldn't fill logical volume maps.");
goto out;
}
if (!_check_maps_are_complete(maps)) {
stack;
goto out;
}
if (!_build_all_segments(mem, maps)) {
log_err("Couldn't build extent segments.");
goto out;
}
r = 1;
out:
if (maps)
hash_destroy(maps);
pool_destroy(scratch);
return r;
}

View File

@ -8,7 +8,6 @@ vg {
extent_size = 8192 # 4M
extent_count = 1024
free_count = 430
max_lv = 99
max_pv = 255
@ -20,15 +19,12 @@ vg {
pv1 {
id = "lksjdflksdlsk"
major = 123
minor = 23
device = "/dev/hda1"
status = [???]
size = ??
pe_start = 8192
pe_count = 300
pe_allocated = 30
pe_count = 300 # ???M
}
lv1 {

View File

@ -8,6 +8,38 @@
#include "pv_map.h"
#include "log.h"
#include <assert.h>
/*
* These functions adjust the pe counts in pv's
* after we've added or removed segments.
*/
static void _get_extents(struct stripe_segment *seg)
{
int s, count;
struct physical_volume *pv;
for (s = 0; i < seg->stripes; s++) {
pv = seg->area[i % seg->stripes].pv;
count = seg->len / seg->stripes;
pv->pe_allocated += count;
}
}
static void _put_extents(struct stripe_segment *seg)
{
int s, count;
struct physical_volume *pv;
for (s = 0; i < seg->stripes; s++) {
pv = seg->area[i % seg->stripes].pv;
count = seg->len / seg->stripes;
assert(pv->pe_allocated >= count);
pv->pe_allocated -= count;
}
}
/*
* The heart of the allocation code. This
* function takes a pv_area and allocates it to
@ -15,15 +47,16 @@
* area then the area is split, otherwise the area
* is unlinked from the pv_map.
*/
static int _alloc_area(struct logical_volume *lv, uint32_t index,
struct physical_volume *pv, struct pv_area *pva)
static int _alloc_linear_area(struct logical_volume *lv, uint32_t *index,
struct physical_volume *pv, struct pv_area *pva)
{
uint32_t count, remaining, i, start;
struct stripe_segment *seg;
start = pva->start;
count = pva->count;
remaining = lv->le_count - index;
remaining = lv->le_count - *index;
if (remaining < count) {
/* split the area */
@ -36,12 +69,27 @@ static int _alloc_area(struct logical_volume *lv, uint32_t index,
list_del(&pva->list);
}
for (i = 0; i < count; i++) {
lv->map[i + index].pv = pv;
lv->map[i + index].pe = start + i;
/* create the new segment */
seg = pool_zalloc(lv->vg->cmd->mem,
sizeof(*seg) * sizeof(seg->area[0]));
if (!seg) {
log_err("Couldn't allocate new stripe segment.");
return 0;
}
return count;
seg->lv = lv;
seg->le = *index;
seg->len = count;
seg->stripe_size = 0;
seg->stripes = 1;
seg->area[0].pv = pv;
seg->area[0].pe = start;
list_add(&lv->segments, &seg->list);
*index += count;
return 1;
}
static int _alloc_striped(struct logical_volume *lv,
@ -78,7 +126,11 @@ static int _alloc_contiguous(struct logical_volume *lv,
break;
}
allocated += _alloc_area(lv, allocated, pvm->pv, pva);
if (!_alloc_linear_area(lv, &allocated, pvm->pv, pva)) {
stack;
return 0;
}
if (allocated == lv->le_count)
break;
}
@ -109,9 +161,8 @@ static int _alloc_simple(struct logical_volume *lv,
list_iterate(tmp2, &pvm->areas) {
pva = list_item(tmp2, struct pv_area);
allocated += _alloc_area(lv, allocated, pvm->pv, pva);
if (allocated == lv->le_count)
if (!_alloc_linear_area(lv,&allocated, pvm->pv, pva) ||
(allocated == lv->le_count))
goto done;
}
}
@ -135,7 +186,7 @@ static int _allocate(struct volume_group *vg, struct logical_volume *lv,
{
int r = 0;
struct pool *scratch;
struct list *pvms;
struct list *pvms, *old_tail = lv->segments->p;
if (!(scratch = pool_create(1024))) {
stack;
@ -167,6 +218,16 @@ static int _allocate(struct volume_group *vg, struct logical_volume *lv,
if (r) {
vg->free_count -= lv->le_count - allocated;
/* Iterate through the new segments,
* updating pe counts in pv's. */
for (segh = lv->segments.p; segh != old_tail; segh = segh->p)
_get_extents(list_item(segh, struct stripe_segment));
} else {
/* Put the segment list back how
* we found it. */
old_tail->n = &lv->segments;
lv->segments.p = old_tail;
}
out:
@ -258,27 +319,20 @@ struct logical_volume *lv_create(const char *name,
lv->stripes = stripes;
lv->size = extents * vg->extent_size;
lv->le_count = extents;
if (!(lv->map = pool_zalloc(cmd->mem, sizeof(*lv->map) * extents))) {
stack;
goto bad;
}
list_init(&lv->segments);
if (!_allocate(vg, lv, acceptable_pvs, 0u)) {
stack;
goto bad;
}
for (i = 0; i < lv->le_count; i++)
lv->map[i].pv->pe_allocated++;
vg->lv_count++;
list_add(&vg->lvs, &ll->list);
lv->vg = vg;
return lv;
bad:
bad:
if (ll)
pool_free(cmd->mem, ll);
@ -287,16 +341,31 @@ struct logical_volume *lv_create(const char *name,
int lv_reduce(struct logical_volume *lv, uint32_t extents)
{
int i;
struct list *segh;
struct stripe_segment *seg;
uint32_t count = extents;
extents = lv->le_count - extents;
for (segh = lv->segments.p;
(segh != &lv->segments) && count;
segh = segh->p) {
seg = list_item(segh, struct stripe_segment);
for (i = extents; i < lv->le_count; i++) {
lv->map[i].pv->pe_allocated--;
if (seg->len <= count) {
/* remove this segment completely */
count -= seg->len;
_put_extents(seg);
list_del(segh);
} else {
/* reduce this segment */
_put_extents(seg);
seg->len -= count;
_get_extents(seg);
count = 0;
}
}
lv->le_count = extents;
lv->size = extents * lv->vg->extent_size;
lv->le_count -= extents;
lv->size = lv->le_count * lv->vg->extent_size;
return 1;
}
@ -304,59 +373,30 @@ int lv_reduce(struct logical_volume *lv, uint32_t extents)
int lv_extend(struct logical_volume *lv, uint32_t extents,
struct list *acceptable_pvs)
{
struct cmd_context *cmd = lv->vg->cmd;
struct pe_specifier *new_map;
struct logical_volume *new_lv;
int i;
uint32_t old_le_count = lv->le_count;
uint64_t old_size = lv->size;
if (!(new_map = pool_zalloc(cmd->mem, sizeof(*new_map) *
(extents + lv->le_count)))) {
stack;
lv->le_count += extents;
lv->size += extents * lv->vg->extent_size;
if (!_allocate(lv->vg, lv, acceptable_pvs, old_le_count)) {
lv->le_count = old_le_count;
lv->size = old_lv_size;
return 0;
}
memcpy(new_map, lv->map, sizeof(*new_map) * lv->le_count);
if (!(new_lv = pool_alloc(cmd->mem, sizeof(*new_lv)))) {
pool_free(cmd->mem, new_map);
stack;
return 0;
}
memcpy(new_lv, lv, sizeof(*lv));
new_lv->map = new_map;
new_lv->le_count += extents;
new_lv->size += extents * lv->vg->extent_size;
if (!_allocate(new_lv->vg, new_lv, acceptable_pvs, lv->le_count)) {
stack;
goto bad;
}
for (i = lv->le_count; i < new_lv->le_count; i++)
new_lv->map[i].pv->pe_allocated++;
memcpy(lv, new_lv, sizeof(*lv));
/*
* new_lv had to be allocated last so we
* could free it without touching the new
* map
*/
pool_free(cmd->mem, new_lv);
return 1;
bad:
pool_free(cmd->mem, new_map);
return 0;
}
int lv_remove(struct volume_group *vg, struct logical_volume *lv)
{
int i;
struct list *segh;
struct stripe_segment *seg;
for (i = 0; i < lv->le_count; i++)
lv->map[i].pv->pe_allocated--;
/* iterate through the lv's segments freeing off the pe's */
list_iterate (segh, &lv->segments)
_put_extents(list_item(segh, struct stripe_segment));
vg->lv_count--;
vg->free_count += lv->le_count;

View File

@ -1,7 +1,7 @@
/*
* Copyright (C) 2001 Sistina Software (UK) Limited.
*
* This file is released under the GPL.
* This file is released under the LGPL.
*
* This is the in core representation of a volume group and its
* associated physical and logical volumes.
@ -46,7 +46,6 @@
#define EXPORTED_TAG "PV_EXP" /* Identifier of exported PV */
#define IMPORTED_TAG "PV_IMP" /* Identifier of imported PV */
struct physical_volume {
struct id id;
struct device *dev;
@ -60,23 +59,7 @@ struct physical_volume {
uint64_t pe_size;
uint64_t pe_start;
uint32_t pe_count;
uint32_t pe_allocated;
};
struct pv_area {
struct physical_volume *pv;
uint32_t start; /* in extents */
uint32_t len; /* in extents */
};
struct stripe_segment {
struct list list;
uint32_t stripe_size;
uint32_t stripes;
/* There will be one pv_area for each stripe */
struct pv_area areas[0];
uint32_t pe_allocated; /* FIXME: change the name to alloc_count ? */
};
struct cmd_context;
@ -105,8 +88,23 @@ struct volume_group {
struct list lvs;
};
struct stripe_segment {
struct list list;
struct logical_volume *lv;
uint32_t le;
uint32_t len;
uint32_t stripe_size;
uint32_t stripes;
/* There will be one area for each stripe */
struct {
struct physical_volume *pv;
uint32_t pe;
} area[0];
};
struct logical_volume {
/* disk */
struct id id;
char *name;
@ -118,7 +116,6 @@ struct logical_volume {
uint64_t size;
uint32_t le_count;
/* the segment array */
struct list segments;
};
@ -287,7 +284,7 @@ struct volume_group *find_vg_with_lv(const char *lv_name);
/* FIXME Merge these functions with ones above */
struct physical_volume *_find_pv(struct volume_group *vg, struct device *dev);
struct physical_volume *find_pv(struct volume_group *vg, struct device *dev);
struct logical_volume *find_lv(struct volume_group *vg, const char *lv_name);
/*

View File

@ -7,6 +7,8 @@
#include "pv_map.h"
#include "log.h"
#include <assert.h>
static int _create_maps(struct pool *mem, struct list *pvs, struct list *maps)
{
struct list *tmp;
@ -35,42 +37,68 @@ static int _create_maps(struct pool *mem, struct list *pvs, struct list *maps)
return 1;
}
static int _set_allocated(struct hash_table *hash,
struct physical_volume *pv, int pe)
{
struct pv_map *pvm;
if (!(pvm = (struct pv_map *) hash_lookup(hash, dev_name(pv->dev)))) {
log_err("pv_map not present in hash table.");
return 0;
}
/* sanity check */
assert(!bit(pvm->allocated_extents, pe));
bit_set(pvm->allocated_extents, pe);
return 1;
}
static int _fill_bitsets(struct volume_group *vg, struct list *maps)
{
/*
* FIXME: should put pvm's in a table for
* O(1) access, and remove the nasty inner
* loop in this code.
*/
struct list *lvh, *pvmh;
struct logical_volume *lv;
struct pe_specifier *pes;
struct pv_map *pvm;
uint32_t le;
uint32_t i, r = 0;
struct hash_table *hash;
list_iterate(lvh, &vg->lvs) {
lv = &(list_item(lvh, struct lv_list)->lv);
if (!(hash = hash_table_create(128))) {
log_err("Couldn't create hash table for pv maps.");
return 0;
}
for (le = 0; le < lv->le_count; le++) {
pes = lv->map + le;
/* this is the nasty that will kill performance */
list_iterate(pvmh, maps) {
pvm = list_item(pvmh, struct pv_map);
if (pvm->pv == pes->pv)
break;
}
/* not all pvs are necc. in the list */
if (pvmh == maps)
continue;
bit_set(pvm->allocated_extents, pes->pe);
/* populate the hash table */
list_iterate (pvmh, maps) {
pvm = list_item(pvmh, struct pv_map);
if (!hash_insert(hash, dev_name(pvm->pv->dev), pvm)) {
stack;
goto out;
}
}
return 1;
/* iterate through all the lv's setting bit's for used pe's */
list_iterate (lvh, &vg->lvs) {
lv = &(list_item(lvh, struct lv_list)->lv);
list_iterate (segh, &lv->segments) {
seg = list_item(segh, struct stripe_segment);
for (i = 0; i < seg->len; i++) {
if (!_set_allocated(hash,
seg->area[i % seg->stripes].pv,
seg->area[i % seg->stripes].pe +
(i / stripes))) {
stack;
goto out;
}
}
}
}
r = 1;
out:
hash_table_destroy(hash);
return r;
}
static int _create_single_area(struct pool *mem, struct pv_map *pvm,