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 \
}
/*
- * 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;
-
- for (i = le; i < lv->le_count; i++) {
- pes = lv->map + i;
-
- if (!first)
- first = pes;
-
- /*
- * check that we're still contiguous.
- */
- else if ((pes->pv != first->pv) ||
- (pes->pe != first->pe + count))
- break;
-
- count++;
+ uint32_t s, stripes = seg->stripes;
+ int w, tw;
+
+ 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 (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;
}
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;
return count;
}
-
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)
{
pv->pe_start = pvd->pe_start;
pv->pe_count = pvd->pe_total;
pv->pe_allocated = pvd->pe_allocated;
+
+ init_list(&pv->allocated);
+
return 1;
}
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;
}
lvd->lv_allocation |= LV_CONTIGUOUS;
}
-int import_extents(struct pool *mem, struct volume_group *vg, struct list *pvds)
+int export_extents(struct disk_list *dl, int lv_num,
+ struct logical_volume *lv,
+ struct physical_volume *pv)
{
- 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;
+ struct list *segh;
+ struct pe_disk *ped;
+ struct stripe_segment *seg;
+ uint32_t pe;
+ struct span *pes;
- else if(lv_num > dl->pvd.lv_cur) {
- log_err("invalid lv in extent map\n");
- return 0;
+ list_iterate (segh, &lv->segments) {
+ seg = list_item(segh, struct stripe_segment);
- } else {
- lv_num--;
- lv = lvs[lv_num];
- le = e[i].le_num;
+ for (a = 0; a < seg->stripes; a++) {
+ if (seg->areas[a].pv != pv)
+ continue; /* not our pv */
- if (le >= lv->le_count) {
- log_err("logical extent number "
- "out of bounds");
- return 0;
- }
+ pes = seg->areas[a].pes;
- lv->map[le].pv = pv;
- lv->map[le].pe = i;
+ 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;
}
-int export_extents(struct disk_list *dl, int lv_num,
- struct logical_volume *lv,
- struct physical_volume *pv)
-{
- struct pe_disk *ped;
- int le;
-
- 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;
- }
- }
- return 1;
-}
-
int import_pvs(struct pool *mem, struct list *pvds,
struct list *results, int *count)
{
--- /dev/null
+/*
+ * 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;
+}
extent_size = 8192 # 4M
extent_count = 1024
- free_count = 430
max_lv = 99
max_pv = 255
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 {
#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
* 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 */
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,
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;
}
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;
}
}
{
int r = 0;
struct pool *scratch;
- struct list *pvms;
+ struct list *pvms, *old_tail = lv->segments->p;
if (!(scratch = pool_create(1024))) {
stack;
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:
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);
int lv_reduce(struct logical_volume *lv, uint32_t extents)
{
- int i;
-
- extents = lv->le_count - extents;
-
- for (i = extents; i < lv->le_count; i++) {
- lv->map[i].pv->pe_allocated--;
+ struct list *segh;
+ struct stripe_segment *seg;
+ uint32_t count = extents;
+
+ for (segh = lv->segments.p;
+ (segh != &lv->segments) && count;
+ segh = segh->p) {
+ seg = list_item(segh, struct stripe_segment);
+
+ 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;
}
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;
-
- if (!(new_map = pool_zalloc(cmd->mem, sizeof(*new_map) *
- (extents + lv->le_count)))) {
- stack;
- return 0;
- }
+ uint32_t old_le_count = lv->le_count;
+ uint64_t old_size = lv->size;
- memcpy(new_map, lv->map, sizeof(*new_map) * lv->le_count);
+ lv->le_count += extents;
+ lv->size += extents * lv->vg->extent_size;
- if (!(new_lv = pool_alloc(cmd->mem, sizeof(*new_lv)))) {
- pool_free(cmd->mem, new_map);
- stack;
+ 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_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;
/*
* 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.
#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;
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;
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;
uint64_t size;
uint32_t le_count;
- /* the segment array */
struct list segments;
};
/* 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);
/*
#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;
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;
+ /* 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;
+ }
+ }
- /* this is the nasty that will kill performance */
- list_iterate(pvmh, maps) {
- pvm = list_item(pvmh, struct pv_map);
+ /* 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);
- if (pvm->pv == pes->pv)
- break;
+ 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;
+ }
}
-
- /* not all pvs are necc. in the list */
- if (pvmh == maps)
- continue;
-
- bit_set(pvm->allocated_extents, pes->pe);
}
}
+ r = 1;
- return 1;
+ out:
+ hash_table_destroy(hash);
+ return r;
}
static int _create_single_area(struct pool *mem, struct pv_map *pvm,