]> sourceware.org Git - lvm2.git/commitdiff
more mirror library functions
authorAlasdair Kergon <agk@redhat.com>
Fri, 28 Oct 2005 12:48:50 +0000 (12:48 +0000)
committerAlasdair Kergon <agk@redhat.com>
Fri, 28 Oct 2005 12:48:50 +0000 (12:48 +0000)
lib/metadata/lv_alloc.h
lib/metadata/lv_manip.c
lib/metadata/merge.c
lib/metadata/metadata.c
lib/metadata/metadata.h
lib/metadata/mirror.c
tools/lvconvert.c

index aeed91a0585a660cd8140e1f9a505eee95242d76..e66d454093882bfe60aaa26e40624c2dc097bcb4 100644 (file)
@@ -76,6 +76,10 @@ int lv_add_mirror_segment(struct alloc_handle *ah,
                          uint32_t status,
                          uint32_t region_size,
                          struct logical_volume *log_lv);
+int lv_add_more_mirrored_areas(struct logical_volume *lv,
+                               struct logical_volume **sub_lvs,
+                               uint32_t new_area_count,
+                               uint32_t status);
 
 void alloc_destroy(struct alloc_handle *ah);
 
index b069a92bed5292c5a477681cd4c2728682a88723..56ac577037b52c6ed1dc83a699a8c5e66c864d8a 100644 (file)
@@ -102,7 +102,7 @@ struct lv_segment *alloc_lv_segment(struct dm_pool *mem,
 
        if (log_lv) {
                log_lv->status |= MIRROR_LOG;
-               find_seg_by_le(log_lv, 0)->mirror_seg = seg;
+               first_seg(log_lv)->mirror_seg = seg;
        }
 
        return seg;
@@ -232,9 +232,6 @@ void set_lv_segment_area_lv(struct lv_segment *seg, uint32_t area_num,
        lv->status |= flags;
 }
 
-static int _lv_segment_add_areas(struct logical_volume *lv,
-                                struct lv_segment *seg,
-                                uint32_t new_area_count) __attribute__ ((unused));
 /*
  * Prepare for adding parallel areas to an existing segment.
  */
@@ -1063,7 +1060,7 @@ int lv_add_mirror_segment(struct alloc_handle *ah,
 
        for (m = 0; m < mirrors; m++) {
                set_lv_segment_area_lv(seg, m, sub_lvs[m], 0, MIRROR_IMAGE);
-               find_seg_by_le(sub_lvs[m], 0)->mirror_seg = seg;
+               first_seg(sub_lvs[m])->mirror_seg = seg;
        }
 
        list_add(&lv->segments, &seg->list);
@@ -1079,6 +1076,42 @@ int lv_add_mirror_segment(struct alloc_handle *ah,
        return 1;
 }
 
+/*
+ * Add parallel areas to an existing mirror
+ */
+int lv_add_more_mirrored_areas(struct logical_volume *lv,
+                              struct logical_volume **sub_lvs,
+                              uint32_t num_extra_areas,
+                              uint32_t status)
+{
+       struct lv_segment *seg;
+       uint32_t old_area_count, new_area_count;
+       uint32_t m;
+
+       if (list_size(&lv->segments) != 1) {
+               log_error("Mirrored LV must only have one segment.");
+               return 0;
+       }
+
+       list_iterate_items(seg, &lv->segments)
+               break;
+
+       old_area_count = seg->area_count;
+       new_area_count = old_area_count + num_extra_areas;
+
+       if (!_lv_segment_add_areas(lv, seg, new_area_count)) {
+               log_error("Failed to allocate widened LV segment for %s.",
+                         lv->name);
+               return 0;
+       }
+
+       for (m = old_area_count; m < new_area_count; m++) {
+               set_lv_segment_area_lv(seg, m, sub_lvs[m - old_area_count], 0, status);
+               first_seg(sub_lvs[m - old_area_count])->mirror_seg = seg;
+       }
+
+       return 1;
+}
 
 /*
  * Entry point for single-step LV allocation + extension.
@@ -1094,7 +1127,7 @@ int lv_extend(struct logical_volume *lv,
        int r = 1;
        uint32_t m;
        struct alloc_handle *ah;
-       struct lv_segment *first_seg;
+       struct lv_segment *seg;
 
        if (segtype_is_virtual(segtype))
                return lv_add_virtual_segment(lv, status, extents, segtype);
@@ -1113,20 +1146,19 @@ int lv_extend(struct logical_volume *lv,
                        goto out;
                }
        } else {
-               list_iterate_items(first_seg, &lv->segments)
-                       break;
+               seg = first_seg(lv);
                for (m = 0; m < mirrors; m++) {
-                       if (!lv_add_segment(ah, m, 1, seg_lv(first_seg, m),
+                       if (!lv_add_segment(ah, m, 1, seg_lv(seg, m),
                                            get_segtype_from_string(lv->vg->cmd,
                                                                    "striped"),
                                            0, NULL, 0, 0, 0, NULL)) {
                                log_error("Aborting. Failed to extend %s.",
-                                         seg_lv(first_seg, m)->name);
+                                         seg_lv(seg, m)->name);
                                return 0;
                        }
                }
-               first_seg->area_len += extents;
-               first_seg->len += extents;
+               seg->area_len += extents;
+               seg->len += extents;
                lv->le_count += extents;
                lv->size += (uint64_t) extents *lv->vg->extent_size;
        }
index f861c52889e930a4be81d541b7cda2c4a57806ac..1cdc94065a10ac32feb2aecf91dbb16535481689 100644 (file)
@@ -100,7 +100,7 @@ int check_lv_segments(struct logical_volume *lv, int complete_vg)
                                r = 0;
                        }
 
-                       if (!(seg2 = find_seg_by_le(seg->log_lv, 0)) ||
+                       if (!(seg2 = first_seg(seg->log_lv)) ||
                            seg2->mirror_seg != seg) {
                                log_error("LV %s: segment %u log LV does not "
                                          "point back to mirror segment",
index c44d56ff72667961ef630e2f6e3d96e4f90bb627..0be839391439f37b5be22bcc0d337a2cf5b28814 100644 (file)
@@ -675,6 +675,16 @@ struct lv_segment *find_seg_by_le(struct logical_volume *lv, uint32_t le)
        return NULL;
 }
 
+struct lv_segment *first_seg(struct logical_volume *lv)
+{
+       struct lv_segment *seg = NULL;
+
+       list_iterate_items(seg, &lv->segments)
+               break;
+
+       return seg;
+}
+
 /* Find segment at a given physical extent in a PV */
 struct pv_segment *find_peg_by_pe(struct physical_volume *pv, uint32_t pe)
 {
index 233729bce7603637f50e17656ddc1276b3c53cd6..1d1625318eab82e055f5c1520a53207297c9da2a 100644 (file)
@@ -501,6 +501,7 @@ struct physical_volume *find_pv_by_name(struct cmd_context *cmd,
 
 /* Find LV segment containing given LE */
 struct lv_segment *find_seg_by_le(struct logical_volume *lv, uint32_t le);
+struct lv_segment *first_seg(struct logical_volume *lv);
 
 /* Find PV segment containing given LE */
 struct pv_segment *find_peg_by_pe(struct physical_volume *pv, uint32_t pe);
index f48b808f4853a715ccbc4bd64befc1d83db2fc19..9e03a6bb2630571bd389226d0ef8b030e42bdd9c 100644 (file)
@@ -47,6 +47,25 @@ uint32_t adjusted_mirror_region_size(uint32_t extent_size, uint32_t extents,
        return region_size;
 }
 
+static void _move_lv_segments(struct logical_volume *lv_to, struct logical_volume *lv_from)
+{
+       struct lv_segment *seg;
+
+       lv_to->segments = lv_from->segments;
+       lv_to->segments.n->p = &lv_to->segments;
+       lv_to->segments.p->n = &lv_to->segments;
+
+       list_iterate_items(seg, &lv_to->segments)
+               seg->lv = lv_to;
+
+/* FIXME set or reset seg->mirror_seg (according to status)? */
+
+       list_init(&lv_from->segments);
+
+       lv_from->le_count = 0;
+       lv_from->size = 0;
+}
+
 /*
  * Reduce mirrored_seg to num_mirrors images.
  */
@@ -68,31 +87,25 @@ int remove_mirror_images(struct lv_segment *mirrored_seg, uint32_t num_mirrors)
 
 int remove_all_mirror_images(struct logical_volume *lv)
 {
-       struct lv_segment *first_seg, *seg;
+       struct lv_segment *seg;
        struct logical_volume *lv1;
 
-       list_iterate_items(first_seg, &lv->segments)
-               break;
+       seg = first_seg(lv);
 
-       if (!remove_mirror_images(first_seg, 1)) {
+       if (!remove_mirror_images(seg, 1)) {
                stack;
                return 0;
        }
 
-       if (!lv_remove(first_seg->log_lv)) {
+       if (seg->log_lv && !lv_remove(seg->log_lv)) {
                stack;
                return 0;
        }
 
-       lv1 = seg_lv(first_seg, 0);
+       lv1 = seg_lv(seg, 0);
 
-       lv->segments = lv1->segments;
-       lv->segments.n->p = &lv->segments;
-       lv->segments.p->n = &lv->segments;
+       _move_lv_segments(lv, lv1);
 
-       list_init(&lv1->segments);
-       lv1->le_count = 0;
-       lv1->size = 0;
        if (!lv_remove(lv1)) {
                stack;
                return 0;
@@ -100,9 +113,6 @@ int remove_all_mirror_images(struct logical_volume *lv)
 
        lv->status &= ~MIRRORED;
 
-       list_iterate_items(seg, &lv->segments)
-               seg->lv = lv;
-
        return 1;
 }
 
@@ -118,26 +128,17 @@ int add_mirror_images(struct alloc_handle *ah,
 }
 */
 
-int create_mirror_layers(struct alloc_handle *ah,
-                        uint32_t first_area,
-                        uint32_t num_mirrors,
-                        struct logical_volume *lv,
-                        struct segment_type *segtype,
-                        uint32_t status,
-                        uint32_t region_size,
-                        struct logical_volume *log_lv)
+static int _create_layers_for_mirror(struct alloc_handle *ah,
+                                    uint32_t first_area,
+                                    uint32_t num_mirrors,
+                                    struct logical_volume *lv,
+                                    struct segment_type *segtype,
+                                    struct logical_volume **img_lvs)
 {
        uint32_t m;
-       struct logical_volume **img_lvs;
        char *img_name;
        size_t len;
        
-       if (!(img_lvs = alloca(sizeof(*img_lvs) * num_mirrors))) {
-               log_error("img_lvs allocation failed. "
-                         "Remove new LV and retry.");
-               return 0;
-       }
-
        len = strlen(lv->name) + 32;
        if (!(img_name = alloca(len))) {
                log_error("img_name allocation failed. "
@@ -171,6 +172,43 @@ int create_mirror_layers(struct alloc_handle *ah,
                }
        }
 
+       return 1;
+}
+
+int create_mirror_layers(struct alloc_handle *ah,
+                        uint32_t first_area,
+                        uint32_t num_mirrors,
+                        struct logical_volume *lv,
+                        struct segment_type *segtype,
+                        uint32_t status,
+                        uint32_t region_size,
+                        struct logical_volume *log_lv)
+{
+       struct logical_volume **img_lvs;
+       
+       if (!(img_lvs = alloca(sizeof(*img_lvs) * num_mirrors))) {
+               log_error("img_lvs allocation failed. "
+                         "Remove new LV and retry.");
+               return 0;
+       }
+
+       if (!_create_layers_for_mirror(ah, first_area, num_mirrors, lv,
+                                      segtype, img_lvs)) {
+               stack;
+               return 0;
+       }
+
+       /* Already got the parent mirror segment? */
+       if (lv->status & MIRRORED)
+               return lv_add_more_mirrored_areas(lv, img_lvs, num_mirrors,
+                                                 MIRROR_IMAGE);
+
+       /* Already got a non-mirrored area to be converted? */
+       if (!first_area) {
+               _move_lv_segments(img_lvs[0], lv);
+               lv->status |= MIRRORED;
+       }
+
        if (!lv_add_mirror_segment(ah, lv, img_lvs, num_mirrors, segtype,
                                   0, region_size, log_lv)) {
                log_error("Aborting. Failed to add mirror segment. "
@@ -568,12 +606,14 @@ int fixup_imported_mirrors(struct volume_group *vg)
                                continue;
 
                        if (seg->log_lv)
-                               find_seg_by_le(seg->log_lv, 0)->mirror_seg = seg;
+                               first_seg(seg->log_lv)->mirror_seg = seg;
                        for (s = 0; s < seg->area_count; s++)
                                if (seg_type(seg, s) == AREA_LV)
-                                       find_seg_by_le(seg_lv(seg, s), 0)->
-                                           mirror_seg = seg;
+                                       first_seg(seg_lv(seg, s))->mirror_seg
+                                           = seg;
                }
        }
+
+       return 1;
 }
 
index 70d3afd5438615a2b41ef5e1568b3426aa1245e8..5f11e185b48ebe8b1002736eb944ae8bcf4858e2 100644 (file)
@@ -59,7 +59,7 @@ static int _read_params(struct lvconvert_params *lp, struct cmd_context *cmd,
 static int lvconvert_mirrors(struct cmd_context * cmd, struct logical_volume * lv,
                             struct lvconvert_params *lp)
 {
-       struct lv_segment *first_seg;
+       struct lv_segment *seg;
        uint32_t existing_mirrors;
        // struct alloc_handle *ah = NULL;
        // struct logical_volume *log_lv;
@@ -82,9 +82,8 @@ static int lvconvert_mirrors(struct cmd_context * cmd, struct logical_volume * l
                                          "mirror segments.", lv->name);
                                return 0;
                        }
-                       list_iterate_items(first_seg, &lv->segments)
-                               break;
-                       existing_mirrors = first_seg->area_count;
+                       seg = first_seg(lv);
+                       existing_mirrors = seg->area_count;
                        if (lp->mirrors == existing_mirrors) {
                                log_error("Logical volume %s already has %"
                                          PRIu32 " mirror(s).", lv->name,
@@ -101,7 +100,7 @@ static int lvconvert_mirrors(struct cmd_context * cmd, struct logical_volume * l
                                          "supported yet.");
                                return 0;
                        } else {
-                               if (!remove_mirror_images(first_seg, lp->mirrors)) {
+                               if (!remove_mirror_images(seg, lp->mirrors)) {
                                        stack;
                                        return 0;
                                }
This page took 0.04968 seconds and 5 git commands to generate.