]> sourceware.org Git - lvm2.git/commitdiff
Support for PE ranges in pvmove source PV.
authorAlasdair Kergon <agk@redhat.com>
Tue, 17 Aug 2004 22:09:02 +0000 (22:09 +0000)
committerAlasdair Kergon <agk@redhat.com>
Tue, 17 Aug 2004 22:09:02 +0000 (22:09 +0000)
WHATS_NEW
lib/metadata/merge.c
lib/metadata/metadata.h
lib/metadata/mirror.c
lib/mirror/mirrored.c
tools/pvmove.c

index 77d5b2055607f8b4890b78e4b0ccb6c0d3531577..a9677dfbbd6155011eb32e6bc0d3526e479af330 100644 (file)
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,10 @@
 Version 2.00.21 - 
 =============================
+  Fix extents_moved metadata size comment.
+  Remove duplicate line in pvremove help text.
+  Support variable mirror region size.
+  Support PE ranges in pvmove source PV.
+  Fixes to as-yet-unused LV segment splitting code.
   Change alloc_areas to pe_ranges and allow suppression of availability checks.
   Add dev_size column to pvs.
   Add report columns for in-kernel device number.
index decd7051eff4da17585284352a007581965ea028..61b05eb60e10999e7b6509f6d613cd3b401e0c9c 100644 (file)
@@ -39,6 +39,9 @@ int lv_merge_segments(struct logical_volume *lv)
        struct list *segh, *t;
        struct lv_segment *current, *prev = NULL;
 
