]> sourceware.org Git - lvm2.git/commitdiff
Change pvresize code to work with new metadata handling interface and allow
authorPeter Rajnoha <prajnoha@redhat.com>
Mon, 21 Feb 2011 12:27:26 +0000 (12:27 +0000)
committerPeter Rajnoha <prajnoha@redhat.com>
Mon, 21 Feb 2011 12:27:26 +0000 (12:27 +0000)
resizing a PV with two metadata areas.

lib/format_text/format-text.c
lib/metadata/metadata-exported.h
lib/metadata/metadata.h
lib/metadata/pv_manip.c
tools/pvresize.c

index e72a9363117266847d49f9cc931dc4e4e55b26fb..4d387e31f69019a8b14260da874c929e04eae738 100644 (file)
@@ -2093,6 +2093,55 @@ static int _text_pv_remove_metadata_area(const struct format_type *fmt,
        return remove_metadata_area_from_pv(pv, mda_index);
 }
 
+static int _text_pv_resize(const struct format_type *fmt,
+                          struct physical_volume *pv,
+                          struct volume_group *vg,
+                          uint64_t size)
+{
+       struct format_instance *fid = pv->fid;
+       const char *pvid = (const char *) &pv->id;
+       struct metadata_area *mda;
+       struct mda_context *mdac;
+       uint64_t size_reduction;
+       uint64_t mda_size;
+       unsigned mda_ignored;
+
+       /*
+        * First, set the new size and update the cache and reset pe_count.
+        * (pe_count must be reset otherwise it would be considered as
+        * a limiting factor while moving the mda!)
+        */
+       pv->size = size;
+       pv->pe_count = 0;
+
+       /* If there's an mda at the end, move it to a new position. */
+       if ((mda = fid_get_mda_indexed(fid, pvid, ID_LEN, 1)) &&
+           (mdac = mda->metadata_locn)) {
+               /* FIXME: Maybe MDA0 size would be better? */
+               mda_size = mdac->area.size >> SECTOR_SHIFT;
+               mda_ignored = mda_is_ignored(mda);
+
+               if (!_text_pv_remove_metadata_area(fmt, pv, 1) ||
+                   !_text_pv_add_metadata_area(fmt, pv, 1, 1, mda_size,
+                                               mda_ignored)) {
+                       log_error("Failed to move metadata area with index 1 "
+                                 "while resizing PV %s.", pv_dev_name(pv));
+                       return 0;
+               }
+       }
+
+       /* If there's a VG, reduce size by counting in pe_start and metadata areas. */
+       if (vg) {
+               size_reduction = pv_pe_start(pv);
+               if ((mda = fid_get_mda_indexed(fid, pvid, ID_LEN, 1)) &&
+                   (mdac = mda->metadata_locn))
+                       size_reduction += mdac->area.size >> SECTOR_SHIFT;
+               pv->size -= size_reduction;
+       }
+
+       return 1;
+}
+
 /* NULL vgname means use only the supplied context e.g. an archive file */
 static struct format_instance *_text_create_text_instance(const struct format_type *fmt,
                                                           const struct format_instance_ctx *fic)
@@ -2170,6 +2219,7 @@ static struct format_handler _text_handler = {
        .pv_setup = _text_pv_setup,
        .pv_add_metadata_area = _text_pv_add_metadata_area,
        .pv_remove_metadata_area = _text_pv_remove_metadata_area,
+       .pv_resize = _text_pv_resize,
        .pv_write = _text_pv_write,
        .vg_setup = _text_vg_setup,
        .lv_setup = _text_lv_setup,
index 6cc02bd5985c54fc70e7063eeb79bb582985d5cd..464c5c1d220446b1d1f64fd815611ab3da72aee2 100644 (file)
@@ -428,7 +428,7 @@ struct physical_volume *pv_create(const struct cmd_context *cmd,
                                  uint64_t pvmetadatasize,
                                  unsigned metadataignore);
 int pv_resize(struct physical_volume *pv, struct volume_group *vg,
-             uint32_t new_pe_count);
+             uint64_t size);
 int pv_analyze(struct cmd_context *cmd, const char *pv_name,
               uint64_t label_sector);
 
