From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 4631 invoked by alias); 21 Feb 2011 12:27:28 -0000 Received: (qmail 4614 invoked by uid 9796); 21 Feb 2011 12:27:28 -0000 Date: Mon, 21 Feb 2011 12:27:00 -0000 Message-ID: <20110221122728.4612.qmail@sourceware.org> From: prajnoha@sourceware.org To: lvm-devel@redhat.com, lvm2-cvs@sourceware.org Subject: LVM2 lib/format_text/format-text.c lib/metadat ... Mailing-List: contact lvm2-cvs-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Post: List-Help: , Sender: lvm2-cvs-owner@sourceware.org X-SW-Source: 2011-02/txt/msg00062.txt.bz2 CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: prajnoha@sourceware.org 2011-02-21 12:27:26 Modified files: lib/format_text: format-text.c lib/metadata : metadata-exported.h metadata.h pv_manip.c tools : pvresize.c Log message: Change pvresize code to work with new metadata handling interface and allow resizing a PV with two metadata areas. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/format_text/format-text.c.diff?cvsroot=lvm2&r1=1.164&r2=1.165 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/metadata-exported.h.diff?cvsroot=lvm2&r1=1.180&r2=1.181 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/metadata.h.diff?cvsroot=lvm2&r1=1.238&r2=1.239 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/pv_manip.c.diff?cvsroot=lvm2&r1=1.25&r2=1.26 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/pvresize.c.diff?cvsroot=lvm2&r1=1.40&r2=1.41 --- LVM2/lib/format_text/format-text.c 2011/02/21 12:26:27 1.164 +++ LVM2/lib/format_text/format-text.c 2011/02/21 12:27:26 1.165 @@ -2093,6 +2093,55 @@ 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 @@ .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, --- LVM2/lib/metadata/metadata-exported.h 2011/02/21 12:26:27 1.180 +++ LVM2/lib/metadata/metadata-exported.h 2011/02/21 12:27:26 1.181 @@ -428,7 +428,7 @@ 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); --- LVM2/lib/metadata/metadata.h 2011/02/21 12:26:27 1.238 +++ LVM2/lib/metadata/metadata.h 2011/02/21 12:27:26 1.239 @@ -293,6 +293,14 @@ 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 */ --- LVM2/lib/metadata/pv_manip.c 2010/03/31 17:23:19 1.25 +++ LVM2/lib/metadata/pv_manip.c 2011/02/21 12:27:26 1.26 @@ -357,10 +357,10 @@ 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 _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 @@ */ 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 (new_pe_count > pv->pe_count) - return _extend_pv(pv, vg, new_pe_count); - else - return _reduce_pv(pv, vg, 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)); + } + + 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; } --- LVM2/tools/pvresize.c 2011/02/21 12:26:28 1.40 +++ LVM2/tools/pvresize.c 2011/02/21 12:27:26 1.41 @@ -30,12 +30,9 @@ { 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 @@ 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 @@ 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 @@ 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)) {