+       if (lv->status & LOCKED || lv->status & PVMOVE)
+               return 1;
+
        list_iterate_safe(segh, t, &lv->segments) {
                current = list_item(segh, struct lv_segment);
 
@@ -77,6 +80,7 @@ int lv_check_segments(struct logical_volume *lv)
 
 /*
  * Split the supplied segment at the supplied logical extent
+ * NB Use LE numbering that works across stripes PV1: 0,2,4 PV2: 1,3,5 etc.
  */
 static int _lv_split_segment(struct logical_volume *lv, struct lv_segment *seg,
                             uint32_t le)
@@ -85,6 +89,7 @@ static int _lv_split_segment(struct logical_volume *lv, struct lv_segment *seg,
        struct lv_segment *split_seg;
        uint32_t s;
        uint32_t offset = le - seg->le;
+       uint32_t area_offset;
 
        if (!(seg->segtype->flags & SEG_CAN_SPLIT)) {
                log_error("Unable to split the %s segment at LE %" PRIu32
@@ -107,8 +112,9 @@ static int _lv_split_segment(struct logical_volume *lv, struct lv_segment *seg,
        }
 
        /* In case of a striped segment, the offset has to be / stripes */
+       area_offset = offset;
        if (seg->segtype->flags & SEG_AREAS_STRIPED)
-               offset /= seg->area_count;
+               area_offset /= seg->area_count;
 
        /* Adjust the PV mapping */
        for (s = 0; s < seg->area_count; s++) {
@@ -116,12 +122,19 @@ static int _lv_split_segment(struct logical_volume *lv, struct lv_segment *seg,
                switch (seg->area[s].type) {
                case AREA_LV:
                        split_seg->area[s].u.lv.le =
-                           seg->area[s].u.lv.le + offset;
+                           seg->area[s].u.lv.le + area_offset;
+                       log_debug("Split %s:%u[%u] at %u: %s LE %u", lv->name,
+                                 seg->le, s, le, seg->area[s].u.lv.lv->name,
+                                 split_seg->area[s].u.lv.le);
                        break;
 
                case AREA_PV:
                        split_seg->area[s].u.pv.pe =
-                           seg->area[s].u.pv.pe + offset;
+                           seg->area[s].u.pv.pe + area_offset;
+                       log_debug("Split %s:%u[%u] at %u: %s PE %u", lv->name,
+                                 seg->le, s, le,
+                                 dev_name(seg->area[s].u.pv.pv->dev),
+                                 split_seg->area[s].u.pv.pe);
                        break;
 
                default:
@@ -131,8 +144,13 @@ static int _lv_split_segment(struct logical_volume *lv, struct lv_segment *seg,
                }
        }
 
-       split_seg->area_len = seg->area_len - offset;
-       seg->area_len = offset;
+       split_seg->area_len -= area_offset;
+       seg->area_len = area_offset;
+
+       split_seg->len -= offset;
+       seg->len = offset;
+
+       split_seg->le = seg->le + seg->len;
 
        /* Add split off segment to the list _after_ the original one */
        list_add_h(&seg->list, &split_seg->list);
index 1340f7b04c0dfff07bb9af930a65c063513eb93c..2022130b83a1c33f986f6e4b411fc86338923b45 100644 (file)
@@ -501,7 +501,7 @@ int vg_remove_snapshot(struct volume_group *vg, struct logical_volume *cow);
  */
 int insert_pvmove_mirrors(struct cmd_context *cmd,
                          struct logical_volume *lv_mirr,
-                         struct physical_volume *pv,
+                         struct list *source_pvl,
                          struct logical_volume *lv,
                          struct list *allocatable_pvs,
                          struct list *lvs_changed);
index 8d926769cfcc2b4368c70c3b44e96f4a086b22d4..7664c7eb33f55f09129b01c2869c88a93330296a 100644 (file)
@@ -26,7 +26,7 @@
  */
 int insert_pvmove_mirrors(struct cmd_context *cmd,
                          struct logical_volume *lv_mirr,
-                         struct physical_volume *pv,
+                         struct list *source_pvl,
                          struct logical_volume *lv,
                          struct list *allocatable_pvs,
                          struct list *lvs_changed)
@@ -34,9 +34,15 @@ int insert_pvmove_mirrors(struct cmd_context *cmd,
        struct list *segh;
        struct lv_segment *seg;
        struct lv_list *lvl;
+       struct pv_list *pvl;
        int lv_used = 0;
        uint32_t s, start_le, extent_count = 0u;
        struct segment_type *segtype;
+       struct pe_range *per;
+       uint32_t pe_start, pe_end, per_end, stripe_multiplier;
+
+       /* Only 1 PV may feature in source_pvl */
+       pvl = list_item(source_pvl->n, struct pv_list);
 
        if (!(segtype = get_segtype_from_string(lv->vg->cmd, "mirror"))) {
                stack;
@@ -50,43 +56,113 @@ int insert_pvmove_mirrors(struct cmd_context *cmd,
                 return 0;
         }
 
-       /* Work through all segments on the supplied PV */
+       /* Split LV segments to match PE ranges */
        list_iterate(segh, &lv->segments) {
                seg = list_item(segh, struct lv_segment);
                for (s = 0; s < seg->area_count; s++) {
                        if (seg->area[s].type != AREA_PV ||
-                           seg->area[s].u.pv.pv->dev != pv->dev)
+                           seg->area[s].u.pv.pv->dev != pvl->pv->dev)
                                continue;
 
-                       /* First time, add LV to list of LVs affected */
-                       if (!lv_used) {
-                               if (!(lvl = pool_alloc(cmd->mem, sizeof(*lvl)))) {
-                                       log_error("lv_list alloc failed");
+                       /* Do these PEs need moving? */
+                       list_iterate_items(per, pvl->pe_ranges) {
+                               pe_start = seg->area[s].u.pv.pe;
+                               pe_end = pe_start + seg->area_len - 1;
+                               per_end = per->start + per->count - 1;
+
+                               /* No overlap? */
+                               if ((pe_end < per->start) ||
+                                   (pe_start > per_end))
+                                       continue;
+
+                               if (seg->segtype->flags & SEG_AREAS_STRIPED)
+                                       stripe_multiplier = seg->area_count;
+                               else
+                                       stripe_multiplier = 1;
+
+                               if ((per->start != pe_start &&
+                                    per->start > pe_start) &&
+                                   !lv_split_segment(lv, seg->le +
+                                                     (per->start - pe_start) *
+                                                     stripe_multiplier)) {
+                                       stack;
                                        return 0;
                                }
-                               lvl->lv = lv;
-                               list_add(lvs_changed, &lvl->list);
-                               lv_used = 1;
-                       }
 
-                       start_le = lv_mirr->le_count;
-                       if (!lv_extend(lv->vg->fid, lv_mirr, segtype, 1,
-                                      seg->area_len, 0u, seg->area_len,
-                                      seg->area[s].u.pv.pv,
-                                      seg->area[s].u.pv.pe,
-                                      PVMOVE, allocatable_pvs,
-                                      lv->alloc)) {
-                               log_error("Allocation for temporary "
-                                         "pvmove LV failed");
-                               return 0;
+                               if ((per_end != pe_end &&
+                                    per_end < pe_end) &&
+                                   !lv_split_segment(lv, seg->le +
+                                                     (per_end - pe_start + 1) *
+                                                     stripe_multiplier)) {
+                                       stack;
+                                       return 0;
+                               }
                        }
-                       seg->area[s].type = AREA_LV;
-                       seg->area[s].u.lv.lv = lv_mirr;
-                       seg->area[s].u.lv.le = start_le;
+               }
+       }
 
-                       extent_count += seg->area_len;
+       /* Work through all segments on the supplied PV */
+       list_iterate(segh, &lv->segments) {
+               seg = list_item(segh, struct lv_segment);
+               for (s = 0; s < seg->area_count; s++) {
+                       if (seg->area[s].type != AREA_PV ||
+                           seg->area[s].u.pv.pv->dev != pvl->pv->dev)
+                               continue;
+
+                       pe_start = seg->area[s].u.pv.pe;
+
+                       /* Do these PEs need moving? */
+                       list_iterate_items(per, pvl->pe_ranges) {
+                               per_end = per->start + per->count - 1;
+
+                               if ((pe_start < per->start) ||
+                                   (pe_start > per_end))
+                                       continue;
 
-                       lv->status |= LOCKED;
+                               log_debug("Matched PE range %u-%u against "
+                                         "%s %u len %u", per->start, per_end,
+                                         dev_name(seg->area[s].u.pv.pv->dev),
+                                         seg->area[s].u.pv.pe, seg->area_len);
+
+                               /* First time, add LV to list of LVs affected */
+                               if (!lv_used) {
+                                       if (!(lvl = pool_alloc(cmd->mem, sizeof(*lvl)))) {
+                                               log_error("lv_list alloc failed");
+                                               return 0;
+                                       }
+                                       lvl->lv = lv;
+                                       list_add(lvs_changed, &lvl->list);
+                                       lv_used = 1;
+                               }
+       
+                               log_very_verbose("Moving %s:%u-%u of %s/%s",
+                                                dev_name(pvl->pv->dev),
+                                                seg->area[s].u.pv.pe,
+                                                seg->area[s].u.pv.pe +
+                                                    seg->area_len - 1,
+                                                lv->vg->name, lv->name);
+
+                               start_le = lv_mirr->le_count;
+                               if (!lv_extend(lv->vg->fid, lv_mirr, segtype, 1,
+                                       seg->area_len, 0u, seg->area_len,
+                                       seg->area[s].u.pv.pv,
+                                       seg->area[s].u.pv.pe,
+                                       PVMOVE, allocatable_pvs,
+                                       lv->alloc)) {
+                                       log_error("Allocation for temporary "
+                                               "pvmove LV failed");
+                                       return 0;
+                               }
+                               seg->area[s].type = AREA_LV;
+                               seg->area[s].u.lv.lv = lv_mirr;
+                               seg->area[s].u.lv.le = start_le;
+       
+                               extent_count += seg->area_len;
+       
+                               lv->status |= LOCKED;
+
+                               break;
+                       }
                }
        }
 
@@ -167,8 +243,12 @@ int remove_pvmove_mirrors(struct volume_group *vg,
                                lv1->status &= ~LOCKED;
                        }
                }
+               if (!lv_merge_segments(lv1))
+                       stack;
+
        }
 
+
        return 1;
 }
 
index 7d94201536a9ec41f47e26dc34735c2991175f47..a7137b49ca6740e5b6b9ee4cbf8317908614d52e 100644 (file)
@@ -95,7 +95,7 @@ static int _text_export(const struct lv_segment *seg, struct formatter *f)
 {
        outf(f, "mirror_count = %u", seg->area_count);
        if (seg->status & PVMOVE)
-               out_size(f, (uint64_t) seg->extents_copied,
+               out_size(f, (uint64_t) seg->extents_copied * seg->lv->vg->extent_size,
                         "extents_moved = %u", seg->extents_copied);
 
        return out_areas(f, seg, "mirror");
@@ -130,6 +130,7 @@ static int _compose_target_line(struct dev_manager *dm, struct pool *mem,
        int mirror_status = MIRR_RUNNING;
        int areas = seg->area_count;
        int start_area = 0u;
+       uint32_t region_size, region_max;
 
        if (!*target_state)
                *target_state = _init_target(mem, cft);
@@ -143,7 +144,7 @@ static int _compose_target_line(struct dev_manager *dm, struct pool *mem,
                if (seg->extents_copied == seg->area_len) {
                        mirror_status = MIRR_COMPLETED;
                        start_area = 1;
-               } else if (*pvmove_mirror_count++) {
+               } else if ((*pvmove_mirror_count)++) {
                        mirror_status = MIRR_DISABLED;
                        areas = 1;
                }
@@ -153,8 +154,20 @@ static int _compose_target_line(struct dev_manager *dm, struct pool *mem,
                *target = "linear";
        } else {
                *target = "mirror";
+
+               /* Find largest power of 2 region size unit we can use */
+               region_max = (1 << (ffs(seg->area_len) - 1)) *
+                             seg->lv->vg->extent_size;
+
+               region_size = mirr_state->region_size;
+               if (region_max < region_size) {
+                       region_size = region_max;
+                       log_verbose("Using reduced mirror region size of %u sectors",
+                                   region_size);
+               }
+
                if ((*pos = lvm_snprintf(params, paramsize, "core 1 %u %u ",
-                                        mirr_state->region_size, areas)) < 0) {
+                                        region_size, areas)) < 0) {
                        stack;
                        return -1;
                }
@@ -162,7 +175,6 @@ static int _compose_target_line(struct dev_manager *dm, struct pool *mem,
 
        return compose_areas_line(dm, seg, params, paramsize, pos, start_area,
                                  areas);
-
 }
 
 static int _target_percent(void **target_state, struct pool *mem,
@@ -188,8 +200,7 @@ static int _target_percent(void **target_state, struct pool *mem,
        *total_denominator += denominator;
 
        if (seg)
-               seg->extents_copied = mirr_state->region_size *
-                   numerator / seg->lv->vg->extent_size;
+               seg->extents_copied = seg->area_len * numerator / denominator;
 
        return 1;
 }
index f0cb73c2aa6c3488a0912866617b28efe801b931..97416252a21d3532933aff2ce87e47f76cdf8625 100644 (file)
@@ -123,7 +123,7 @@ static struct list *_get_allocatable_pvs(struct cmd_context *cmd, int argc,
 /* Create new LV with mirror segments for the required copies */
 static struct logical_volume *_set_up_pvmove_lv(struct cmd_context *cmd,
                                                struct volume_group *vg,
-                                               struct physical_volume *pv,
+                                               struct list *source_pvl,
                                                const char *lv_name,
                                                struct list *allocatable_pvs,
                                                struct list **lvs_changed)
@@ -165,7 +165,7 @@ static struct logical_volume *_set_up_pvmove_lv(struct cmd_context *cmd,
                        log_print("Skipping locked LV %s", lv->name);
                        continue;
                }
-               if (!insert_pvmove_mirrors(cmd, lv_mirr, pv, lv,
+               if (!insert_pvmove_mirrors(cmd, lv_mirr, source_pvl, lv,
                                           allocatable_pvs, *lvs_changed)) {
                        stack;
                        return NULL;
@@ -248,13 +248,19 @@ static int _set_up_pvmove(struct cmd_context *cmd, const char *pv_name,
                          int argc, char **argv)
 {
        const char *lv_name = NULL;
+       char *pv_name_arg;
        struct volume_group *vg;
+       struct list *source_pvl;
        struct list *allocatable_pvs;
        struct list *lvs_changed;
        struct physical_volume *pv;
        struct logical_volume *lv_mirr;
        int first_time = 1;
 
+       pv_name_arg = argv[0];
+       argc--;
+       argv++;
+
        /* Find PV (in VG) */
        if (!(pv = find_pv_by_name(cmd, pv_name))) {
                stack;
@@ -299,6 +305,13 @@ static int _set_up_pvmove(struct cmd_context *cmd, const char *pv_name,
 
                first_time = 0;
        } else {
+               /* Determine PE ranges to be moved */
+               if (!(source_pvl = create_pv_list(cmd->mem, vg, 1,
+                                                 &pv_name_arg, 0))) {
+                       stack;
+                       unlock_vg(cmd, pv->vg_name);
+                       return ECMD_FAILED;
+               }
 
                /* Get PVs we can use for allocation */
                if (!(allocatable_pvs = _get_allocatable_pvs(cmd, argc, argv,
@@ -314,7 +327,7 @@ static int _set_up_pvmove(struct cmd_context *cmd, const char *pv_name,
                        return ECMD_FAILED;
                }
 
-               if (!(lv_mirr = _set_up_pvmove_lv(cmd, vg, pv, lv_name,
+               if (!(lv_mirr = _set_up_pvmove_lv(cmd, vg, source_pvl, lv_name,
                                                  allocatable_pvs,
                                                  &lvs_changed))) {
                        stack;
@@ -459,12 +472,21 @@ int pvmove_poll(struct cmd_context *cmd, const char *pv_name,
 int pvmove(struct cmd_context *cmd, int argc, char **argv)
 {
        char *pv_name = NULL;
+       char *colon;
        int ret;
 
        if (argc) {
                pv_name = argv[0];
-               argc--;
-               argv++;
+
+               /* Drop any PE lists from PV name */
+               if ((colon = strchr(pv_name, ':'))) {
+                       if (!(pv_name = pool_strndup(cmd->mem, pv_name,
+                                                    (unsigned) (colon -
+                                                                pv_name)))) {
+                               log_error("Failed to clone PV name");
+                               return 0;
+                       }
+               }
 
                if (!arg_count(cmd, abort_ARG) &&
                    (ret = _set_up_pvmove(cmd, pv_name, argc, argv)) !=
@@ -472,6 +494,7 @@ int pvmove(struct cmd_context *cmd, int argc, char **argv)
                        stack;
                        return ret;
                }
+
        }
 
        return pvmove_poll(cmd, pv_name,
This page took 0.053853 seconds and 5 git commands to generate.