index 6acb30b8aaecc57eabf10beb446faba613bd039f..956cc1a1515bfc94c80d1515c3e25bfa855f8f09 100644 (file)
@@ -292,6 +292,14 @@ struct format_handler {
                                        struct physical_volume *pv,
                                        unsigned metadata_index);
 
+       /*
+        * Recalculate the PV size taking into account any existing metadata areas.
+        */
+       int (*pv_resize) (const struct format_type *fmt,
+                         struct physical_volume *pv,
+                         struct volume_group *vg,
+                         uint64_t size);
+
        /*
         * Write a PV structure to disk. Fails if the PV is in a VG ie
         * pv->vg_name must be a valid orphan VG name
index e6fe6c2068899768120dbbf16aed2f3b0a0d5a44..a5b6815a722d616f0888ce5fd976ac3ba7fb1f89 100644 (file)
@@ -357,10 +357,10 @@ int check_pv_segments(struct volume_group *vg)
        return ret;
 }
 
-static int _reduce_pv(struct physical_volume *pv, struct volume_group *vg, uint32_t new_pe_count)
+static int _reduce_pv(struct physical_volume *pv, struct volume_group *vg,
+                     uint32_t old_pe_count, uint32_t new_pe_count)
 {
        struct pv_segment *peg, *pegt;
-       uint32_t old_pe_count = pv->pe_count;
 
        if (new_pe_count < pv->pe_alloc_count) {
                log_error("%s: cannot resize to %" PRIu32 " extents "
@@ -400,10 +400,9 @@ static int _reduce_pv(struct physical_volume *pv, struct volume_group *vg, uint3
 }
 
 static int _extend_pv(struct physical_volume *pv, struct volume_group *vg,
-                     uint32_t new_pe_count)
+                     uint32_t old_pe_count, uint32_t new_pe_count)
 {
        struct pv_segment *peg;
-       uint32_t old_pe_count = pv->pe_count;
 
        if ((uint64_t) new_pe_count * pv->pe_size > pv->size ) {
                log_error("%s: cannot resize to %" PRIu32 " extents as there "
@@ -432,20 +431,59 @@ static int _extend_pv(struct physical_volume *pv, struct volume_group *vg,
  */
 int pv_resize(struct physical_volume *pv,
              struct volume_group *vg,
-             uint32_t new_pe_count)
+             uint64_t size)
 {
-       if ((new_pe_count == pv->pe_count)) {
-               log_verbose("No change to size of physical volume %s.",
-                           pv_dev_name(pv));
-               return 1;
+       uint32_t old_pe_count, new_pe_count = 0;
+
+       if (size < pv_min_size()) {
+               log_error("Size must exceed minimum of %ld sectors on PV %s.",
+                          pv_min_size(), pv_dev_name(pv));
+               return 0;
        }
 
-       log_verbose("Resizing physical volume %s from %" PRIu32
-                   " to %" PRIu32 " extents.",
-                   pv_dev_name(pv), pv->pe_count, new_pe_count);
+       if (size < pv_pe_start(pv)) {
+               log_error("Size must exceed physical extent start "
+                         "of %" PRIu64 " sectors on PV %s.",
+                         pv_pe_start(pv), pv_dev_name(pv));
+       }
 
-       if (new_pe_count > pv->pe_count)
-               return _extend_pv(pv, vg, new_pe_count);
-       else
-               return _reduce_pv(pv, vg, new_pe_count);
+       old_pe_count = pv->pe_count;
+
+       if (!pv->fmt->ops->pv_resize(pv->fmt, pv, vg, size)) {
+               log_error("Format specific resize of PV %s failed.",
+                          pv_dev_name(pv));
+               return 0;
+       }
+
+       /* pv->pe_count is 0 now! We need to recalculate! */
+
+       /* If there's a VG, calculate new PE count value. */
+       if (vg) {
+               /* FIXME: Maybe PE calculation should go into pv->fmt->resize?
+                         (like it is for pv->fmt->setup) */
+               if (!(new_pe_count = pv_size(pv) / vg->extent_size)) {
+                       log_error("Size must leave space for at least one physical "
+                                 "extent of %" PRIu32 " sectors on PV %s.",
+                                  pv_pe_size(pv), pv_dev_name(pv));
+                       return 0;
+               }
+
+               if ((new_pe_count == old_pe_count)) {
+                       pv->pe_count = old_pe_count;
+                       log_verbose("No change to size of physical volume %s.",
+                                   pv_dev_name(pv));
+                       return 1;
+               }
+
+               log_verbose("Resizing physical volume %s from %" PRIu32
+                           " to %" PRIu32 " extents.",
+                           pv_dev_name(pv), pv->pe_count, new_pe_count);
+
+               if (new_pe_count > old_pe_count)
+                       return _extend_pv(pv, vg, old_pe_count, new_pe_count);
+               else
+                       return _reduce_pv(pv, vg, old_pe_count, new_pe_count);
+       }
+
+       return 1;
 }
index f1870c6c6e7d897548dd5ab133a04677c61c6e9f..636c0adaae40efc056b98969fee4bcb9bf54e60d 100644 (file)
@@ -30,12 +30,9 @@ static int _pv_resize_single(struct cmd_context *cmd,
 {
        struct pv_list *pvl;
        uint64_t size = 0;
-       uint32_t new_pe_count = 0;
        int r = 0;
        const char *pv_name = pv_dev_name(pv);
        const char *vg_name = pv_vg_name(pv);
-       struct lvmcache_info *info;
-       int mda_count = 0;
        struct volume_group *old_vg = vg;
 
        if (is_orphan_vg(vg_name)) {
@@ -49,9 +46,6 @@ static int _pv_resize_single(struct cmd_context *cmd,
                        log_error("Unable to read PV \"%s\"", pv_name);
                        return 0;
                }
-
-               mda_count = dm_list_size(&pv->fid->metadata_areas_in_use) +
-                           dm_list_size(&pv->fid->metadata_areas_ignored);
        } else {
                vg = vg_read_for_update(cmd, vg_name, NULL, 0);
 
@@ -70,24 +64,10 @@ static int _pv_resize_single(struct cmd_context *cmd,
 
                pv = pvl->pv;
 
-               if (!(info = info_from_pvid(pv->dev->pvid, 0))) {
-                       log_error("Can't get info for PV %s in volume group %s",
-                                 pv_name, vg->name);
-                       goto out;
-               }
-
-               mda_count = dm_list_size(&info->mdas);
-
                if (!archive(vg))
                        goto out;
        }
 
-       /* FIXME Create function to test compatibility properly */
-       if (mda_count > 1) {
-               log_error("%s: too many metadata areas for pvresize", pv_name);
-               goto out;
-       }
-
        if (!(pv->fmt->features & FMT_RESIZE_PV)) {
                log_error("Physical volume %s format does not support resizing.",
                          pv_name);
@@ -109,39 +89,12 @@ static int _pv_resize_single(struct cmd_context *cmd,
                size = new_size;
        }
 
-       if (size < pv_min_size()) {
-               log_error("%s: Size must exceed minimum of %" PRIu64 " sectors.",
-                         pv_name, pv_min_size());
-               goto out;
-       }
-
-       if (size < pv_pe_start(pv)) {
-               log_error("%s: Size must exceed physical extent start of "
-                         "%" PRIu64 " sectors.", pv_name, pv_pe_start(pv));
-               goto out;
-       }
-
-       pv->size = size;
-
-       if (vg) {
-               pv->size -= pv_pe_start(pv);
-               new_pe_count = pv_size(pv) / vg->extent_size;
-
-               if (!new_pe_count) {
-                       log_error("%s: Size must leave space for at "
-                                 "least one physical extent of "
-                                 "%" PRIu32 " sectors.", pv_name,
-                                 pv_pe_size(pv));
-                       goto out;
-               }
-
-               if (!pv_resize(pv, vg, new_pe_count))
-                       goto_out;
-       }
-
        log_verbose("Resizing volume \"%s\" to %" PRIu64 " sectors.",
                    pv_name, pv_size(pv));
 
+       if (!pv_resize(pv, vg, size))
+               goto_out;
+
        log_verbose("Updating physical volume \"%s\"", pv_name);
        if (!is_orphan_vg(vg_name)) {
                if (!vg_write(vg) || !vg_commit(vg)) {
This page took 0.043982 seconds and 5 git commands to generate.