]> sourceware.org Git - lvm2.git/commitdiff
o Sync up todays work on converting to the segmented representation of
authorJoe Thornber <thornber@redhat.com>
Tue, 27 Nov 2001 16:37:33 +0000 (16:37 +0000)
committerJoe Thornber <thornber@redhat.com>
Tue, 27 Nov 2001 16:37:33 +0000 (16:37 +0000)
   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.

lib/Makefile.in
lib/activate/activate.c
lib/format1/import-export.c
lib/format1/import-extents.c [new file with mode: 0644]
lib/format_text/sample.vg
lib/metadata/lv_manip.c
lib/metadata/metadata.h
lib/metadata/pv_map.c

index 0674dda3f969a559686664b5db8d9c5e5ce3563b..3b6b9b806f4181b8c0f00d195600e315f2463cc0 100644 (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 \
index 7fb81ad270e5d3680383125ec214891d134ab7bf..e323744d9445fd1221f02c55d6ce11a16d728fb5 100644 (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;
-
-       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;
        }
@@ -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;
 }
-
index 0e7bf57ec234090074140c81748f06f95bf3e7ec..04b12b0484c663ee77f48f6f04bb718c44ae3068 100644 (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,50 +304,30 @@ 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)
+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);
                        }
                }
        }
@@ -374,23 +335,6 @@ int import_extents(struct pool *mem, struct volume_group *vg, struct list *pvds)
        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)
 {
diff --git a/lib/format1/import-extents.c b/lib/format1/import-extents.c
new file mode 100644 (file)
index 0000000..aa03f5e
--- /dev/null
@@ -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;
+}
index d44b453c3c819d64bbeeb9d84c1b506da25408ef..bba353cb6fd26c7ad0414bd9f330c22d9aaf1607 100644 (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 {
index e352b0cd3a72c03c7d64d82d5559c5eac107619c..f4f94192144961412b3259a0acbda9cedc018559 100644 (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
  * 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;
-
-       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;
 }
@@ -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;
-
-       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;
index 8d70c6c68c849896a6f96b5b368050e3996b84cc..bf968234069ebfc0cd5029c535294024dd913239 100644 (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);
 
 /*
index 9666e1b87b946a3db8bec85f02f8fc8eb218df37..64cd4ba3de574a52c882db09eda6a9e83826d47a 100644 (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;
+       /* 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,
This page took 0.061593 seconds and 5 git commands to generate.