All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/17] Add interface to support adding and removing metadata areas on demand (v2)
@ 2011-01-24 11:03 Peter Rajnoha
  2011-01-24 11:03 ` [PATCH 01/17] Add pvid parameter to create_instance function Peter Rajnoha
                   ` (17 more replies)
  0 siblings, 18 replies; 36+ messages in thread
From: Peter Rajnoha @ 2011-01-24 11:03 UTC (permalink / raw)
  To: lvm-devel

This patchset provides a possibility to add new metadata areas on demand
as well as removing them. Now, we can add a new metadata area independently
of the PV initialisation so if there's a place we can even add metadata area
additionally. The same applies for metadata removal functionality. This is
only internal interface for now, but we should be able to provide external
hooks in lvm2 commands if desired.

The patchset also tries to cleanup existing pv_setup/pv_write code. It also
uses the new interface to allow resizing a PV with more copies of metadata
areas on disk which was not allowed before because of missing metadata
handling part in the interface.

To support all these changes, a definition of format_instance for PVs is
now supported. This structure holds all the information we need.

This patchset should be applicable to 4dff097f6617ef746cd75250f74425825082a8ce.
The tests seems to be passing, just one is still failing - it's lvm2 format
handling: t-pv-create-usage.sh: "PV segment pe_count mismatch: 33 != 32".

Peter Rajnoha (17):
  Add pvid parameter to create_instance function.
  Add supporting functions for metadata areas stored in format
    instance.
  Add struct format_instance *fid field to struct physical_volume.
  Add format_instance support for pv_read.
  Add attach_existing_mdas parameter to create_instance fn.
  Remove useless mdas parameter from PV read functions.
  Add pv_add_metadata_area fn to support adding metadata areas on
    demand.
  Add pv_remove_metadata_area fn to support removing metadata areas on 
       demand.
  Add pv_initialise fn to format_handler interface.
  Add pe_start_locked parameter to pv_create fn.
  Refactor pv_setup to not include the PV initialisation code.
  Remove unused _mda_setup code.
  Cleanup pv_write code to use recent changes in metadata handling    
    interface.
  Use new metadata handling interface to provide better support for PV 
       resize.
  Change vg_convert code to actually work with recent changes in
    metadata     handling interface.
  Fix pvchange -u to work with recent changes in metadata handling    
    interface.
  Fix pvchange --metadataignore to work with recent changes in metadata
        handling interface.

 lib/cache/lvmcache.c             |    4 +-
 lib/format1/format1.c            |   38 +-
 lib/format_pool/format_pool.c    |   28 +-
 lib/format_text/archive.c        |    2 +-
 lib/format_text/archiver.c       |   15 +-
 lib/format_text/format-text.c    | 1027 ++++++++++++++++++++++----------------
 lib/format_text/format-text.h    |    8 +
 lib/metadata/metadata-exported.h |   23 +-
 lib/metadata/metadata.c          |  357 +++++++++++---
 lib/metadata/metadata.h          |   71 ++-
 lib/metadata/pv.c                |   20 +-
 lib/metadata/pv.h                |    2 +
 lib/metadata/pv_manip.c          |   70 ++-
 tools/pvchange.c                 |    5 +-
 tools/pvremove.c                 |   10 +-
 tools/pvresize.c                 |   57 +--
 tools/toollib.c                  |   14 +-
 tools/vgconvert.c                |   93 +---
 tools/vgreduce.c                 |    2 +-
 19 files changed, 1120 insertions(+), 726 deletions(-)

-- 
1.7.3.4



^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH 01/17] Add pvid parameter to create_instance function.
  2011-01-24 11:03 [PATCH 00/17] Add interface to support adding and removing metadata areas on demand (v2) Peter Rajnoha
@ 2011-01-24 11:03 ` Peter Rajnoha
  2011-01-25 12:54   ` Petr Rockai
  2011-01-24 11:03 ` [PATCH 02/17] Add supporting functions for metadata areas stored in format instance Peter Rajnoha
                   ` (16 subsequent siblings)
  17 siblings, 1 reply; 36+ messages in thread
From: Peter Rajnoha @ 2011-01-24 11:03 UTC (permalink / raw)
  To: lvm-devel

This is a preparation for the next patches...

The format instance holds the information about current metadata areas and it
is a snapshot of what we have in the cache at the moment of the instance
creation. Through the command exection, we use this instance to modify, set
and access modified metadata areas (like we use it to support the
--metadataignore and we store the metadata areas that are in use and the
ones that are ignored).

But to support modifying metadata areas fully (with add/remove metadata
area support), we need to be able to create format instances for PVs as well.
Hence, add the pvid parameter for the create_instance function.

The rules we will follow:

 - the format instance is VG-based or PV-based, but *never both*
   at the same time,

 - when a PV (structure) is alone, not part of any VG, we will have
   a PV based format_instance attached to the PV structure,

 - when a PV is part of the VG, any existing PV-based format_instance
   is destroyed and the PV strucutre will reference VG based format
   instance instead.

 - whatever we need change for mdas, we'll use the format_instance,
   we don't touch the cache directly! This will be synchronized with the
   format instance after pv_write automatically.

Signed-off-by: Peter Rajnoha <prajnoha@redhat.com>
---
 lib/cache/lvmcache.c          |    2 +-
 lib/format1/format1.c         |    1 +
 lib/format_pool/format_pool.c |    1 +
 lib/format_text/archive.c     |    2 +-
 lib/format_text/archiver.c    |    8 ++++----
 lib/format_text/format-text.c |   20 +++++++++++---------
 lib/metadata/metadata.c       |   10 +++++-----
 lib/metadata/metadata.h       |    5 +++--
 8 files changed, 27 insertions(+), 22 deletions(-)

diff --git a/lib/cache/lvmcache.c b/lib/cache/lvmcache.c
index 0e9cae1..476b176 100644
--- a/lib/cache/lvmcache.c
+++ b/lib/cache/lvmcache.c
@@ -653,7 +653,7 @@ struct volume_group *lvmcache_get_vg(const char *vgid, unsigned precommitted)
 		return NULL;
 
 	if (!(fid = vginfo->fmt->ops->create_instance(vginfo->fmt,
-						      vginfo->vgname,
+						      NULL, vginfo->vgname,
 						      vgid, NULL)))
 		return_NULL;
 
diff --git a/lib/format1/format1.c b/lib/format1/format1.c
index fc14444..13b757d 100644
--- a/lib/format1/format1.c
+++ b/lib/format1/format1.c
@@ -522,6 +522,7 @@ static struct metadata_area_ops _metadata_format1_ops = {
 };
 
 static struct format_instance *_format1_create_instance(const struct format_type *fmt,
+						const char *pvid __attribute__((unused)),
 						const char *vgname __attribute__((unused)),
 						const char *vgid __attribute__((unused)),
 						void *private __attribute__((unused)))
diff --git a/lib/format_pool/format_pool.c b/lib/format_pool/format_pool.c
index 730da87..814d80c 100644
--- a/lib/format_pool/format_pool.c
+++ b/lib/format_pool/format_pool.c
@@ -249,6 +249,7 @@ static struct metadata_area_ops _metadata_format_pool_ops = {
 /* *INDENT-ON* */
 
 static struct format_instance *_pool_create_instance(const struct format_type *fmt,
+						const char *pvid __attribute__((unused)),
 						const char *vgname __attribute__((unused)),
 						const char *vgid __attribute__((unused)),
 						void *private __attribute__((unused)))
diff --git a/lib/format_text/archive.c b/lib/format_text/archive.c
index 43425dc..760153c 100644
--- a/lib/format_text/archive.c
+++ b/lib/format_text/archive.c
@@ -309,7 +309,7 @@ static void _display_archive(struct cmd_context *cmd, struct archive_file *af)
 
 	if (!(context = create_text_context(cmd, af->path, NULL)) ||
 	    !(tf = cmd->fmt_backup->ops->create_instance(cmd->fmt_backup, NULL,
-							 NULL, context))) {
+							 NULL, NULL, context))) {
 		log_error("Couldn't create text instance object.");
 		return;
 	}
diff --git a/lib/format_text/archiver.c b/lib/format_text/archiver.c
index e0212a2..b7dcad9 100644
--- a/lib/format_text/archiver.c
+++ b/lib/format_text/archiver.c
@@ -278,7 +278,7 @@ struct volume_group *backup_read_vg(struct cmd_context *cmd,
 	if (!(context = create_text_context(cmd, file,
 					    cmd->cmd_line)) ||
 	    !(tf = cmd->fmt_backup->ops->create_instance(cmd->fmt_backup, NULL,
-							 NULL, context))) {
+							 NULL, NULL, context))) {
 		log_error("Couldn't create text format object.");
 		return NULL;
 	}
@@ -306,8 +306,8 @@ int backup_restore_vg(struct cmd_context *cmd, struct volume_group *vg)
 	 */
 
 	/* Attempt to write out using currently active format */
-	if (!(vg->fid = cmd->fmt->ops->create_instance(cmd->fmt, vg->name,
-						       NULL, NULL))) {
+	if (!(vg->fid = cmd->fmt->ops->create_instance(cmd->fmt, NULL,
+						vg->name, NULL, NULL))) {
 		log_error("Failed to allocate format instance");
 		return 0;
 	}
@@ -398,7 +398,7 @@ int backup_to_file(const char *file, const char *desc, struct volume_group *vg)
 
 	if (!(context = create_text_context(cmd, file, desc)) ||
 	    !(tf = cmd->fmt_backup->ops->create_instance(cmd->fmt_backup, NULL,
-							 NULL, context))) {
+							 NULL, NULL, context))) {
 		log_error("Couldn't create backup object.");
 		return 0;
 	}
diff --git a/lib/format_text/format-text.c b/lib/format_text/format-text.c
index c186757..fda8255 100644
--- a/lib/format_text/format-text.c
+++ b/lib/format_text/format-text.c
@@ -37,10 +37,11 @@
 #include <dirent.h>
 #include <ctype.h>
 
-static struct format_instance *_text_create_text_instance(const struct format_type
-						     *fmt, const char *vgname,
-						     const char *vgid,
-						     void *context);
+static struct format_instance *_text_create_text_instance(const struct format_type *fmt,
+							  const char *pvid,
+							  const char *vgname,
+							  const char *vgid,
+							  void *context);
 
 struct text_fid_context {
 	char *raw_metadata_buf;
@@ -1085,7 +1086,7 @@ static int _scan_file(const struct format_type *fmt, const char *vgname)
 
 				/* FIXME stat file to see if it's changed */
 				fid = _text_create_text_instance(fmt, NULL, NULL,
-							    NULL);
+								 NULL, NULL);
 				if ((vg = _vg_read_file_name(fid, scanned_vgname,
 							     path))) {
 					/* FIXME Store creation host in vg */
@@ -1912,10 +1913,11 @@ static int _text_pv_setup(const struct format_type *fmt,
 }
 
 /* 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 char *vgname,
-						     const char *vgid,
-						     void *context)
+static struct format_instance *_text_create_text_instance(const struct format_type*fmt,
+							  const char *pvid,
+							  const char *vgname,
+							  const char *vgid,
+							  void *context)
 {
 	struct format_instance *fid;
 	struct text_fid_context *fidtc;
diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
index 771cdb0..fd1948a 100644
--- a/lib/metadata/metadata.c
+++ b/lib/metadata/metadata.c
@@ -974,8 +974,8 @@ struct volume_group *vg_create(struct cmd_context *cmd, const char *vg_name)
 	/* initialize removed_pvs list */
 	dm_list_init(&vg->removed_pvs);
 
-	if (!(vg->fid = cmd->fmt->ops->create_instance(cmd->fmt, vg_name,
-						       NULL, NULL))) {
+	if (!(vg->fid = cmd->fmt->ops->create_instance(cmd->fmt, NULL,
+						vg_name, NULL, NULL))) {
 		log_error("Failed to create format instance");
 		goto bad;
 	}
@@ -2629,7 +2629,7 @@ static struct volume_group *_vg_read_orphans(struct cmd_context *cmd,
 	}
 
 	/* create format instance with appropriate metadata area */
-	if (!(vg->fid = vginfo->fmt->ops->create_instance(vginfo->fmt,
+	if (!(vg->fid = vginfo->fmt->ops->create_instance(vginfo->fmt, NULL,
 							  orphan_vgname, NULL,
 							  NULL))) {
 		log_error("Failed to create format instance");
@@ -2808,7 +2808,7 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
 		use_precommitted = 0;
 
 	/* create format instance with appropriate metadata area */
-	if (!(fid = fmt->ops->create_instance(fmt, vgname, vgid, NULL))) {
+	if (!(fid = fmt->ops->create_instance(fmt, NULL, vgname, vgid, NULL))) {
 		log_error("Failed to create format instance");
 		return NULL;
 	}
@@ -2962,7 +2962,7 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
 			use_precommitted = 0;
 
 		/* create format instance with appropriate metadata area */
-		if (!(fid = fmt->ops->create_instance(fmt, vgname, vgid, NULL))) {
+		if (!(fid = fmt->ops->create_instance(fmt, NULL, vgname, vgid, NULL))) {
 			log_error("Failed to create format instance");
 			return NULL;
 		}
diff --git a/lib/metadata/metadata.h b/lib/metadata/metadata.h
index c0f9148..ab7cff0 100644
--- a/lib/metadata/metadata.h
+++ b/lib/metadata/metadata.h
@@ -279,8 +279,9 @@ struct format_handler {
 	/*
 	 * Create format instance with a particular metadata area
 	 */
-	struct format_instance *(*create_instance) (const struct format_type *
-						    fmt, const char *vgname,
+	struct format_instance *(*create_instance) (const struct format_type *fmt,
+						    const char *pvid,
+						    const char *vgname,
 						    const char *vgid,
 						    void *context);
 
-- 
1.7.3.4



^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 02/17] Add supporting functions for metadata areas stored in format instance.
  2011-01-24 11:03 [PATCH 00/17] Add interface to support adding and removing metadata areas on demand (v2) Peter Rajnoha
  2011-01-24 11:03 ` [PATCH 01/17] Add pvid parameter to create_instance function Peter Rajnoha
@ 2011-01-24 11:03 ` Peter Rajnoha
  2011-01-25 13:16   ` Petr Rockai
  2011-01-24 11:03 ` [PATCH 03/17] Add struct format_instance *fid field to struct physical_volume Peter Rajnoha
                   ` (15 subsequent siblings)
  17 siblings, 1 reply; 36+ messages in thread
From: Peter Rajnoha @ 2011-01-24 11:03 UTC (permalink / raw)
  To: lvm-devel

This patch divides current create_instance functionality into PV-based
and VG-based. We add a simple flag "pv_only" in struct format_instance
that will help us to identify the type of the format_instance when used
later on (since we will always have PV/VG separation, I think it would
be useless to define an interface for this where we would attach supporting
functions on the fly like we do for mda->ops as an example. In this case,
a simple flag is fine to switch the functionality).

Another change is the metadata_areas_index we have in the struct
format_instance. To access a certain metadata area, we need to know
two keys - PV id and metadta area index within that PV. So a few new
functions have been modified/added to support this:
- fid_add_mda (modified)
- fid_add_mdas (modified)
- fid_remove_mda (new)
- fid_get_mda_indexed (new)

Actually, the form of the key that will be used is up to the caller,
but he needs to remember the key somehow to get the mda back :)

The key is simply made up of the base key (a string) and a subkey
(an unsigned integer). The actual key used internally is then a string:

  <basekey>_<subkey>

Now, the metadata_areas_index is format specific. This is because
each format can have different number and types of metadata areas
it can support and so we'd like to be able to use the most suitable
index for the specific format. Also, we can use a different indexing
scheme for PV and VG based format_instance.

For PV based format instance in current lvm2 format, we have only
2 metadata areas at maximum. So we use only a simple array. No need
to use any buldozer-type indexing here :)

For VG based format instance, we can group many many mdas together
from numerous PVs. So we'll use a hash here (like we use for the cache).
(but maybe we can add even better indexing in the future!)

If key is not defined, we just store the mda without indexing.
We'll have it in the metadata_areas_in_use/ignored list directly.

...but we can change these later if needed, of course. The
implementation is internal, the interface stays the same)

Also, I kept the format instance's metadata_areas_in_use/ignored for
now, but eventually, I'd like this to be accessed through the index
in the future. But that is another step to take later...

Signed-off-by: Peter Rajnoha <prajnoha@redhat.com>
---
 lib/format1/format1.c            |    1 +
 lib/format_text/format-text.c    |  137 ++++++++++++++++++++++++++++----------
 lib/format_text/format-text.h    |    1 +
 lib/metadata/metadata-exported.h |    3 +
 lib/metadata/metadata.c          |  103 +++++++++++++++++++++++++++-
 lib/metadata/metadata.h          |   10 ++-
 6 files changed, 213 insertions(+), 42 deletions(-)

diff --git a/lib/format1/format1.c b/lib/format1/format1.c
index 13b757d..ff5b0f5 100644
--- a/lib/format1/format1.c
+++ b/lib/format1/format1.c
@@ -534,6 +534,7 @@ static struct format_instance *_format1_create_instance(const struct format_type
 		return_NULL;
 
 	fid->fmt = fmt;
+	fid->metadata_areas_index = NULL;
 	dm_list_init(&fid->metadata_areas_in_use);
 	dm_list_init(&fid->metadata_areas_ignored);
 
diff --git a/lib/format_text/format-text.c b/lib/format_text/format-text.c
index fda8255..c8c56f7 100644
--- a/lib/format_text/format-text.c
+++ b/lib/format_text/format-text.c
@@ -48,6 +48,10 @@ struct text_fid_context {
 	uint32_t raw_metadata_buf_size;
 };
 
+struct text_fid_pv_context {
+	int64_t label_sector;
+};
+
 struct dir_list {
 	struct dm_list list;
 	char dir[0];
@@ -1912,14 +1916,38 @@ static int _text_pv_setup(const struct format_type *fmt,
 	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 char *pvid,
-							  const char *vgname,
-							  const char *vgid,
-							  void *context)
+static int _create_pv_text_instance(struct format_instance *fid, const char *pvid)
+{
+	struct text_fid_pv_context *fid_pv_tc;
+	struct lvmcache_info *info;
+
+	fid->pv_only = 1;
+
+	if (!(fid_pv_tc = (struct text_fid_pv_context *)
+			  dm_pool_zalloc(fid->fmt->cmd->mem, sizeof(*fid_pv_tc)))) {
+		log_error("Couldn't allocate text_fid_pv_context.");
+		return 0;
+	}
+	fid_pv_tc->label_sector = -1;
+	fid->private = (void *) fid_pv_tc;
+
+	if (!(fid->metadata_areas_index = dm_pool_zalloc(fid->fmt->cmd->mem,
+						   FMT_TEXT_MAX_MDAS_PER_PV *
+						   sizeof(struct metadata_area *)))) {
+		log_error("Couldn't allocate format instance metadata index.");
+		return 0;
+	}
+
+	if ((info = info_from_pvid(pvid, 0)))
+		fid_add_mdas(fid, &info->mdas, pvid, ID_LEN);
+
+	return 1;
+}
+
+static int _create_vg_text_instance(struct format_instance *fid,
+				    const char *vgname, const char *vgid,
+				    void *context)
 {
-	struct format_instance *fid;
 	struct text_fid_context *fidtc;
 	struct metadata_area *mda;
 	struct mda_context *mdac;
@@ -1930,85 +1958,122 @@ static struct format_instance *_text_create_text_instance(const struct format_ty
 	struct lvmcache_vginfo *vginfo;
 	struct lvmcache_info *info;
 
-	if (!(fid = dm_pool_alloc(fmt->cmd->mem, sizeof(*fid)))) {
-		log_error("Couldn't allocate format instance object.");
-		return NULL;
-	}
+	fid->pv_only = 0;
 
 	if (!(fidtc = (struct text_fid_context *)
-			dm_pool_zalloc(fmt->cmd->mem,sizeof(*fidtc)))) {
+			dm_pool_zalloc(fid->fmt->cmd->mem,sizeof(*fidtc)))) {
 		log_error("Couldn't allocate text_fid_context.");
-		return NULL;
+		return 0;
 	}
 
 	fidtc->raw_metadata_buf = NULL;
 	fid->private = (void *) fidtc;
 
-	fid->fmt = fmt;
-	dm_list_init(&fid->metadata_areas_in_use);
-	dm_list_init(&fid->metadata_areas_ignored);
-
 	if (!vgname) {
-		if (!(mda = dm_pool_zalloc(fmt->cmd->mem, sizeof(*mda))))
-			return_NULL;
+		if (!(mda = dm_pool_zalloc(fid->fmt->cmd->mem, sizeof(*mda))))
+			return_0;
 		mda->ops = &_metadata_text_file_backup_ops;
 		mda->metadata_locn = context;
 		mda->status = 0;
-		fid_add_mda(fid, mda);
+		fid_add_mda(fid, mda, NULL, 0, 0);
 	} else {
-		dir_list = &((struct mda_lists *) fmt->private)->dirs;
+		if (!(fid->metadata_areas_index = dm_hash_create(128))) {
+			log_error("Couldn't create metadata index for format "
+				  "instance of VG %s.", vgname);
+			return 0;
+		}
+
+		dir_list = &((struct mda_lists *) fid->fmt->private)->dirs;
 
 		dm_list_iterate_items(dl, dir_list) {
 			if (dm_snprintf(path, PATH_MAX, "%s/%s",
 					 dl->dir, vgname) < 0) {
 				log_error("Name too long %s/%s", dl->dir,
 					  vgname);
-				return NULL;
+				return 0;
 			}
 
-			context = create_text_context(fmt->cmd, path, NULL);
-			if (!(mda = dm_pool_zalloc(fmt->cmd->mem, sizeof(*mda))))
-				return_NULL;
+			context = create_text_context(fid->fmt->cmd, path, NULL);
+			if (!(mda = dm_pool_zalloc(fid->fmt->cmd->mem, sizeof(*mda))))
+				return_0;
 			mda->ops = &_metadata_text_file_ops;
 			mda->metadata_locn = context;
 			mda->status = 0;
-			fid_add_mda(fid, mda);
+			fid_add_mda(fid, mda, NULL, 0, 0);
 		}
 
-		raw_list = &((struct mda_lists *) fmt->private)->raws;
+		raw_list = &((struct mda_lists *) fid->fmt->private)->raws;
 
 		dm_list_iterate_items(rl, raw_list) {
 			/* FIXME Cache this; rescan below if some missing */
 			if (!_raw_holds_vgname(fid, &rl->dev_area, vgname))
 				continue;
 
-			if (!(mda = dm_pool_zalloc(fmt->cmd->mem, sizeof(*mda))))
-				return_NULL;
+			if (!(mda = dm_pool_zalloc(fid->fmt->cmd->mem, sizeof(*mda))))
+				return_0;
 
-			if (!(mdac = dm_pool_zalloc(fmt->cmd->mem, sizeof(*mdac))))
-				return_NULL;
+			if (!(mdac = dm_pool_zalloc(fid->fmt->cmd->mem, sizeof(*mdac))))
+				return_0;
 			mda->metadata_locn = mdac;
 			/* FIXME Allow multiple dev_areas inside area */
 			memcpy(&mdac->area, &rl->dev_area, sizeof(mdac->area));
 			mda->ops = &_metadata_text_raw_ops;
 			mda->status = 0;
 			/* FIXME MISTAKE? mda->metadata_locn = context; */
-			fid_add_mda(fid, mda);
+			fid_add_mda(fid, mda, NULL, 0, 0);
 		}
 
 		/* Scan PVs in VG for any further MDAs */
-		lvmcache_label_scan(fmt->cmd, 0);
+		lvmcache_label_scan(fid->fmt->cmd, 0);
 		if (!(vginfo = vginfo_from_vgname(vgname, vgid)))
 			goto_out;
 		dm_list_iterate_items(info, &vginfo->infos) {
-			if (!fid_add_mdas(fid, &info->mdas))
-				return_NULL;
+			if (!fid_add_mdas(fid, &info->mdas, info->dev->pvid,
+					  ID_LEN))
+				return_0;
 		}
 		/* FIXME Check raw metadata area count - rescan if required */
 	}
 
       out:
-	return fid;
+	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 char *pvid,
+							  const char *vgname,
+							  const char *vgid,
+							  void *context)
+{
+	struct format_instance *fid;
+	int r;
+
+	if (pvid && (vgname || vgid)) {
+		log_error(INTERNAL_ERROR "Format instance must be PV "
+					 "or VG specific, not both.");
+		return NULL;
+	}
+
+	if (!(fid = dm_pool_alloc(fmt->cmd->mem, sizeof(*fid)))) {
+		log_error("Couldn't allocate format instance object.");
+		return NULL;
+	}
+
+	fid->fmt = fmt;
+	fid->metadata_areas_index = NULL;
+	dm_list_init(&fid->metadata_areas_in_use);
+	dm_list_init(&fid->metadata_areas_ignored);
+
+	r = pvid ? _create_pv_text_instance(fid, pvid) :
+		   _create_vg_text_instance(fid, vgname, vgid, context);
+
+	if (r)
+		return fid;
+	else {
+		dm_pool_free(fmt->cmd->mem, fid);
+		return NULL;
+	}
 }
 
 void *create_text_context(struct cmd_context *cmd, const char *path,
diff --git a/lib/format_text/format-text.h b/lib/format_text/format-text.h
index 79365ea..f3cf4f5 100644
--- a/lib/format_text/format-text.h
+++ b/lib/format_text/format-text.h
@@ -22,6 +22,7 @@
 #define FMT_TEXT_NAME "lvm2"
 #define FMT_TEXT_ALIAS "text"
 #define FMT_TEXT_ORPHAN_VG_NAME ORPHAN_VG_NAME(FMT_TEXT_NAME)
+#define FMT_TEXT_MAX_MDAS_PER_PV 2
 
 /*
  * Archives a vg config.  'retain_days' is the minimum number of
diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index a9709d6..d8247dd 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -173,6 +173,8 @@ struct pv_segment {
 
 struct format_instance {
 	const struct format_type *fmt;
+	int pv_only;
+
 	/*
 	 * Each mda in a vg is on exactly one of the below lists.
 	 * MDAs on the 'in_use' list will be read from / written to
@@ -181,6 +183,7 @@ struct format_instance {
 	 */
 	struct dm_list metadata_areas_in_use;
 	struct dm_list metadata_areas_ignored;
+	void *metadata_areas_index;
 	void *private;
 };
 
diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
index fd1948a..c3accaf 100644
--- a/lib/metadata/metadata.c
+++ b/lib/metadata/metadata.c
@@ -2881,7 +2881,8 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
 					break;
 				}
 				if (dm_list_size(&info->mdas)) {
-					if (!fid_add_mdas(fid, &info->mdas))
+					if (!fid_add_mdas(fid, &info->mdas,
+							info->dev->pvid, ID_LEN))
 						return_NULL;
 					 
 					log_debug("Empty mda found for VG %s.", vgname);
@@ -3912,22 +3913,116 @@ uint32_t vg_lock_newname(struct cmd_context *cmd, const char *vgname)
 	return FAILED_EXIST;
 }
 
-void fid_add_mda(struct format_instance *fid, struct metadata_area *mda)
+static int _convert_key_to_string(const char *key, size_t key_len,
+				  unsigned subkey, char *buf, size_t buf_len)
 {
+	memcpy(buf, key, key_len);
+	buf += key_len;
+	buf_len -= key_len;
+	if ((dm_snprintf(buf, buf_len, "_%u", subkey) == -1))
+		return_0;
+
+	return 1;
+}
+
+int fid_add_mda(struct format_instance *fid, struct metadata_area *mda,
+		 const char *key, size_t key_len, const unsigned subkey)
+{
+	char extended_key[PATH_MAX];
+
 	dm_list_add(mda_is_ignored(mda) ? &fid->metadata_areas_ignored :
 					  &fid->metadata_areas_in_use, &mda->list);
+
+	/*
+	 * Return if the mda is not supposed to be
+	 * indexed or the index itself is not initialised */
+	if (!key || !fid->metadata_areas_index)
+		return 1;
+
+	if (!_convert_key_to_string(key, key_len, subkey,
+				    extended_key, PATH_MAX))
+		return_0;
+
+	/* Add metadata area to index. */
+	if (fid->pv_only)
+		((struct metadata_area **)fid->metadata_areas_index)[subkey] = mda;
+	else
+		dm_hash_insert(fid->metadata_areas_index, extended_key, mda);
+
+	return 1;
 }
 
-int fid_add_mdas(struct format_instance *fid, struct dm_list *mdas)
+int fid_add_mdas(struct format_instance *fid, struct dm_list *mdas,
+		 const char *key, size_t key_len)
 {
 	struct metadata_area *mda, *mda_new;
+	unsigned mda_index = 0;
 
 	dm_list_iterate_items(mda, mdas) {
 		mda_new = mda_copy(fid->fmt->cmd->mem, mda);
 		if (!mda_new)
 			return_0;
-		fid_add_mda(fid, mda_new);
+
+		fid_add_mda(fid, mda_new, key, key_len, mda_index);
+		mda_index++;
 	}
+
+	return 1;
+}
+
+struct metadata_area *fid_get_mda_indexed(struct format_instance *fid,
+					  const char *key, size_t key_len,
+					  const unsigned subkey)
+{
+	char extended_key[PATH_MAX];
+	struct metadata_area *mda = NULL;
+
+	if (!_convert_key_to_string(key, key_len, subkey,
+				    extended_key, PATH_MAX))
+		return_NULL;
+
+	if (fid->pv_only)
+		mda = ((struct metadata_area **)fid->metadata_areas_index)[subkey];
+	else
+		mda = (struct metadata_area *) dm_hash_lookup(fid->metadata_areas_index,
+							      extended_key);
+	return mda;
+}
+
+int fid_remove_mda(struct format_instance *fid, struct metadata_area *mda,
+		   const char *key, size_t key_len, const unsigned subkey)
+{
+	struct metadata_area *mda_indexed = NULL;
+	char extended_key[PATH_MAX];
+
+	/* At least one of mda or key must be specified. */
+	if (!mda && !key)
+		return 1;
+
+	if (key) {
+		/*
+		 * If both mda and key specified, check given mda
+		 * with what we find using the index and return
+		 * immediately if these two do not match.
+		 */
+		if (!(mda_indexed = fid_get_mda_indexed(fid, key, key_len, subkey)) ||
+		     (mda && mda != mda_indexed))
+			return 1;
+
+		if (!_convert_key_to_string(key, key_len, subkey,
+					    extended_key, PATH_MAX))
+			return_0;
+
+		mda = mda_indexed;
+
+		if (fid->pv_only)
+			((struct metadata_area**)fid->metadata_areas_index)[subkey] = NULL;
+		else
+			dm_hash_remove(fid->metadata_areas_index, extended_key);
+	}
+
+	dm_list_del(&mda->list);
+
 	return 1;
 }
 
diff --git a/lib/metadata/metadata.h b/lib/metadata/metadata.h
index ab7cff0..0fbc954 100644
--- a/lib/metadata/metadata.h
+++ b/lib/metadata/metadata.h
@@ -191,8 +191,14 @@ struct metadata_area *mda_copy(struct dm_pool *mem,
 unsigned mda_is_ignored(struct metadata_area *mda);
 void mda_set_ignored(struct metadata_area *mda, unsigned ignored);
 unsigned mda_locns_match(struct metadata_area *mda1, struct metadata_area *mda2);
-void fid_add_mda(struct format_instance *fid, struct metadata_area *mda);
-int fid_add_mdas(struct format_instance *fid, struct dm_list *mdas);
+int fid_add_mda(struct format_instance *fid, struct metadata_area *mda,
+		 const char *key, size_t key_len, const unsigned subkey);
+int fid_add_mdas(struct format_instance *fid, struct dm_list *mdas,
+		 const char *key, size_t key_len);
+int fid_remove_mda(struct format_instance *fid, struct metadata_area *mda,
+		   const char *key, size_t key_len, const unsigned subkey);
+struct metadata_area *fid_get_mda_indexed(struct format_instance *fid,
+		const char *key, size_t key_len, const unsigned subkey);
 int mdas_empty_or_ignored(struct dm_list *mdas);
 
 #define seg_pvseg(seg, s)	(seg)->areas[(s)].u.pv.pvseg
-- 
1.7.3.4



^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 03/17] Add struct format_instance *fid field to struct physical_volume.
  2011-01-24 11:03 [PATCH 00/17] Add interface to support adding and removing metadata areas on demand (v2) Peter Rajnoha
  2011-01-24 11:03 ` [PATCH 01/17] Add pvid parameter to create_instance function Peter Rajnoha
  2011-01-24 11:03 ` [PATCH 02/17] Add supporting functions for metadata areas stored in format instance Peter Rajnoha
@ 2011-01-24 11:03 ` Peter Rajnoha
  2011-01-25 13:03   ` Petr Rockai
  2011-01-24 11:03 ` [PATCH 04/17] Add format_instance support for pv_read Peter Rajnoha
                   ` (14 subsequent siblings)
  17 siblings, 1 reply; 36+ messages in thread
From: Peter Rajnoha @ 2011-01-24 11:03 UTC (permalink / raw)
  To: lvm-devel

So PV has also a format instance from now on.
Also, for starters, let's create a new PV-based format_instance in
pv_create code.

Signed-off-by: Peter Rajnoha <prajnoha@redhat.com>
---
 lib/metadata/metadata.c |    7 +++++++
 lib/metadata/pv.h       |    1 +
 2 files changed, 8 insertions(+), 0 deletions(-)

diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
index c3accaf..ed2084d 100644
--- a/lib/metadata/metadata.c
+++ b/lib/metadata/metadata.c
@@ -1547,6 +1547,7 @@ static struct physical_volume *_alloc_pv(struct dm_pool *mem, struct device *dev
 	if (!pv)
 		return_NULL;
 
+	pv->fid = NULL;
 	pv->pe_size = 0;
 	pv->pe_start = 0;
 	pv->pe_count = 0;
@@ -1638,6 +1639,12 @@ struct physical_volume *pv_create(const struct cmd_context *cmd,
 		goto bad;
 	}
 
+	if (!(pv->fid = fmt->ops->create_instance(fmt, (const char *) &pv->id,
+						  NULL, NULL, NULL))) {
+		log_error("Couldn't create format instance for PV %s.", pv_dev_name(pv));
+		goto bad;
+	}
+
 	pv->fmt = fmt;
 	pv->vg_name = fmt->orphan_vg_name;
 
diff --git a/lib/metadata/pv.h b/lib/metadata/pv.h
index a02f6f8..a9efcfe 100644
--- a/lib/metadata/pv.h
+++ b/lib/metadata/pv.h
@@ -24,6 +24,7 @@ struct physical_volume {
 	struct id id;
 	struct device *dev;
 	const struct format_type *fmt;
+	struct format_instance *fid;
 
 	/*
 	 * vg_name and vgid are used before the parent VG struct exists.
-- 
1.7.3.4



^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 04/17] Add format_instance support for pv_read.
  2011-01-24 11:03 [PATCH 00/17] Add interface to support adding and removing metadata areas on demand (v2) Peter Rajnoha
                   ` (2 preceding siblings ...)
  2011-01-24 11:03 ` [PATCH 03/17] Add struct format_instance *fid field to struct physical_volume Peter Rajnoha
@ 2011-01-24 11:03 ` Peter Rajnoha
  2011-01-25 13:30   ` Petr Rockai
  2011-01-24 11:03 ` [PATCH 05/17] Add attach_existing_mdas parameter to create_instance fn Peter Rajnoha
                   ` (13 subsequent siblings)
  17 siblings, 1 reply; 36+ messages in thread
From: Peter Rajnoha @ 2011-01-24 11:03 UTC (permalink / raw)
  To: lvm-devel

We don't need to store metadata areas in a separate "mdas" parameter
since it is in the pv->fid now. If the fid is not defined yet and is
NULL, pv_read code will create a new one (if there's no VG fid yet
where the metadata areas read off of a PV should be attached to).

Signed-off-by: Peter Rajnoha <prajnoha@redhat.com>
---
 lib/metadata/metadata.c |   26 +++++++++++++++++++++-----
 1 files changed, 21 insertions(+), 5 deletions(-)

diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
index ed2084d..f6ea0e5 100644
--- a/lib/metadata/metadata.c
+++ b/lib/metadata/metadata.c
@@ -37,6 +37,7 @@
 static struct physical_volume *_pv_read(struct cmd_context *cmd,
 					struct dm_pool *pvmem,
 					const char *pv_name,
+					struct format_instance *fid,
 					struct dm_list *mdas,
 					uint64_t *label_sector,
 					int warnings, int scan_label_only);
@@ -166,6 +167,7 @@ void add_pvl_to_vgs(struct volume_group *vg, struct pv_list *pvl)
 	dm_list_add(&vg->pvs, &pvl->list);
 	vg->pv_count++;
 	pvl->pv->vg = vg;
+	pvl->pv->fid = vg->fid;
 }
 
 void del_pvl_from_vgs(struct volume_group *vg, struct pv_list *pvl)
@@ -1813,7 +1815,7 @@ static struct physical_volume *_find_pv_by_name(struct cmd_context *cmd,
 	struct physical_volume *pv;
 
 	dm_list_init(&mdas);
-	if (!(pv = _pv_read(cmd, cmd->mem, pv_name, &mdas, NULL, 1, 0))) {
+	if (!(pv = _pv_read(cmd, cmd->mem, pv_name, NULL, &mdas, NULL, 1, 0))) {
 		log_error("Physical volume %s not found", pv_name);
 		return NULL;
 	}
@@ -1822,7 +1824,7 @@ static struct physical_volume *_find_pv_by_name(struct cmd_context *cmd,
 		/* If a PV has no MDAs - need to search all VGs for it */
 		if (!scan_vgs_for_pvs(cmd, 1))
 			return_NULL;
-		if (!(pv = _pv_read(cmd, cmd->mem, pv_name, NULL, NULL, 1, 0))) {
+		if (!(pv = _pv_read(cmd, cmd->mem, pv_name, NULL, NULL, NULL, 1, 0))) {
 			log_error("Physical volume %s not found", pv_name);
 			return NULL;
 		}
@@ -2644,7 +2646,8 @@ static struct volume_group *_vg_read_orphans(struct cmd_context *cmd,
 	}
 
 	dm_list_iterate_items(info, &vginfo->infos) {
-		if (!(pv = _pv_read(cmd, mem, dev_name(info->dev), NULL, NULL, warnings, 0))) {
+		if (!(pv = _pv_read(cmd, mem, dev_name(info->dev), vg->fid,
+				    NULL, NULL, warnings, 0))) {
 			continue;
 		}
 		if (!(pvl = dm_pool_zalloc(mem, sizeof(*pvl)))) {
@@ -3357,13 +3360,14 @@ struct physical_volume *pv_read(struct cmd_context *cmd, const char *pv_name,
 				struct dm_list *mdas, uint64_t *label_sector,
 				int warnings, int scan_label_only)
 {
-	return _pv_read(cmd, cmd->mem, pv_name, mdas, label_sector, warnings, scan_label_only);
+	return _pv_read(cmd, cmd->mem, pv_name, NULL, mdas, label_sector, warnings, scan_label_only);
 }
 
 /* FIXME Use label functions instead of PV functions */
 static struct physical_volume *_pv_read(struct cmd_context *cmd,
 					struct dm_pool *pvmem,
 					const char *pv_name,
+					struct format_instance *fid,
 					struct dm_list *mdas,
 					uint64_t *label_sector,
 					int warnings, int scan_label_only)
@@ -3407,6 +3411,18 @@ static struct physical_volume *_pv_read(struct cmd_context *cmd,
 	if (!alloc_pv_segment_whole_pv(pvmem, pv))
 		goto_bad;
 
+	if (fid)
+		fid_add_mdas(fid, &info->mdas, (const char *) &pv->id, ID_LEN);
+	else {
+		if (!(pv->fid = pv->fmt->ops->create_instance(pv->fmt,
+						(const char *) &pv->id,
+						NULL, NULL, NULL))) {
+			log_error("_pv_read: Couldn't create format instance "
+				  "for PV %s", pv_name);
+			goto bad;
+		}
+	}
+
 	return pv;
 bad:
 	_free_pv(pvmem, pv);
@@ -4213,5 +4229,5 @@ struct physical_volume *pv_by_path(struct cmd_context *cmd, const char *pv_name)
 	struct dm_list mdas;
 
 	dm_list_init(&mdas);
-	return _pv_read(cmd, cmd->mem, pv_name, &mdas, NULL, 1, 0);
+	return _pv_read(cmd, cmd->mem, pv_name, NULL, &mdas, NULL, 1, 0);
 }
-- 
1.7.3.4



^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 05/17] Add attach_existing_mdas parameter to create_instance fn.
  2011-01-24 11:03 [PATCH 00/17] Add interface to support adding and removing metadata areas on demand (v2) Peter Rajnoha
                   ` (3 preceding siblings ...)
  2011-01-24 11:03 ` [PATCH 04/17] Add format_instance support for pv_read Peter Rajnoha
@ 2011-01-24 11:03 ` Peter Rajnoha
  2011-01-25 14:43   ` Petr Rockai
  2011-01-24 11:03 ` [PATCH 06/17] Remove useless mdas parameter from PV read functions Peter Rajnoha
                   ` (12 subsequent siblings)
  17 siblings, 1 reply; 36+ messages in thread
From: Peter Rajnoha @ 2011-01-24 11:03 UTC (permalink / raw)
  To: lvm-devel

If attach_existing_mdas parameter is set, we'll attach any existing
metadata areas found in the cache to the format_instance. Otherwise,
we will only initialise the format_instance and keep the metadata
areas list empty (so we can fill that later if that's needed).

Signed-off-by: Peter Rajnoha <prajnoha@redhat.com>
---
 lib/cache/lvmcache.c          |    2 +-
 lib/format1/format1.c         |    3 ++-
 lib/format_pool/format_pool.c |    3 ++-
 lib/format_text/archive.c     |    2 +-
 lib/format_text/archiver.c    |   10 ++++++----
 lib/format_text/format-text.c |   34 ++++++++++++++++++++--------------
 lib/metadata/metadata.c       |   27 ++++++++++++++++++++-------
 lib/metadata/metadata.h       |    4 +++-
 8 files changed, 55 insertions(+), 30 deletions(-)

diff --git a/lib/cache/lvmcache.c b/lib/cache/lvmcache.c
index 476b176..e3ac4f2 100644
--- a/lib/cache/lvmcache.c
+++ b/lib/cache/lvmcache.c
@@ -654,7 +654,7 @@ struct volume_group *lvmcache_get_vg(const char *vgid, unsigned precommitted)
 
 	if (!(fid = vginfo->fmt->ops->create_instance(vginfo->fmt,
 						      NULL, vginfo->vgname,
-						      vgid, NULL)))
+						      vgid, NULL, 1)))
 		return_NULL;
 
 	/* Build config tree from vgmetadata, if not yet cached */
diff --git a/lib/format1/format1.c b/lib/format1/format1.c
index ff5b0f5..b79bd56 100644
--- a/lib/format1/format1.c
+++ b/lib/format1/format1.c
@@ -525,7 +525,8 @@ static struct format_instance *_format1_create_instance(const struct format_type
 						const char *pvid __attribute__((unused)),
 						const char *vgname __attribute__((unused)),
 						const char *vgid __attribute__((unused)),
-						void *private __attribute__((unused)))
+						void *private __attribute__((unused)),
+						int attach_existing_mdas __attribute((unused)))
 {
 	struct format_instance *fid;
 	struct metadata_area *mda;
diff --git a/lib/format_pool/format_pool.c b/lib/format_pool/format_pool.c
index 814d80c..3ecbfe9 100644
--- a/lib/format_pool/format_pool.c
+++ b/lib/format_pool/format_pool.c
@@ -252,7 +252,8 @@ static struct format_instance *_pool_create_instance(const struct format_type *f
 						const char *pvid __attribute__((unused)),
 						const char *vgname __attribute__((unused)),
 						const char *vgid __attribute__((unused)),
-						void *private __attribute__((unused)))
+						void *private __attribute__((unused)),
+						int attach_existing_mdas __attribute__((unused)))
 {
 	struct format_instance *fid;
 	struct metadata_area *mda;
diff --git a/lib/format_text/archive.c b/lib/format_text/archive.c
index 760153c..8d55988 100644
--- a/lib/format_text/archive.c
+++ b/lib/format_text/archive.c
@@ -309,7 +309,7 @@ static void _display_archive(struct cmd_context *cmd, struct archive_file *af)
 
 	if (!(context = create_text_context(cmd, af->path, NULL)) ||
 	    !(tf = cmd->fmt_backup->ops->create_instance(cmd->fmt_backup, NULL,
-							 NULL, NULL, context))) {
+						NULL, NULL, context, 1))) {
 		log_error("Couldn't create text instance object.");
 		return;
 	}
diff --git a/lib/format_text/archiver.c b/lib/format_text/archiver.c
index b7dcad9..ec65794 100644
--- a/lib/format_text/archiver.c
+++ b/lib/format_text/archiver.c
@@ -278,7 +278,7 @@ struct volume_group *backup_read_vg(struct cmd_context *cmd,
 	if (!(context = create_text_context(cmd, file,
 					    cmd->cmd_line)) ||
 	    !(tf = cmd->fmt_backup->ops->create_instance(cmd->fmt_backup, NULL,
-							 NULL, NULL, context))) {
+						NULL, NULL, context, 1))) {
 		log_error("Couldn't create text format object.");
 		return NULL;
 	}
@@ -299,6 +299,7 @@ int backup_restore_vg(struct cmd_context *cmd, struct volume_group *vg)
 	struct pv_list *pvl;
 	struct physical_volume *pv;
 	struct lvmcache_info *info;
+	struct format_instance *fid;
 
 	/*
 	 * FIXME: Check that the PVs referenced in the backup are
@@ -306,11 +307,12 @@ int backup_restore_vg(struct cmd_context *cmd, struct volume_group *vg)
 	 */
 
 	/* Attempt to write out using currently active format */
-	if (!(vg->fid = cmd->fmt->ops->create_instance(cmd->fmt, NULL,
-						vg->name, NULL, NULL))) {
+	if (!(fid = cmd->fmt->ops->create_instance(cmd->fmt, NULL,
+						vg->name, NULL, NULL, 1))) {
 		log_error("Failed to allocate format instance");
 		return 0;
 	}
+	change_vg_format_instance(vg, fid);
 
 	/*
 	 * Setting vg->old_name to a blank value will explicitly
@@ -398,7 +400,7 @@ int backup_to_file(const char *file, const char *desc, struct volume_group *vg)
 
 	if (!(context = create_text_context(cmd, file, desc)) ||
 	    !(tf = cmd->fmt_backup->ops->create_instance(cmd->fmt_backup, NULL,
-							 NULL, NULL, context))) {
+						NULL, NULL, context, 1))) {
 		log_error("Couldn't create backup object.");
 		return 0;
 	}
diff --git a/lib/format_text/format-text.c b/lib/format_text/format-text.c
index c8c56f7..a2f3d74 100644
--- a/lib/format_text/format-text.c
+++ b/lib/format_text/format-text.c
@@ -41,7 +41,8 @@ static struct format_instance *_text_create_text_instance(const struct format_ty
 							  const char *pvid,
 							  const char *vgname,
 							  const char *vgid,
-							  void *context);
+							  void *context,
+							  int attach_existing_mdas);
 
 struct text_fid_context {
 	char *raw_metadata_buf;
@@ -1090,7 +1091,7 @@ static int _scan_file(const struct format_type *fmt, const char *vgname)
 
 				/* FIXME stat file to see if it's changed */
 				fid = _text_create_text_instance(fmt, NULL, NULL,
-								 NULL, NULL);
+								 NULL, NULL, 1);
 				if ((vg = _vg_read_file_name(fid, scanned_vgname,
 							     path))) {
 					/* FIXME Store creation host in vg */
@@ -1916,7 +1917,8 @@ static int _text_pv_setup(const struct format_type *fmt,
 	return 1;
 }
 
-static int _create_pv_text_instance(struct format_instance *fid, const char *pvid)
+static int _create_pv_text_instance(struct format_instance *fid, const char *pvid,
+				    int attach_existing_mdas)
 {
 	struct text_fid_pv_context *fid_pv_tc;
 	struct lvmcache_info *info;
@@ -1938,7 +1940,7 @@ static int _create_pv_text_instance(struct format_instance *fid, const char *pvi
 		return 0;
 	}
 
-	if ((info = info_from_pvid(pvid, 0)))
+	if (attach_existing_mdas && (info = info_from_pvid(pvid, 0)))
 		fid_add_mdas(fid, &info->mdas, pvid, ID_LEN);
 
 	return 1;
@@ -1946,7 +1948,7 @@ static int _create_pv_text_instance(struct format_instance *fid, const char *pvi
 
 static int _create_vg_text_instance(struct format_instance *fid,
 				    const char *vgname, const char *vgid,
-				    void *context)
+				    void *context, int attach_existing_mdas)
 {
 	struct text_fid_context *fidtc;
 	struct metadata_area *mda;
@@ -1969,6 +1971,15 @@ static int _create_vg_text_instance(struct format_instance *fid,
 	fidtc->raw_metadata_buf = NULL;
 	fid->private = (void *) fidtc;
 
+	if (!(fid->metadata_areas_index = dm_hash_create(128))) {
+		log_error("Couldn't create metadata index for format "
+			  "instance of VG %s.", vgname);
+		return 0;
+	}
+
+	if (!attach_existing_mdas)
+		goto out;
+
 	if (!vgname) {
 		if (!(mda = dm_pool_zalloc(fid->fmt->cmd->mem, sizeof(*mda))))
 			return_0;
@@ -1977,12 +1988,6 @@ static int _create_vg_text_instance(struct format_instance *fid,
 		mda->status = 0;
 		fid_add_mda(fid, mda, NULL, 0, 0);
 	} else {
-		if (!(fid->metadata_areas_index = dm_hash_create(128))) {
-			log_error("Couldn't create metadata index for format "
-				  "instance of VG %s.", vgname);
-			return 0;
-		}
-
 		dir_list = &((struct mda_lists *) fid->fmt->private)->dirs;
 
 		dm_list_iterate_items(dl, dir_list) {
@@ -2044,7 +2049,8 @@ static struct format_instance *_text_create_text_instance(const struct format_ty
 							  const char *pvid,
 							  const char *vgname,
 							  const char *vgid,
-							  void *context)
+							  void *context,
+							  int attach_existing_mdas)
 {
 	struct format_instance *fid;
 	int r;
@@ -2065,8 +2071,8 @@ static struct format_instance *_text_create_text_instance(const struct format_ty
 	dm_list_init(&fid->metadata_areas_in_use);
 	dm_list_init(&fid->metadata_areas_ignored);
 
-	r = pvid ? _create_pv_text_instance(fid, pvid) :
-		   _create_vg_text_instance(fid, vgname, vgid, context);
+	r = pvid ? _create_pv_text_instance(fid, pvid, attach_existing_mdas) :
+		   _create_vg_text_instance(fid, vgname, vgid, context, attach_existing_mdas);
 
 	if (r)
 		return fid;
diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
index f6ea0e5..dccc3af 100644
--- a/lib/metadata/metadata.c
+++ b/lib/metadata/metadata.c
@@ -977,7 +977,7 @@ struct volume_group *vg_create(struct cmd_context *cmd, const char *vg_name)
 	dm_list_init(&vg->removed_pvs);
 
 	if (!(vg->fid = cmd->fmt->ops->create_instance(cmd->fmt, NULL,
-						vg_name, NULL, NULL))) {
+					vg_name, NULL, NULL, 1))) {
 		log_error("Failed to create format instance");
 		goto bad;
 	}
@@ -1642,7 +1642,7 @@ struct physical_volume *pv_create(const struct cmd_context *cmd,
 	}
 
 	if (!(pv->fid = fmt->ops->create_instance(fmt, (const char *) &pv->id,
-						  NULL, NULL, NULL))) {
+						  NULL, NULL, NULL, 0))) {
 		log_error("Couldn't create format instance for PV %s.", pv_dev_name(pv));
 		goto bad;
 	}
@@ -2637,10 +2637,13 @@ static struct volume_group *_vg_read_orphans(struct cmd_context *cmd,
 		goto bad;
 	}
 
-	/* create format instance with appropriate metadata area */
+	/*
+	 * Create an empty format instance. Metadata areas
+	 * will be attached using consequent PV read calls.
+	 */
 	if (!(vg->fid = vginfo->fmt->ops->create_instance(vginfo->fmt, NULL,
 							  orphan_vgname, NULL,
-							  NULL))) {
+							  NULL, 0))) {
 		log_error("Failed to create format instance");
 		goto bad;
 	}
@@ -2818,7 +2821,7 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
 		use_precommitted = 0;
 
 	/* create format instance with appropriate metadata area */
-	if (!(fid = fmt->ops->create_instance(fmt, NULL, vgname, vgid, NULL))) {
+	if (!(fid = fmt->ops->create_instance(fmt, NULL, vgname, vgid, NULL, 1))) {
 		log_error("Failed to create format instance");
 		return NULL;
 	}
@@ -2973,7 +2976,7 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
 			use_precommitted = 0;
 
 		/* create format instance with appropriate metadata area */
-		if (!(fid = fmt->ops->create_instance(fmt, NULL, vgname, vgid, NULL))) {
+		if (!(fid = fmt->ops->create_instance(fmt, NULL, vgname, vgid, NULL, 1))) {
 			log_error("Failed to create format instance");
 			return NULL;
 		}
@@ -3416,7 +3419,7 @@ static struct physical_volume *_pv_read(struct cmd_context *cmd,
 	else {
 		if (!(pv->fid = pv->fmt->ops->create_instance(pv->fmt,
 						(const char *) &pv->id,
-						NULL, NULL, NULL))) {
+						NULL, NULL, NULL, 1))) {
 			log_error("_pv_read: Couldn't create format instance "
 				  "for PV %s", pv_name);
 			goto bad;
@@ -3936,6 +3939,16 @@ uint32_t vg_lock_newname(struct cmd_context *cmd, const char *vgname)
 	return FAILED_EXIST;
 }
 
+void change_vg_format_instance(struct volume_group *vg,
+			       struct format_instance *fid)
+{
+	struct pv_list *pvl;
+
+	vg->fid = fid;
+	dm_list_iterate_items(pvl, &vg->pvs)
+		pvl->pv->fid = fid;
+}
+
 static int _convert_key_to_string(const char *key, size_t key_len,
 				  unsigned subkey, char *buf, size_t buf_len)
 {
diff --git a/lib/metadata/metadata.h b/lib/metadata/metadata.h
index 0fbc954..bd638b5 100644
--- a/lib/metadata/metadata.h
+++ b/lib/metadata/metadata.h
@@ -191,6 +191,7 @@ struct metadata_area *mda_copy(struct dm_pool *mem,
 unsigned mda_is_ignored(struct metadata_area *mda);
 void mda_set_ignored(struct metadata_area *mda, unsigned ignored);
 unsigned mda_locns_match(struct metadata_area *mda1, struct metadata_area *mda2);
+void change_vg_format_instance(struct volume_group *vg, struct format_instance *fid);
 int fid_add_mda(struct format_instance *fid, struct metadata_area *mda,
 		 const char *key, size_t key_len, const unsigned subkey);
 int fid_add_mdas(struct format_instance *fid, struct dm_list *mdas,
@@ -289,7 +290,8 @@ struct format_handler {
 						    const char *pvid,
 						    const char *vgname,
 						    const char *vgid,
-						    void *context);
+						    void *context,
+						    int attach_existing_mdas);
 
 	/*
 	 * Destructor for format instance
-- 
1.7.3.4



^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 06/17] Remove useless mdas parameter from PV read functions.
  2011-01-24 11:03 [PATCH 00/17] Add interface to support adding and removing metadata areas on demand (v2) Peter Rajnoha
                   ` (4 preceding siblings ...)
  2011-01-24 11:03 ` [PATCH 05/17] Add attach_existing_mdas parameter to create_instance fn Peter Rajnoha
@ 2011-01-24 11:03 ` Peter Rajnoha
  2011-01-25 14:44   ` Petr Rockai
  2011-01-24 11:03 ` [PATCH 07/17] Add pv_add_metadata_area fn to support adding metadata areas on demand Peter Rajnoha
                   ` (11 subsequent siblings)
  17 siblings, 1 reply; 36+ messages in thread
From: Peter Rajnoha @ 2011-01-24 11:03 UTC (permalink / raw)
  To: lvm-devel

...metadata areas are now stored within pv->fid.

Signed-off-by: Peter Rajnoha <prajnoha@redhat.com>
---
 lib/format1/format1.c            |    3 +--
 lib/format_pool/format_pool.c    |    1 -
 lib/format_text/format-text.c    |   15 +--------------
 lib/metadata/metadata-exported.h |    4 ++--
 lib/metadata/metadata.c          |   37 +++++++++++++------------------------
 lib/metadata/metadata.h          |    3 +--
 tools/pvremove.c                 |   10 ++++------
 tools/pvresize.c                 |    8 +++-----
 tools/toollib.c                  |   14 ++++++--------
 9 files changed, 31 insertions(+), 64 deletions(-)

diff --git a/lib/format1/format1.c b/lib/format1/format1.c
index b79bd56..4f66cdc 100644
--- a/lib/format1/format1.c
+++ b/lib/format1/format1.c
@@ -331,8 +331,7 @@ static int _format1_vg_write(struct format_instance *fid, struct volume_group *v
 }
 
 static int _format1_pv_read(const struct format_type *fmt, const char *pv_name,
-		    struct physical_volume *pv, struct dm_list *mdas __attribute__((unused)),
-		    int scan_label_only __attribute__((unused)))
+		    struct physical_volume *pv, int scan_label_only __attribute__((unused)))
 {
 	struct dm_pool *mem = dm_pool_create("lvm1 pv_read", 1024);
 	struct disk_list *dl;
diff --git a/lib/format_pool/format_pool.c b/lib/format_pool/format_pool.c
index 3ecbfe9..24ccfc2 100644
--- a/lib/format_pool/format_pool.c
+++ b/lib/format_pool/format_pool.c
@@ -206,7 +206,6 @@ static int _pool_pv_setup(const struct format_type *fmt __attribute__((unused)),
 
 static int _pool_pv_read(const struct format_type *fmt, const char *pv_name,
 			 struct physical_volume *pv,
-			 struct dm_list *mdas __attribute__((unused)),
 			 int scan_label_only __attribute__((unused)))
 {
 	struct dm_pool *mem = dm_pool_create("pool pv_read", 1024);
diff --git a/lib/format_text/format-text.c b/lib/format_text/format-text.c
index a2f3d74..5dfe0b8 100644
--- a/lib/format_text/format-text.c
+++ b/lib/format_text/format-text.c
@@ -1669,10 +1669,8 @@ static uint64_t _metadata_locn_offset_raw(void *metadata_locn)
 }
 
 static int _text_pv_read(const struct format_type *fmt, const char *pv_name,
-		    struct physical_volume *pv, struct dm_list *mdas,
-		    int scan_label_only)
+		    struct physical_volume *pv, int scan_label_only)
 {
-	struct metadata_area *mda, *mda_new;
 	struct label *label;
 	struct device *dev;
 	struct lvmcache_info *info;
@@ -1687,17 +1685,6 @@ static int _text_pv_read(const struct format_type *fmt, const char *pv_name,
 	if (!_populate_pv_fields(info, pv, scan_label_only))
 		return 0;
 
-	if (!mdas)
-		return 1;
-
-	/* Add copy of mdas to supplied list */
-	dm_list_iterate_items(mda, &info->mdas) {
-		mda_new = mda_copy(fmt->cmd->mem, mda);
-		if (!mda_new)
-			return 0;
-		dm_list_add(mdas, &mda_new->list);
-	}
-
 	return 1;
 }
 
diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index d8247dd..da62764 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -340,8 +340,8 @@ int vg_revert(struct volume_group *vg);
 struct volume_group *vg_read_internal(struct cmd_context *cmd, const char *vg_name,
 			     const char *vgid, int warnings, int *consistent);
 struct physical_volume *pv_read(struct cmd_context *cmd, const char *pv_name,
-				struct dm_list *mdas, uint64_t *label_sector,
-				int warnings, int scan_label_only);
+				uint64_t *label_sector, int warnings,
+				int scan_label_only);
 struct dm_list *get_pvs(struct cmd_context *cmd);
 
 /*
diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
index dccc3af..591f7b5 100644
--- a/lib/metadata/metadata.c
+++ b/lib/metadata/metadata.c
@@ -38,7 +38,6 @@ static struct physical_volume *_pv_read(struct cmd_context *cmd,
 					struct dm_pool *pvmem,
 					const char *pv_name,
 					struct format_instance *fid,
-					struct dm_list *mdas,
 					uint64_t *label_sector,
 					int warnings, int scan_label_only);
 
@@ -1330,14 +1329,11 @@ static int pvcreate_check(struct cmd_context *cmd, const char *name,
 {
 	struct physical_volume *pv;
 	struct device *dev;
-	struct dm_list mdas;
-
-	dm_list_init(&mdas);
 
 	/* FIXME Check partition type is LVM unless --force is given */
 
 	/* Is there a pv here already? */
-	pv = pv_read(cmd, name, &mdas, NULL, 0, 0);
+	pv = pv_read(cmd, name, NULL, 0, 0);
 
 	/*
 	 * If a PV has no MDAs it may appear to be an orphan until the
@@ -1345,10 +1341,10 @@ static int pvcreate_check(struct cmd_context *cmd, const char *name,
 	 * this means checking every VG by scanning every PV on the
 	 * system.
 	 */
-	if (pv && is_orphan(pv) && mdas_empty_or_ignored(&mdas)) {
+	if (pv && is_orphan(pv) && !dm_list_size(&pv->fid->metadata_areas_in_use)) {
 		if (!scan_vgs_for_pvs(cmd, 0))
 			return_0;
-		pv = pv_read(cmd, name, NULL, NULL, 0, 0);
+		pv = pv_read(cmd, name, NULL, 0, 0);
 	}
 
 	/* Allow partial & exported VGs to be destroyed. */
@@ -1811,20 +1807,18 @@ struct physical_volume *find_pv_by_name(struct cmd_context *cmd,
 static struct physical_volume *_find_pv_by_name(struct cmd_context *cmd,
 			 			const char *pv_name)
 {
-	struct dm_list mdas;
 	struct physical_volume *pv;
 
-	dm_list_init(&mdas);
-	if (!(pv = _pv_read(cmd, cmd->mem, pv_name, NULL, &mdas, NULL, 1, 0))) {
+	if (!(pv = _pv_read(cmd, cmd->mem, pv_name, NULL, NULL, 1, 0))) {
 		log_error("Physical volume %s not found", pv_name);
 		return NULL;
 	}
 
-	if (is_orphan_vg(pv->vg_name) && mdas_empty_or_ignored(&mdas)) {
+	if (is_orphan_vg(pv->vg_name) && !dm_list_size(&pv->fid->metadata_areas_in_use)) {
 		/* If a PV has no MDAs - need to search all VGs for it */
 		if (!scan_vgs_for_pvs(cmd, 1))
 			return_NULL;
-		if (!(pv = _pv_read(cmd, cmd->mem, pv_name, NULL, NULL, NULL, 1, 0))) {
+		if (!(pv = _pv_read(cmd, cmd->mem, pv_name, NULL, NULL, 1, 0))) {
 			log_error("Physical volume %s not found", pv_name);
 			return NULL;
 		}
@@ -2649,8 +2643,8 @@ static struct volume_group *_vg_read_orphans(struct cmd_context *cmd,
 	}
 
 	dm_list_iterate_items(info, &vginfo->infos) {
-		if (!(pv = _pv_read(cmd, mem, dev_name(info->dev), vg->fid,
-				    NULL, NULL, warnings, 0))) {
+		if (!(pv = _pv_read(cmd, mem, dev_name(info->dev),
+				    vg->fid, NULL, warnings, 0))) {
 			continue;
 		}
 		if (!(pvl = dm_pool_zalloc(mem, sizeof(*pvl)))) {
@@ -3360,10 +3354,10 @@ const char *find_vgname_from_pvname(struct cmd_context *cmd,
  *   FIXME - liblvm todo - make into function that returns handle
  */
 struct physical_volume *pv_read(struct cmd_context *cmd, const char *pv_name,
-				struct dm_list *mdas, uint64_t *label_sector,
-				int warnings, int scan_label_only)
+				uint64_t *label_sector, int warnings,
+				int scan_label_only)
 {
-	return _pv_read(cmd, cmd->mem, pv_name, NULL, mdas, label_sector, warnings, scan_label_only);
+	return _pv_read(cmd, cmd->mem, pv_name, NULL, label_sector, warnings, scan_label_only);
 }
 
 /* FIXME Use label functions instead of PV functions */
@@ -3371,7 +3365,6 @@ static struct physical_volume *_pv_read(struct cmd_context *cmd,
 					struct dm_pool *pvmem,
 					const char *pv_name,
 					struct format_instance *fid,
-					struct dm_list *mdas,
 					uint64_t *label_sector,
 					int warnings, int scan_label_only)
 {
@@ -3401,8 +3394,7 @@ static struct physical_volume *_pv_read(struct cmd_context *cmd,
 	}
 
 	/* FIXME Move more common code up here */
-	if (!(info->fmt->ops->pv_read(info->fmt, pv_name, pv, mdas,
-	      scan_label_only))) {
+	if (!(info->fmt->ops->pv_read(info->fmt, pv_name, pv, scan_label_only))) {
 		log_error("Failed to read existing physical volume '%s'",
 			  pv_name);
 		goto bad;
@@ -4239,8 +4231,5 @@ char *tags_format_and_copy(struct dm_pool *mem, const struct dm_list *tags)
  */
 struct physical_volume *pv_by_path(struct cmd_context *cmd, const char *pv_name)
 {
-	struct dm_list mdas;
-
-	dm_list_init(&mdas);
-	return _pv_read(cmd, cmd->mem, pv_name, NULL, &mdas, NULL, 1, 0);
+	return _pv_read(cmd, cmd->mem, pv_name, NULL, NULL, 1, 0);
 }
diff --git a/lib/metadata/metadata.h b/lib/metadata/metadata.h
index bd638b5..7ebf85c 100644
--- a/lib/metadata/metadata.h
+++ b/lib/metadata/metadata.h
@@ -241,8 +241,7 @@ struct format_handler {
 	 * Return PV with given path.
 	 */
 	int (*pv_read) (const struct format_type * fmt, const char *pv_name,
-			struct physical_volume * pv, struct dm_list *mdas,
-			int scan_label_only);
+			struct physical_volume * pv, int scan_label_only);
 
 	/*
 	 * Tweak an already filled out a pv ready for importing into a
diff --git a/tools/pvremove.c b/tools/pvremove.c
index a8717e0..ace3c1d 100644
--- a/tools/pvremove.c
+++ b/tools/pvremove.c
@@ -25,15 +25,12 @@ const char _really_wipe[] =
 static int pvremove_check(struct cmd_context *cmd, const char *name)
 {
 	struct physical_volume *pv;
-	struct dm_list mdas;
-
-	dm_list_init(&mdas);
 
 	/* FIXME Check partition type is LVM unless --force is given */
 
 	/* Is there a pv here already? */
 	/* If not, this is an error unless you used -f. */
-	if (!(pv = pv_read(cmd, name, &mdas, NULL, 1, 0))) {
+	if (!(pv = pv_read(cmd, name, NULL, 1, 0))) {
 		if (arg_count(cmd, force_ARG))
 			return 1;
 		log_error("Physical Volume %s not found", name);
@@ -47,13 +44,14 @@ static int pvremove_check(struct cmd_context *cmd, const char *name)
 	 * means checking every VG by scanning every
 	 * PV on the system.
 	 */
-	if (is_orphan(pv) && !dm_list_size(&mdas)) {
+	if (is_orphan(pv) && !dm_list_size(&pv->fid->metadata_areas_in_use) &&
+	    !dm_list_size(&pv->fid->metadata_areas_ignored)) {
 		if (!scan_vgs_for_pvs(cmd, 0)) {
 			log_error("Rescan for PVs without metadata areas "
 				  "failed.");
 			return 0;
 		}
-		if (!(pv = pv_read(cmd, name, NULL, NULL, 1, 0))) {
+		if (!(pv = pv_read(cmd, name, NULL, 1, 0))) {
 			log_error("Failed to read physical volume %s", name);
 			return 0;
 		}
diff --git a/tools/pvresize.c b/tools/pvresize.c
index 8582ef4..4f1d610 100644
--- a/tools/pvresize.c
+++ b/tools/pvresize.c
@@ -32,28 +32,26 @@ static int _pv_resize_single(struct cmd_context *cmd,
 	uint64_t size = 0;
 	uint32_t new_pe_count = 0;
 	int r = 0;
-	struct dm_list mdas;
 	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;
 
-	dm_list_init(&mdas);
-
 	if (is_orphan_vg(vg_name)) {
 		if (!lock_vol(cmd, vg_name, LCK_VG_WRITE)) {
 			log_error("Can't get lock for orphans");
 			return 0;
 		}
 
-		if (!(pv = pv_read(cmd, pv_name, &mdas, NULL, 1, 0))) {
+		if (!(pv = pv_read(cmd, pv_name, NULL, 1, 0))) {
 			unlock_vg(cmd, vg_name);
 			log_error("Unable to read PV \"%s\"", pv_name);
 			return 0;
 		}
 
-		mda_count = dm_list_size(&mdas);
+		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);
 
diff --git a/tools/toollib.c b/tools/toollib.c
index f76aacd..48f8ed5 100644
--- a/tools/toollib.c
+++ b/tools/toollib.c
@@ -640,7 +640,7 @@ static int _process_all_devs(struct cmd_context *cmd, void *handle,
 	}
 
 	while ((dev = dev_iter_get(iter))) {
-		if (!(pv = pv_read(cmd, dev_name(dev), NULL, NULL, 0, 0))) {
+		if (!(pv = pv_read(cmd, dev_name(dev), NULL, 0, 0))) {
 			memset(&pv_dummy, 0, sizeof(pv_dummy));
 			dm_list_init(&pv_dummy.tags);
 			dm_list_init(&pv_dummy.segments);
@@ -682,7 +682,6 @@ int process_each_pv(struct cmd_context *cmd, int argc, char **argv,
 	struct str_list *sll;
 	char *at_sign, *tagname;
 	int scanned = 0;
-	struct dm_list mdas;
 
 	dm_list_init(&tags);
 
@@ -724,10 +723,8 @@ int process_each_pv(struct cmd_context *cmd, int argc, char **argv,
 				}
 				pv = pvl->pv;
 			} else {
-
-				dm_list_init(&mdas);
-				if (!(pv = pv_read(cmd, argv[opt], &mdas,
-						   NULL, 1, scan_label_only))) {
+				if (!(pv = pv_read(cmd, argv[opt], NULL,
+						   1, scan_label_only))) {
 					log_error("Failed to read physical "
 						  "volume \"%s\"", argv[opt]);
 					ret_max = ECMD_FAILED;
@@ -742,7 +739,8 @@ int process_each_pv(struct cmd_context *cmd, int argc, char **argv,
 				 * PV on the system.
 				 */
 				if (!scanned && is_orphan(pv) &&
-				    !dm_list_size(&mdas)) {
+				    !dm_list_size(&pv->fid->metadata_areas_in_use) &&
+				    !dm_list_size(&pv->fid->metadata_areas_ignored)) {
 					if (!scan_label_only &&
 					    !scan_vgs_for_pvs(cmd, 1)) {
 						stack;
@@ -751,7 +749,7 @@ int process_each_pv(struct cmd_context *cmd, int argc, char **argv,
 					}
 					scanned = 1;
 					if (!(pv = pv_read(cmd, argv[opt],
-							   NULL, NULL, 1,
+							   NULL, 1,
 							   scan_label_only))) {
 						log_error("Failed to read "
 							  "physical volume "
-- 
1.7.3.4



^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 07/17] Add pv_add_metadata_area fn to support adding metadata areas on demand.
  2011-01-24 11:03 [PATCH 00/17] Add interface to support adding and removing metadata areas on demand (v2) Peter Rajnoha
                   ` (5 preceding siblings ...)
  2011-01-24 11:03 ` [PATCH 06/17] Remove useless mdas parameter from PV read functions Peter Rajnoha
@ 2011-01-24 11:03 ` Peter Rajnoha
  2011-01-25 14:48   ` Petr Rockai
  2011-01-24 11:03 ` [PATCH 08/17] Add pv_remove_metadata_area fn to support removing " Peter Rajnoha
                   ` (10 subsequent siblings)
  17 siblings, 1 reply; 36+ messages in thread
From: Peter Rajnoha @ 2011-01-24 11:03 UTC (permalink / raw)
  To: lvm-devel

My previous version of the patch used the cache and that was not quite
a happy solution (but it was easy to use :)) since any revert would
be quite complex (or we'd need to destroy the cache item and rescan).

Now, we can use the format_instance to store metadata areas. If anything
goes wrong, we can just throw the instance away and create a new one to
work with (so we don't need to revert the cache or rescan).

Signed-off-by: Peter Rajnoha <prajnoha@redhat.com>
---
 lib/format_text/format-text.c |  245 +++++++++++++++++++++++++++++++++++++++++
 lib/format_text/format-text.h |    5 +
 lib/metadata/metadata.h       |   10 ++
 3 files changed, 260 insertions(+), 0 deletions(-)

diff --git a/lib/format_text/format-text.c b/lib/format_text/format-text.c
index 5dfe0b8..cf18f25 100644
--- a/lib/format_text/format-text.c
+++ b/lib/format_text/format-text.c
@@ -2031,6 +2031,250 @@ static int _create_vg_text_instance(struct format_instance *fid,
 	return 1;
 }
 
+int add_metadata_area_to_pv(struct physical_volume *pv,
+			    unsigned mda_index,
+			    uint64_t mda_start,
+			    uint64_t mda_size,
+			    unsigned mda_ignored)
+{
+	struct metadata_area *mda;
+	struct mda_context *mdac;
+	struct mda_lists *mda_lists = (struct mda_lists *) pv->fmt->private;
+
+	if (mda_index >= FMT_TEXT_MAX_MDAS_PER_PV) {
+		log_error(INTERNAL_ERROR "can't add metadata area with "
+					 "index %u to PV %s. Metadata "
+					 "layout not supported by %s format.",
+					  mda_index, dev_name(pv->dev),
+					  pv->fmt->name);
+	}
+
+	if (!(mda = dm_malloc(sizeof(struct metadata_area)))) {
+		log_error("struct metadata_area allocation failed");
+		return 0;
+	}
+
+	if (!(mdac = dm_malloc(sizeof(struct mda_context)))) {
+		log_error("struct mda_context allocation failed");
+		dm_free(mda);
+		return 0;
+	}
+
+	mda->ops = mda_lists->raw_ops;
+	mda->metadata_locn = mdac;
+	mda->status = 0;
+
+	mdac->area.dev = pv->dev;
+	mdac->area.start = mda_start;
+	mdac->area.size = mda_size;
+	mdac->free_sectors = UINT64_C(0);
+	memset(&mdac->rlocn, 0, sizeof(mdac->rlocn));
+	mda_set_ignored(mda, mda_ignored);
+
+	fid_add_mda(pv->fid ? pv->fid : pv->vg->fid, mda,
+		    (char *) &pv->id, ID_LEN, mda_index);
+
+	return 1;
+}
+
+static int _text_pv_add_metadata_area(const struct format_type *fmt,
+				      struct physical_volume *pv,
+				      int pe_start_locked,
+				      unsigned mda_index,
+				      uint64_t mda_size,
+				      unsigned mda_ignored)
+{
+	struct format_instance *fid = pv->fid;
+	const char *pvid = (char *) &pv->id;
+	uint64_t pe_start, pe_end;
+	uint64_t alignment, alignment_offset;
+	uint64_t disk_size;
+	uint64_t mda_start;
+	uint64_t adjustment, limit;
+	uint64_t wipe_size = 8 << SECTOR_SHIFT;
+	size_t page_size = lvm_getpagesize();
+	struct metadata_area *mda;
+	struct mda_context *mdac;
+
+	if (mda_index >= FMT_TEXT_MAX_MDAS_PER_PV) {
+		log_error(INTERNAL_ERROR "invalid index of value %u used "
+			      "while trying to add metadata area on PV %s. "
+			      "Metadata layout not supported by %s format.",
+			       mda_index, pv_dev_name(pv), fmt->name);
+		return 0;
+	}
+
+	pe_start = pv->pe_start << SECTOR_SHIFT;
+	alignment = pv->pe_align << SECTOR_SHIFT;
+	alignment_offset = pv->pe_align_offset << SECTOR_SHIFT;
+	disk_size = pv->size << SECTOR_SHIFT;
+	mda_size = mda_size << SECTOR_SHIFT;
+
+	if (fid_get_mda_indexed(fid, pvid, ID_LEN, mda_index)) {
+		log_error(INTERNAL_ERROR "metadata area with index %u already "
+			"exists on PV %s.", mda_index, pv_dev_name(pv));
+		return 0;
+	}
+
+	/* First metadata area@the start of the device. */
+	if (mda_index == 0) {
+		/*
+		 * Try to fit MDA0 end within given pe_start limit if its value
+		 * is locked. If it's not locked, count with any existing MDA1.
+		 * If there's no MDA1, just use disk size as the limit.
+		 */
+		if (pe_start_locked)
+			limit = pe_start;
+		else if ((mda = fid_get_mda_indexed(fid, pvid, ID_LEN, 1)) &&
+			 (mdac = mda->metadata_locn))
+			limit = mdac->area.start;
+		else
+			limit = disk_size;
+
+		if (limit > disk_size)
+			goto bad;
+
+		mda_start = LABEL_SCAN_SIZE;
+
+		/* Align MDA0 start with page size if possible. */
+		if (limit - mda_start >= MDA_SIZE_MIN) {
+			if ((adjustment = mda_start % page_size))
+				mda_start += (page_size - adjustment);
+		}
+
+		/* Align MDA0 end position with given alignment if possible. */
+		if (alignment) {
+			if ((adjustment = (mda_start + mda_size) % alignment)) {
+				mda_size += (alignment - adjustment);
+				if (mda_start + mda_size > limit)
+					mda_size -= (alignment - adjustment);
+			}
+		}
+
+		/* Align MDA0 end position with given alignment offset if possible. */
+		if (alignment_offset &&
+		    (((mda_start + mda_size) % alignment) == 0)) {
+			mda_size += alignment_offset;
+			if (mda_start + mda_size > limit)
+				mda_size -= alignment_offset;
+		}
+
+		if (mda_start + mda_size > limit) {
+			log_warn("WARNING: metadata area size outreaches "
+				 "a limit on PV %s specified by its %s. "
+				 "Trying to adjust metadata area size.",
+				  pv_dev_name(pv),
+				  pe_start_locked ? "PE start" : "disk size");
+
+			/*
+			 * Try to decrease the MDA0 size with twice the
+			 * alignment and then align with given alignment.
+			 * If pe_start is locked, skip this type of
+			 * alignment since it would be useless.
+			 * Check first whether we can apply that!
+			 */
+			if (!pe_start_locked &&
+			    ((limit - mda_start) > alignment * 2)) {
+				mda_size = limit - mda_start - alignment * 2;
+
+				if ((adjustment = (mda_start + mda_size) % alignment))
+					mda_size += (alignment - adjustment);
+
+				/* Still too much? Then there's nothing else to do. */
+				if (mda_start + mda_size > limit)
+					goto bad;
+			}
+			/* Otherwise, give up and take any usable space. */
+			/* FIXME: We should probably check for some minimum MDA size here. */
+			else
+				mda_size = limit - mda_start;
+		}
+
+		/*
+		 * If PV's pe_start is not locked, update pe_start value with the
+		 * start of the area that follows the MDA0 we've just calculated.
+		 */
+		if (!pe_start_locked) {
+			pe_start = mda_start + mda_size;
+			pv->pe_start = pe_start >> SECTOR_SHIFT;
+		}
+	}
+	/* Second metadata area at the end of the device. */
+	else {
+		/*
+		 * Try to fit MDA1 start within given pe_end or pe_start limit
+		 * if it's locked. If pe_start and pe_end are not defined yet,
+		 * count with any existing MDA0 and pe_start. If MDA0 does not
+		 * exist, just use LABEL_SCAN_SIZE.
+		 */
+		pe_end = pv->pe_count ? (pv->pe_start +
+					 pv->pe_count * pv->pe_size - 1) << SECTOR_SHIFT
+				      : 0;
+		if (pe_start_locked)
+			limit = pe_end ? pe_end : pe_start;
+		else if (pe_start)
+			limit = pe_start;
+		/*
+		 * Normally MDA0's start + size should be pe_start.
+		 * The statemet here is probably useless since the
+		 * situation is covered by previous statement.
+		 */
+		else if ((mda = fid_get_mda_indexed(fid, pvid, ID_LEN, 0)) &&
+			 (mdac = mda->metadata_locn))
+			limit = mdac->area.start + mdac->area.size;
+		else
+			limit = LABEL_SCAN_SIZE;
+
+		if (limit > disk_size || mda_size > disk_size)
+			goto bad;
+
+		mda_start = disk_size - mda_size;
+
+		if (alignment) {
+			adjustment = mda_start % alignment;
+			if (adjustment)
+				mda_size += adjustment;
+		}
+
+		if (disk_size - mda_size < limit)
+			mda_size = disk_size - limit;
+
+		/*
+		 * If PV's pe_end not set yet, set it to the end of the
+		 * area that precedes the MDA1 we've just calculated.
+		 * FIXME: do we need to set this? Isn't it always set before?
+		 */
+		/*if (!pe_end) {
+			pe_end = mda_start;
+			pv->pe_end = pe_end >> SECTOR_SHIFT;
+		}*/
+	}
+
+	if (mda_size) {
+		/* Wipe metadata area with zeroes. */
+		if (!dev_set((struct device *) pv->dev, mda_start,
+			(size_t) (mda_size > wipe_size ? : mda_size), 0)) {
+				log_error("Failed to wipe new metadata area "
+					  "at the %s of the %s",
+					   mda_index ? "end" : "start",
+					   pv_dev_name(pv));
+				return 0;
+		}
+
+		/* Finally, add new metadata area to PV's format instance. */
+		if (!add_metadata_area_to_pv(pv, mda_index, mda_start,
+					     mda_size, mda_ignored))
+			return_0;
+	}
+
+	return 1;
+
+bad:
+	log_error("Not enough space available for metadata area "
+		  "with index %u on PV %s.", mda_index, pv_dev_name(pv));
+	return 0;
+}
+
 /* 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 char *pvid,
@@ -2111,6 +2355,7 @@ static struct format_handler _text_handler = {
 	.scan = _text_scan,
 	.pv_read = _text_pv_read,
 	.pv_setup = _text_pv_setup,
+	.pv_add_metadata_area = _text_pv_add_metadata_area,
 	.pv_write = _text_pv_write,
 	.vg_setup = _text_vg_setup,
 	.lv_setup = _text_lv_setup,
diff --git a/lib/format_text/format-text.h b/lib/format_text/format-text.h
index f3cf4f5..f65be74 100644
--- a/lib/format_text/format-text.h
+++ b/lib/format_text/format-text.h
@@ -56,6 +56,11 @@ int add_da(struct dm_pool *mem, struct dm_list *das,
 	   uint64_t start, uint64_t size);
 void del_das(struct dm_list *das);
 
+int add_metadata_area_to_pv(struct physical_volume *pv,
+			    unsigned mda_index,
+			    uint64_t mda_start,
+			    uint64_t mda_size,
+			    unsigned mda_ignored);
 int add_mda(const struct format_type *fmt, struct dm_pool *mem, struct dm_list *mdas,
 	    struct device *dev, uint64_t start, uint64_t size, unsigned ignored);
 void del_mdas(struct dm_list *mdas);
diff --git a/lib/metadata/metadata.h b/lib/metadata/metadata.h
index 7ebf85c..0da8b3d 100644
--- a/lib/metadata/metadata.h
+++ b/lib/metadata/metadata.h
@@ -256,6 +256,16 @@ struct format_handler {
 			 struct physical_volume * pv, struct volume_group * vg);
 
 	/*
+	 * Add metadata area to a PV. Changes will take effect on pv_write.
+	 */
+	int (*pv_add_metadata_area) (const struct format_type * fmt,
+				     struct physical_volume * pv,
+				     int pe_start_locked,
+				     unsigned metadata_index,
+				     uint64_t metadata_size,
+				     unsigned metadata_ignored);
+
+	/*
 	 * 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
 	 */
-- 
1.7.3.4



^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 08/17] Add pv_remove_metadata_area fn to support removing metadata areas on demand.
  2011-01-24 11:03 [PATCH 00/17] Add interface to support adding and removing metadata areas on demand (v2) Peter Rajnoha
                   ` (6 preceding siblings ...)
  2011-01-24 11:03 ` [PATCH 07/17] Add pv_add_metadata_area fn to support adding metadata areas on demand Peter Rajnoha
@ 2011-01-24 11:03 ` Peter Rajnoha
  2011-01-28 15:31   ` Petr Rockai
  2011-01-24 11:04 ` [PATCH 09/17] Add pv_initialise fn to format_handler interface Peter Rajnoha
                   ` (9 subsequent siblings)
  17 siblings, 1 reply; 36+ messages in thread
From: Peter Rajnoha @ 2011-01-24 11:03 UTC (permalink / raw)
  To: lvm-devel

The same as for pv_add_metadata_area, but removing...

Signed-off-by: Peter Rajnoha <prajnoha@redhat.com>
---
 lib/format_text/format-text.c |   24 ++++++++++++++++++++++++
 lib/format_text/format-text.h |    2 ++
 lib/metadata/metadata.h       |    7 +++++++
 3 files changed, 33 insertions(+), 0 deletions(-)

diff --git a/lib/format_text/format-text.c b/lib/format_text/format-text.c
index cf18f25..99f691f 100644
--- a/lib/format_text/format-text.c
+++ b/lib/format_text/format-text.c
@@ -2275,6 +2275,29 @@ bad:
 	return 0;
 }
 
+int remove_metadata_area_from_pv(struct physical_volume *pv,
+				 unsigned mda_index)
+{
+	if (mda_index >= FMT_TEXT_MAX_MDAS_PER_PV) {
+		log_error(INTERNAL_ERROR "can't remove metadata area with "
+					 "index %u from PV %s. Metadata "
+					 "layou not supported by %s format.",
+					  mda_index, dev_name(pv->dev),
+					  pv->fmt->name);
+		return 0;
+	}
+
+	return fid_remove_mda(pv->fid, NULL, (const char *) &pv->id,
+			      ID_LEN, mda_index);
+}
+
+static int _text_pv_remove_metadata_area(const struct format_type *fmt,
+					 struct physical_volume *pv,
+					 unsigned mda_index)
+{
+	return remove_metadata_area_from_pv(pv, mda_index);
+}
+
 /* 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 char *pvid,
@@ -2356,6 +2379,7 @@ static struct format_handler _text_handler = {
 	.pv_read = _text_pv_read,
 	.pv_setup = _text_pv_setup,
 	.pv_add_metadata_area = _text_pv_add_metadata_area,
+	.pv_remove_metadata_area = _text_pv_remove_metadata_area,
 	.pv_write = _text_pv_write,
 	.vg_setup = _text_vg_setup,
 	.lv_setup = _text_lv_setup,
diff --git a/lib/format_text/format-text.h b/lib/format_text/format-text.h
index f65be74..694b5c1 100644
--- a/lib/format_text/format-text.h
+++ b/lib/format_text/format-text.h
@@ -61,6 +61,8 @@ int add_metadata_area_to_pv(struct physical_volume *pv,
 			    uint64_t mda_start,
 			    uint64_t mda_size,
 			    unsigned mda_ignored);
+int remove_metadata_area_from_pv(struct physical_volume *pv,
+				 unsigned mda_index);
 int add_mda(const struct format_type *fmt, struct dm_pool *mem, struct dm_list *mdas,
 	    struct device *dev, uint64_t start, uint64_t size, unsigned ignored);
 void del_mdas(struct dm_list *mdas);
diff --git a/lib/metadata/metadata.h b/lib/metadata/metadata.h
index 0da8b3d..ed72551 100644
--- a/lib/metadata/metadata.h
+++ b/lib/metadata/metadata.h
@@ -266,6 +266,13 @@ struct format_handler {
 				     unsigned metadata_ignored);
 
 	/*
+	 * Remove metadata area from a PV. Changes will take effect on pv_write.
+	 */
+	int (*pv_remove_metadata_area) (const struct format_type *fmt,
+					struct physical_volume *pv,
+					unsigned metadata_index);
+
+	/*
 	 * 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
 	 */
-- 
1.7.3.4



^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 09/17] Add pv_initialise fn to format_handler interface.
  2011-01-24 11:03 [PATCH 00/17] Add interface to support adding and removing metadata areas on demand (v2) Peter Rajnoha
                   ` (7 preceding siblings ...)
  2011-01-24 11:03 ` [PATCH 08/17] Add pv_remove_metadata_area fn to support removing " Peter Rajnoha
@ 2011-01-24 11:04 ` Peter Rajnoha
  2011-01-28 16:31   ` Petr Rockai
  2011-01-24 11:04 ` [PATCH 10/17] Add pe_start_locked parameter to pv_create fn Peter Rajnoha
                   ` (8 subsequent siblings)
  17 siblings, 1 reply; 36+ messages in thread
From: Peter Rajnoha @ 2011-01-24 11:04 UTC (permalink / raw)
  To: lvm-devel

This is a split-off from the original pv_setup code, a simple refactor.
It makes the code easier to read and cleans up the interface a bit. So
now we will call pv_initialise when we initialise a PV only, creating a
brand new PV. It will also initialise a new format_instance to use later on.

Signed-off-by: Peter Rajnoha <prajnoha@redhat.com>
---
 lib/format1/format1.c         |   35 ++++++++++++++------
 lib/format_pool/format_pool.c |   14 ++++++++
 lib/format_text/format-text.c |   71 +++++++++++++++++++++++++++++++++++++++++
 lib/metadata/metadata.h       |   13 +++++++
 4 files changed, 123 insertions(+), 10 deletions(-)

diff --git a/lib/format1/format1.c b/lib/format1/format1.c
index 4f66cdc..cb17ef5 100644
--- a/lib/format1/format1.c
+++ b/lib/format1/format1.c
@@ -361,16 +361,15 @@ static int _format1_pv_read(const struct format_type *fmt, const char *pv_name,
 	return r;
 }
 
-static int _format1_pv_setup(const struct format_type *fmt,
-			     uint64_t pe_start, uint32_t extent_count,
-			     uint32_t extent_size,
-			     unsigned long data_alignment __attribute__((unused)),
-			     unsigned long data_alignment_offset __attribute__((unused)),
-			     int pvmetadatacopies __attribute__((unused)),
-			     uint64_t pvmetadatasize __attribute__((unused)),
-			     unsigned metadataignore __attribute__((unused)),
-			     struct dm_list *mdas __attribute__((unused)),
-			     struct physical_volume *pv, struct volume_group *vg __attribute__((unused)))
+static int _format1_pv_initialise(const struct format_type * fmt,
+				  int64_t label_sector __attribute__((unused)),
+				  uint64_t pe_start,
+				  int pe_start_locked __attribute__((unused)),
+				  uint32_t extent_count,
+				  uint32_t extent_size,
+				  unsigned long data_alignment __attribute__((unused)),
+				  unsigned long data_alignment_offset __attribute__((unused)),
+				  struct physical_volume * pv)
 {
 	if (pv->size > MAX_PV_SIZE)
 		pv->size--;
@@ -400,6 +399,21 @@ static int _format1_pv_setup(const struct format_type *fmt,
 	return 1;
 }
 
+static int _format1_pv_setup(const struct format_type *fmt,
+			     uint64_t pe_start, uint32_t extent_count,
+			     uint32_t extent_size,
+			     unsigned long data_alignment __attribute__((unused)),
+			     unsigned long data_alignment_offset __attribute__((unused)),
+			     int pvmetadatacopies __attribute__((unused)),
+			     uint64_t pvmetadatasize __attribute__((unused)),
+			     unsigned metadataignore __attribute__((unused)),
+			     struct dm_list *mdas __attribute__((unused)),
+			     struct physical_volume *pv,
+			     struct volume_group *vg __attribute__((unused)))
+{
+	return _format1_pv_initialise(fmt, -1, 0, 0, 0, vg->extent_size, 0, 0, pv);
+}
+
 static int _format1_lv_setup(struct format_instance *fid, struct logical_volume *lv)
 {
 	uint64_t max_size = UINT_MAX;
@@ -563,6 +577,7 @@ static void _format1_destroy(struct format_type *fmt)
 
 static struct format_handler _format1_ops = {
 	.pv_read = _format1_pv_read,
+	.pv_initialise = _format1_pv_initialise,
 	.pv_setup = _format1_pv_setup,
 	.pv_write = _format1_pv_write,
 	.lv_setup = _format1_lv_setup,
diff --git a/lib/format_pool/format_pool.c b/lib/format_pool/format_pool.c
index 24ccfc2..83f474a 100644
--- a/lib/format_pool/format_pool.c
+++ b/lib/format_pool/format_pool.c
@@ -188,6 +188,19 @@ out:
 	return NULL;
 }
 
+static int _pool_pv_initialise(const struct format_type *fmt __attribute__((unused)),
+			       int64_t label_sector __attribute__((unused)),
+			       uint64_t pe_start __attribute__((unused)),
+			       int pe_start_locked __attribute__((unused)),
+			       uint32_t extent_count __attribute__((unused)),
+			       uint32_t extent_size __attribute__((unused)),
+			       unsigned long data_alignment __attribute__((unused)),
+			       unsigned long data_alignment_offset __attribute__((unused)),
+			       struct physical_volume *pv __attribute__((unused)))
+{
+	return 1;
+}
+
 static int _pool_pv_setup(const struct format_type *fmt __attribute__((unused)),
 			  uint64_t pe_start __attribute__((unused)),
 			  uint32_t extent_count __attribute__((unused)),
@@ -295,6 +308,7 @@ static void _pool_destroy(struct format_type *fmt)
 /* *INDENT-OFF* */
 static struct format_handler _format_pool_ops = {
 	.pv_read = _pool_pv_read,
+	.pv_initialise = _pool_pv_initialise,
 	.pv_setup = _pool_pv_setup,
 	.create_instance = _pool_create_instance,
 	.destroy_instance = _pool_destroy_instance,
diff --git a/lib/format_text/format-text.c b/lib/format_text/format-text.c
index 99f691f..c6adedc 100644
--- a/lib/format_text/format-text.c
+++ b/lib/format_text/format-text.c
@@ -1688,6 +1688,76 @@ static int _text_pv_read(const struct format_type *fmt, const char *pv_name,
 	return 1;
 }
 
+static int _text_pv_initialise(const struct format_type *fmt,
+			       const int64_t label_sector,
+			       uint64_t pe_start,
+			       int pe_start_locked,
+			       uint32_t extent_count,
+			       uint32_t extent_size,
+			       unsigned long data_alignment,
+			       unsigned long data_alignment_offset,
+			       struct physical_volume *pv)
+{
+	struct text_fid_pv_context *fid_pv_tc;
+
+	/*
+	 * Try to keep the value of PE start set to a firm value if requested.
+	 * This is usefull when restoring existing PE start value (backups etc.).
+	 */
+	if (pe_start_locked)
+		pv->pe_start = pe_start;
+
+	if (!data_alignment)
+		data_alignment = find_config_tree_int(pv->fmt->cmd,
+					      "devices/data_alignment",
+					      0) * 2;
+
+	if (set_pe_align(pv, data_alignment) != data_alignment &&
+	    data_alignment) {
+		log_error("%s: invalid data alignment of "
+			  "%lu sectors (requested %lu sectors)",
+			  pv_dev_name(pv), pv->pe_align, data_alignment);
+		return 0;
+	}
+
+	if (set_pe_align_offset(pv, data_alignment_offset) != data_alignment_offset &&
+	    data_alignment_offset) {
+		log_error("%s: invalid data alignment offset of "
+			  "%lu sectors (requested %lu sectors)",
+			  pv_dev_name(pv), pv->pe_align_offset, data_alignment_offset);
+		return 0;
+	}
+
+	if (pv->pe_align < pv->pe_align_offset) {
+		log_error("%s: pe_align (%lu sectors) must not be less "
+			  "than pe_align_offset (%lu sectors)",
+			  pv_dev_name(pv), pv->pe_align, pv->pe_align_offset);
+		return 0;
+	}
+
+	if (!pe_start_locked && pv->pe_start < pv->pe_align)
+		pv->pe_start = pv->pe_align;
+
+	if (extent_size)
+		pv->pe_size = extent_size;
+
+	if (extent_count)
+		pv->pe_count = extent_count;
+
+	if ((pv->pe_start + pv->pe_count * pv->pe_size - 1) > (pv->size << SECTOR_SHIFT)) {
+		log_error("Physical extents end beyond end of device %s.",
+			   pv_dev_name(pv));
+		return 0;
+	}
+
+	if (label_sector != -1) {
+		fid_pv_tc = (struct text_fid_pv_context *) pv->fid->private;
+		fid_pv_tc->label_sector = label_sector;
+	}
+
+	return 1;
+}
+
 static void _text_destroy_instance(struct format_instance *fid __attribute__((unused)))
 {
 }
@@ -2377,6 +2447,7 @@ void *create_text_context(struct cmd_context *cmd, const char *path,
 static struct format_handler _text_handler = {
 	.scan = _text_scan,
 	.pv_read = _text_pv_read,
+	.pv_initialise = _text_pv_initialise,
 	.pv_setup = _text_pv_setup,
 	.pv_add_metadata_area = _text_pv_add_metadata_area,
 	.pv_remove_metadata_area = _text_pv_remove_metadata_area,
diff --git a/lib/metadata/metadata.h b/lib/metadata/metadata.h
index ed72551..ae8dd9a 100644
--- a/lib/metadata/metadata.h
+++ b/lib/metadata/metadata.h
@@ -244,6 +244,19 @@ struct format_handler {
 			struct physical_volume * pv, int scan_label_only);
 
 	/*
+	 * Initialise a new PV.
+	 */
+	int (*pv_initialise) (const struct format_type * fmt,
+			      int64_t label_sector,
+			      uint64_t pe_start,
+			      int pe_start_locked,
+			      uint32_t extent_count,
+			      uint32_t extent_size,
+			      unsigned long data_alignment,
+			      unsigned long data_alignment_offset,
+			      struct physical_volume * pv);
+
+	/*
 	 * Tweak an already filled out a pv ready for importing into a
 	 * vg.  eg. pe_count is format specific.
 	 */
-- 
1.7.3.4



^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 10/17] Add pe_start_locked parameter to pv_create fn.
  2011-01-24 11:03 [PATCH 00/17] Add interface to support adding and removing metadata areas on demand (v2) Peter Rajnoha
                   ` (8 preceding siblings ...)
  2011-01-24 11:04 ` [PATCH 09/17] Add pv_initialise fn to format_handler interface Peter Rajnoha
@ 2011-01-24 11:04 ` Peter Rajnoha
  2011-01-28 16:39   ` Petr Rockai
  2011-01-24 11:04 ` [PATCH 11/17] Refactor pv_setup to not include the PV initialisation code Peter Rajnoha
                   ` (7 subsequent siblings)
  17 siblings, 1 reply; 36+ messages in thread
From: Peter Rajnoha @ 2011-01-24 11:04 UTC (permalink / raw)
  To: lvm-devel

So we can define and hint the metadata area handling code that the
pe_start is supposed to be firmly set to a certain value and it should
not be changed during calculations.

Signed-off-by: Peter Rajnoha <prajnoha@redhat.com>
---
 lib/metadata/metadata-exported.h |    1 +
 lib/metadata/metadata.c          |    4 +++-
 tools/vgconvert.c                |    2 +-
 3 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index da62764..627d098 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -394,6 +394,7 @@ struct physical_volume *pv_create(const struct cmd_context *cmd,
 				  unsigned long data_alignment,
 				  unsigned long data_alignment_offset,
 				  uint64_t pe_start,
+				  int pe_start_locked,
 				  uint32_t existing_extent_count,
 				  uint32_t existing_extent_size,
 				  int pvmetadatacopies, uint64_t pvmetadatasize,
diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
index 591f7b5..419dcfc 100644
--- a/lib/metadata/metadata.c
+++ b/lib/metadata/metadata.c
@@ -1486,7 +1486,8 @@ struct physical_volume * pvcreate_single(struct cmd_context *cmd,
 	dm_list_init(&mdas);
 	if (!(pv = pv_create(cmd, dev, pp->idp, pp->size,
 			     pp->data_alignment, pp->data_alignment_offset,
-			     pp->pe_start, pp->extent_count, pp->extent_size,
+			     pp->pe_start, pp->pe_start ? 1 : 0,
+			     pp->extent_count, pp->extent_size,
 			     pp->pvmetadatacopies, pp->pvmetadatasize,
 			     pp->metadataignore, &mdas))) {
 		log_error("Failed to setup physical volume \"%s\"", pv_name);
@@ -1591,6 +1592,7 @@ struct physical_volume *pv_create(const struct cmd_context *cmd,
 				  unsigned long data_alignment,
 				  unsigned long data_alignment_offset,
 				  uint64_t pe_start,
+				  int pe_start_locked,
 				  uint32_t existing_extent_count,
 				  uint32_t existing_extent_size,
 				  int pvmetadatacopies, uint64_t pvmetadatasize,
diff --git a/tools/vgconvert.c b/tools/vgconvert.c
index acae0fc..81ff616 100644
--- a/tools/vgconvert.c
+++ b/tools/vgconvert.c
@@ -125,7 +125,7 @@ static int vgconvert_single(struct cmd_context *cmd, const char *vg_name,
 		dm_list_init(&mdas);
 		if (!(pv = pv_create(cmd, pv_dev(existing_pv),
 				     &existing_pv->id, size, 0, 0,
-				     pe_start, pv_pe_count(existing_pv),
+				     pe_start, 1, pv_pe_count(existing_pv),
 				     pv_pe_size(existing_pv), pvmetadatacopies,
 				     pvmetadatasize, 0, &mdas))) {
 			log_error("Failed to setup physical volume \"%s\"",
-- 
1.7.3.4



^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 11/17] Refactor pv_setup to not include the PV initialisation code.
  2011-01-24 11:03 [PATCH 00/17] Add interface to support adding and removing metadata areas on demand (v2) Peter Rajnoha
                   ` (9 preceding siblings ...)
  2011-01-24 11:04 ` [PATCH 10/17] Add pe_start_locked parameter to pv_create fn Peter Rajnoha
@ 2011-01-24 11:04 ` Peter Rajnoha
  2011-01-24 11:04 ` [PATCH 12/17] Remove unused _mda_setup code Peter Rajnoha
                   ` (6 subsequent siblings)
  17 siblings, 0 replies; 36+ messages in thread
From: Peter Rajnoha @ 2011-01-24 11:04 UTC (permalink / raw)
  To: lvm-devel

PV initialisation is done using the new pv_initialise fn. Now, the
pv_setup is supposed to be used only when we're trying to put the
existing PV together with an existing VG.

Also, since the PV is now becoming the part of the VG, we move
any metadata areas from PV-based format instance to VG-based
format_instance. Then we destroy the PV-based one and pv->fid
now references vg->fid.

(...we can still use the same functions to set/get metadata areas
as with the PV-based format_instance, there's no change in use. The
fid handling interface will take care of this internally...)

Signed-off-by: Peter Rajnoha <prajnoha@redhat.com>
---
 lib/format1/format1.c            |    8 --
 lib/format_pool/format_pool.c    |    9 --
 lib/format_text/archiver.c       |    5 +-
 lib/format_text/format-text.c    |  183 +++++++++++---------------------------
 lib/metadata/metadata-exported.h |    7 +-
 lib/metadata/metadata.c          |   53 +++++------
 lib/metadata/metadata.h          |    8 +--
 tools/vgconvert.c                |    6 +-
 8 files changed, 85 insertions(+), 194 deletions(-)

diff --git a/lib/format1/format1.c b/lib/format1/format1.c
index cb17ef5..cbb9e76 100644
--- a/lib/format1/format1.c
+++ b/lib/format1/format1.c
@@ -400,14 +400,6 @@ static int _format1_pv_initialise(const struct format_type * fmt,
 }
 
 static int _format1_pv_setup(const struct format_type *fmt,
-			     uint64_t pe_start, uint32_t extent_count,
-			     uint32_t extent_size,
-			     unsigned long data_alignment __attribute__((unused)),
-			     unsigned long data_alignment_offset __attribute__((unused)),
-			     int pvmetadatacopies __attribute__((unused)),
-			     uint64_t pvmetadatasize __attribute__((unused)),
-			     unsigned metadataignore __attribute__((unused)),
-			     struct dm_list *mdas __attribute__((unused)),
 			     struct physical_volume *pv,
 			     struct volume_group *vg __attribute__((unused)))
 {
diff --git a/lib/format_pool/format_pool.c b/lib/format_pool/format_pool.c
index 83f474a..8b1472c 100644
--- a/lib/format_pool/format_pool.c
+++ b/lib/format_pool/format_pool.c
@@ -202,15 +202,6 @@ static int _pool_pv_initialise(const struct format_type *fmt __attribute__((unus
 }
 
 static int _pool_pv_setup(const struct format_type *fmt __attribute__((unused)),
-			  uint64_t pe_start __attribute__((unused)),
-			  uint32_t extent_count __attribute__((unused)),
-			  uint32_t extent_size __attribute__((unused)),
-			  unsigned long data_alignment __attribute__((unused)),
-			  unsigned long data_alignment_offset __attribute__((unused)),
-			  int pvmetadatacopies __attribute__((unused)),
-			  uint64_t pvmetadatasize __attribute__((unused)),
-			  unsigned metadataignore __attribute__((unused)),
-			  struct dm_list *mdas __attribute__((unused)),
 			  struct physical_volume *pv __attribute__((unused)),
 			  struct volume_group *vg __attribute__((unused)))
 {
diff --git a/lib/format_text/archiver.c b/lib/format_text/archiver.c
index ec65794..5b888fc 100644
--- a/lib/format_text/archiver.c
+++ b/lib/format_text/archiver.c
@@ -333,10 +333,7 @@ int backup_restore_vg(struct cmd_context *cmd, struct volume_group *vg)
 				  pv_dev_name(pv), info->fmt->name);
 			return 0;
 		}
-		if (!vg->fid->fmt->ops->
-		    pv_setup(vg->fid->fmt, UINT64_C(0), 0, 0, 0, 0, 0UL,
-			     UINT64_C(0), 0,
-			     &vg->fid->metadata_areas_in_use, pv, vg)) {
+		if (!vg->fid->fmt->ops->pv_setup(vg->fid->fmt, pv, vg)) {
 			log_error("Format-specific setup for %s failed",
 				  pv_dev_name(pv));
 			return 0;
diff --git a/lib/format_text/format-text.c b/lib/format_text/format-text.c
index c6adedc..2671adb 100644
--- a/lib/format_text/format-text.c
+++ b/lib/format_text/format-text.c
@@ -1826,151 +1826,70 @@ static struct metadata_area_ops _metadata_text_raw_ops = {
 	.mda_locns_match = _mda_locns_match_raw
 };
 
-/* pvmetadatasize in sectors */
-/*
- * pe_start goal: FIXME -- reality of .pv_write complexity undermines this goal
- * - In cases where a pre-existing pe_start is provided (pvcreate --restorefile
- *   and vgconvert): pe_start must not be changed (so pv->pe_start = pe_start).
- * - In cases where pe_start is 0: leave pv->pe_start as 0 and defer the
- *   setting of pv->pe_start to .pv_write
- */
 static int _text_pv_setup(const struct format_type *fmt,
-			  uint64_t pe_start, uint32_t extent_count,
-			  uint32_t extent_size, unsigned long data_alignment,
-			  unsigned long data_alignment_offset,
-			  int pvmetadatacopies, uint64_t pvmetadatasize,
-			  unsigned metadataignore, struct dm_list *mdas,
-			  struct physical_volume *pv, struct volume_group *vg)
+			  struct physical_volume *pv,
+			  struct volume_group *vg)
 {
-	struct metadata_area *mda, *mda_new, *mda2;
-	struct mda_context *mdac, *mdac2;
-	struct dm_list *pvmdas;
-	struct lvmcache_info *info;
-	int found;
-	uint64_t pe_end = 0;
-	unsigned mda_count = 0;
-	uint64_t mda_size2 = 0;
+	struct format_instance *fid = pv->fid;
+	const char *pvid = (const char *) &pv->id;
+	unsigned mda_index;
+	struct metadata_area *pv_mda;
+	struct mda_context *pv_mdac;
 	uint64_t pe_count;
+	uint64_t size_reduction = 0;
 
-	/* FIXME Cope with pvchange */
-	/* FIXME Merge code with _text_create_text_instance */
-
-	/* If new vg, add any further mdas on this PV to the fid's mda list */
-	if (vg) {
-		/* Iterate through all mdas on this PV */
-		if ((info = info_from_pvid(pv->dev->pvid, 0))) {
-			pvmdas = &info->mdas;
-			dm_list_iterate_items(mda, pvmdas) {
-				mda_count++;
-				mdac =
-				    (struct mda_context *) mda->metadata_locn;
-
-				/* FIXME Check it isn't already in use */
-
-				/* Reduce usable device size */
-				if (mda_count > 1)
-					mda_size2 = mdac->area.size >> SECTOR_SHIFT;
-
-				/* Ensure it isn't already on list */
-				found = 0;
-				dm_list_iterate_items(mda2, mdas) {
-					if (mda2->ops !=
-					    &_metadata_text_raw_ops) continue;
-					mdac2 =
-					    (struct mda_context *)
-					    mda2->metadata_locn;
-					if (!memcmp
-					    (&mdac2->area, &mdac->area,
-					     sizeof(mdac->area))) {
-						found = 1;
-						break;
-					}
-				}
-				if (found)
-					continue;
+	/* FIXME Cope with pvchange
+	 * FIXME: What's wrong with pvchange here exactly???
+	 * 	 ...despite the fact that pvchange itself is
+	 * 	 a hack with respect to pv_write... :)
+	 */
 
-				mda_new = mda_copy(fmt->cmd->mem, mda);
-				if (!mda_new)
-					return_0;
-				dm_list_add(mdas, &mda_new->list);
-				/* FIXME multiple dev_areas inside area */
-			}
-		}
+	/* Add any further mdas on this PV to VG's format instance. */
+	for (mda_index = 0; mda_index < FMT_TEXT_MAX_MDAS_PER_PV; mda_index++) {
+		if (!(pv_mda = fid_get_mda_indexed(fid, pvid, ID_LEN, mda_index)))
+			continue;
 
-		/* FIXME Cope with genuine pe_count 0 */
-
-		/* If missing, estimate pv->size from file-based metadata */
-		if (!pv->size && pv->pe_count)
-			pv->size = pv->pe_count * (uint64_t) vg->extent_size +
-				   pv->pe_start + mda_size2;
-
-		/* Recalculate number of extents that will fit */
-		if (!pv->pe_count) {
-			pe_count = (pv->size - pv->pe_start - mda_size2) /
-				   vg->extent_size;
-			if (pe_count > UINT32_MAX) {
-				log_error("PV %s too large for extent size %s.",
-					  pv_dev_name(pv),
-					  display_size(vg->cmd, (uint64_t) vg->extent_size));
-				return 0;
-			}
-			pv->pe_count = (uint32_t) pe_count;
-		}
+		/* Be sure it's not already in VG's format instance! */
+		if (!fid_get_mda_indexed(vg->fid, pvid, ID_LEN, mda_index))
+			fid_add_mda(vg->fid, pv_mda, pvid, ID_LEN, mda_index);
+	}
 
-		/* Unlike LVM1, we don't store this outside a VG */
-		/* FIXME Default from config file? vgextend cmdline flag? */
-		pv->status |= ALLOCATABLE_PV;
-	} else {
-		if (pe_start)
-			pv->pe_start = pe_start;
-
-		if (!data_alignment)
-			data_alignment = find_config_tree_int(pv->fmt->cmd,
-						      "devices/data_alignment",
-						      0) * 2;
-
-		if (set_pe_align(pv, data_alignment) != data_alignment &&
-		    data_alignment) {
-			log_error("%s: invalid data alignment of "
-				  "%lu sectors (requested %lu sectors)",
-				  pv_dev_name(pv), pv->pe_align, data_alignment);
-			return 0;
-		}
+	/* If there's the 2nd mda, we need to reduce
+	 * usable size for further pe_count calculation! */
+	if ((pv_mda = fid_get_mda_indexed(fid, pvid, ID_LEN, 1)) &&
+	    (pv_mdac = pv_mda->metadata_locn))
+		size_reduction = pv_mdac->area.size >> SECTOR_SHIFT;
 
-		if (set_pe_align_offset(pv, data_alignment_offset) != data_alignment_offset &&
-		    data_alignment_offset) {
-			log_error("%s: invalid data alignment offset of "
-				  "%lu sectors (requested %lu sectors)",
-				  pv_dev_name(pv), pv->pe_align_offset, data_alignment_offset);
-			return 0;
-		}
+	/* VG format instance will be used from now on. */
+	if (pv->fid->pv_only) {
+		pv->fmt->ops->destroy_instance(pv->fid);
+		pv->fid = vg->fid;
+	}
 
-		if (pv->pe_align < pv->pe_align_offset) {
-			log_error("%s: pe_align (%lu sectors) must not be less "
-				  "than pe_align_offset (%lu sectors)",
-				  pv_dev_name(pv), pv->pe_align, pv->pe_align_offset);
-			return 0;
-		}
+	/* FIXME Cope with genuine pe_count 0 */
 
-		/*
-		 * This initialization has a side-effect of allowing
-		 * orphaned PVs to be created with the proper alignment.
-		 * Setting pv->pe_start here circumvents .pv_write's
-		 * "pvcreate on PV without prior pvremove" retreival of
-		 * the PV's previous pe_start.
-		 * - Without this you get actual != expected pe_start
-		 *   failures in the testsuite.
-		 */
-		if (!pe_start && pv->pe_start < pv->pe_align)
-			pv->pe_start = pv->pe_align;
+	/* If missing, estimate pv->size from file-based metadata */
+	if (!pv->size && pv->pe_count)
+		pv->size = pv->pe_count * (uint64_t) vg->extent_size +
+			   pv->pe_start + size_reduction;
 
-		if (extent_count)
-			pe_end = pe_start + extent_count * extent_size - 1;
-		if (!_mda_setup(fmt, pe_start, pe_end, pvmetadatacopies,
-				pvmetadatasize, metadataignore,  mdas, pv, vg))
-			return_0;
+	/* Recalculate number of extents that will fit */
+	if (!pv->pe_count) {
+		pe_count = (pv->size - pv->pe_start - size_reduction) /
+			   vg->extent_size;
+		if (pe_count > UINT32_MAX) {
+			log_error("PV %s too large for extent size %s.",
+				  pv_dev_name(pv),
+				  display_size(vg->cmd, (uint64_t) vg->extent_size));
+			return 0;
+		}
+		pv->pe_count = (uint32_t) pe_count;
 	}
 
+	/* Unlike LVM1, we don't store this outside a VG */
+	/* FIXME Default from config file? vgextend cmdline flag? */
+	pv->status |= ALLOCATABLE_PV;
+
 	return 1;
 }
 
diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index 627d098..398f245 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -397,9 +397,10 @@ struct physical_volume *pv_create(const struct cmd_context *cmd,
 				  int pe_start_locked,
 				  uint32_t existing_extent_count,
 				  uint32_t existing_extent_size,
-				  int pvmetadatacopies, uint64_t pvmetadatasize,
-				  unsigned metadataignore,
-				  struct dm_list *mdas);
+				  uint64_t label_sector,
+				  int pvmetadatacopies,
+				  uint64_t pvmetadatasize,
+				  unsigned metadataignore);
 int pv_resize(struct physical_volume *pv, struct volume_group *vg,
              uint32_t new_pe_count);
 int pv_analyze(struct cmd_context *cmd, const char *pv_name,
diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
index 419dcfc..11dc205 100644
--- a/lib/metadata/metadata.c
+++ b/lib/metadata/metadata.c
@@ -195,7 +195,6 @@ int add_pv_to_vg(struct volume_group *vg, const char *pv_name,
 	struct format_instance *fid = vg->fid;
 	struct dm_pool *mem = vg->vgmem;
 	char uuid[64] __attribute__((aligned(8)));
-	struct dm_list *mdas;
 
 	log_verbose("Adding physical volume '%s' to volume group '%s'",
 		    pv_name, vg->name);
@@ -239,24 +238,7 @@ int add_pv_to_vg(struct volume_group *vg, const char *pv_name,
 	 */
 	pv->pe_alloc_count = 0;
 
-	/*
-	 * FIXME: this does not work entirely correctly in the case where a PV
-	 * has 2 mdas and only one is ignored; ideally all non-ignored mdas
-	 * should be placed on metadata_areas list and ignored on the
-	 * metadata_areas_ignored list; however this requires another
-	 * fairly complex refactoring to remove the 'mdas' parameter from both
-	 * pv_setup and pv_write.  For now, we only put ignored mdas on the
-	 * metadata_areas_ignored list if all mdas in the PV are ignored;
-	 * otherwise, we use the non-ignored list.
-	 */
-	if (!pv_mda_used_count(pv))
-		mdas = &fid->metadata_areas_ignored;
-	else
-		mdas = &fid->metadata_areas_in_use;
-
-	if (!fid->fmt->ops->pv_setup(fid->fmt, UINT64_C(0), 0,
-				     vg->extent_size, 0, 0, 0UL, UINT64_C(0),
-				     0, mdas, pv, vg)) {
+	if (!fid->fmt->ops->pv_setup(fid->fmt, pv, vg)) {
 		log_error("Format-specific setup of physical volume '%s' "
 			  "failed.", pv_name);
 		return 0;
@@ -1488,8 +1470,8 @@ struct physical_volume * pvcreate_single(struct cmd_context *cmd,
 			     pp->data_alignment, pp->data_alignment_offset,
 			     pp->pe_start, pp->pe_start ? 1 : 0,
 			     pp->extent_count, pp->extent_size,
-			     pp->pvmetadatacopies, pp->pvmetadatasize,
-			     pp->metadataignore, &mdas))) {
+			     pp->labelsector, pp->pvmetadatacopies,
+			     pp->pvmetadatasize, pp->metadataignore))) {
 		log_error("Failed to setup physical volume \"%s\"", pv_name);
 		goto error;
 	}
@@ -1595,12 +1577,15 @@ struct physical_volume *pv_create(const struct cmd_context *cmd,
 				  int pe_start_locked,
 				  uint32_t existing_extent_count,
 				  uint32_t existing_extent_size,
-				  int pvmetadatacopies, uint64_t pvmetadatasize,
-				  unsigned metadataignore, struct dm_list *mdas)
+				  uint64_t label_sector,
+				  int pvmetadatacopies,
+				  uint64_t pvmetadatasize,
+				  unsigned metadataignore)
 {
 	const struct format_type *fmt = cmd->fmt;
 	struct dm_pool *mem = fmt->cmd->mem;
 	struct physical_volume *pv = _alloc_pv(mem, dev);
+	unsigned mda_index;
 
 	if (!pv)
 		return NULL;
@@ -1648,16 +1633,24 @@ struct physical_volume *pv_create(const struct cmd_context *cmd,
 	pv->fmt = fmt;
 	pv->vg_name = fmt->orphan_vg_name;
 
-	if (!fmt->ops->pv_setup(fmt, pe_start, existing_extent_count,
-				existing_extent_size, data_alignment,
-				data_alignment_offset,
-				pvmetadatacopies, pvmetadatasize,
-				metadataignore, mdas, pv, NULL)) {
-		log_error("%s: Format-specific setup of physical volume "
-			  "failed.", pv_dev_name(pv));
+	if (!fmt->ops->pv_initialise(fmt, label_sector, pe_start, pe_start_locked,
+				     existing_extent_count, existing_extent_size,
+				     data_alignment, data_alignment_offset, pv)) {
+		log_error("Format-specific initialisation of physical "
+			  "volume %s failed.", pv_dev_name(pv));
 		goto bad;
 	}
 
+	for (mda_index = 0; mda_index < pvmetadatacopies; mda_index++) {
+		if (pv->fmt->ops->pv_add_metadata_area &&
+		    !pv->fmt->ops->pv_add_metadata_area(pv->fmt, pv, pe_start_locked,
+					mda_index, pvmetadatasize, metadataignore)) {
+			log_error("Failed to add metadata area for "
+				  "new physical volume %s", pv_dev_name(pv));
+			goto bad;
+		}
+	}
+
 	return pv;
 
       bad:
diff --git a/lib/metadata/metadata.h b/lib/metadata/metadata.h
index ae8dd9a..a4f1fc1 100644
--- a/lib/metadata/metadata.h
+++ b/lib/metadata/metadata.h
@@ -261,12 +261,8 @@ struct format_handler {
 	 * vg.  eg. pe_count is format specific.
 	 */
 	int (*pv_setup) (const struct format_type * fmt,
-			 uint64_t pe_start, uint32_t extent_count,
-			 uint32_t extent_size, unsigned long data_alignment,
-			 unsigned long data_alignment_offset,
-			 int pvmetadatacopies, uint64_t pvmetadatasize,
-			 unsigned metadataignore, struct dm_list * mdas,
-			 struct physical_volume * pv, struct volume_group * vg);
+			 struct physical_volume * pv,
+			 struct volume_group * vg);
 
 	/*
 	 * Add metadata area to a PV. Changes will take effect on pv_write.
diff --git a/tools/vgconvert.c b/tools/vgconvert.c
index 81ff616..e747b0e 100644
--- a/tools/vgconvert.c
+++ b/tools/vgconvert.c
@@ -126,8 +126,10 @@ static int vgconvert_single(struct cmd_context *cmd, const char *vg_name,
 		if (!(pv = pv_create(cmd, pv_dev(existing_pv),
 				     &existing_pv->id, size, 0, 0,
 				     pe_start, 1, pv_pe_count(existing_pv),
-				     pv_pe_size(existing_pv), pvmetadatacopies,
-				     pvmetadatasize, 0, &mdas))) {
+				     pv_pe_size(existing_pv),
+				     arg_int64_value(cmd, labelsector_ARG,
+						     DEFAULT_LABELSECTOR),
+				     pvmetadatacopies, pvmetadatasize, 0))) {
 			log_error("Failed to setup physical volume \"%s\"",
 				  pv_dev_name(existing_pv));
 			if (change_made)
-- 
1.7.3.4



^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 12/17] Remove unused _mda_setup code.
  2011-01-24 11:03 [PATCH 00/17] Add interface to support adding and removing metadata areas on demand (v2) Peter Rajnoha
                   ` (10 preceding siblings ...)
  2011-01-24 11:04 ` [PATCH 11/17] Refactor pv_setup to not include the PV initialisation code Peter Rajnoha
@ 2011-01-24 11:04 ` Peter Rajnoha
  2011-01-24 11:04 ` [PATCH 13/17] Cleanup pv_write code to use recent changes in metadata handling interface Peter Rajnoha
                   ` (5 subsequent siblings)
  17 siblings, 0 replies; 36+ messages in thread
From: Peter Rajnoha @ 2011-01-24 11:04 UTC (permalink / raw)
  To: lvm-devel

The functionality of former _mda_setup fn is now covered by
pv_add_metadata_area fn.

Signed-off-by: Peter Rajnoha <prajnoha@redhat.com>
---
 lib/format_text/format-text.c |  153 -----------------------------------------
 1 files changed, 0 insertions(+), 153 deletions(-)

diff --git a/lib/format_text/format-text.c b/lib/format_text/format-text.c
index 2671adb..4cc6364 100644
--- a/lib/format_text/format-text.c
+++ b/lib/format_text/format-text.c
@@ -1256,159 +1256,6 @@ static int _text_scan(const struct format_type *fmt, const char *vgname)
 	return (_scan_file(fmt, vgname) & _scan_raw(fmt, vgname));
 }
 
-/* For orphan, creates new mdas according to policy.
-   Always have an mda between end-of-label and pe_align() boundary */
-static int _mda_setup(const struct format_type *fmt,
-		      uint64_t pe_start, uint64_t pe_end,
-		      int pvmetadatacopies, uint64_t pvmetadatasize,
-		      unsigned metadataignore, struct dm_list *mdas,
-		      struct physical_volume *pv,
-		      struct volume_group *vg __attribute__((unused)))
-{
-	uint64_t mda_adjustment, disk_size, alignment, alignment_offset;
-	uint64_t start1, mda_size1;	/* First area - start of disk */
-	uint64_t start2, mda_size2;	/* Second area - end of disk */
-	uint64_t wipe_size = 8 << SECTOR_SHIFT;
-	size_t pagesize = lvm_getpagesize();
-
-	if (!pvmetadatacopies)
-		return 1;
-
-	alignment = pv->pe_align << SECTOR_SHIFT;
-	alignment_offset = pv->pe_align_offset << SECTOR_SHIFT;
-	disk_size = pv->size << SECTOR_SHIFT;
-	pe_start <<= SECTOR_SHIFT;
-	pe_end <<= SECTOR_SHIFT;
-
-	if (pe_end > disk_size) {
-		log_error("Physical extents end beyond end of device %s!",
-			  pv_dev_name(pv));
-		return 0;
-	}
-
-	/* Requested metadatasize */
-	mda_size1 = pvmetadatasize << SECTOR_SHIFT;
-
-	/* Place mda straight after label area@start of disk */
-	start1 = LABEL_SCAN_SIZE;
-
-	/* Unless the space available is tiny, round to PAGE_SIZE boundary */
-	if ((!pe_start && !pe_end) ||
-	    ((pe_start > start1) && (pe_start - start1 >= MDA_SIZE_MIN))) {
-		mda_adjustment = start1 % pagesize;
-		if (mda_adjustment)
-			start1 += (pagesize - mda_adjustment);
-	}
-
-	/* Round up to pe_align boundary */
-	mda_adjustment = (mda_size1 + start1) % alignment;
-	if (mda_adjustment) {
-		mda_size1 += (alignment - mda_adjustment);
-		/* Revert if it's now too large */
-		if (start1 + mda_size1 > disk_size)
-			mda_size1 -= (alignment - mda_adjustment);
-	}
-
-	/* Add pe_align_offset if on pe_align boundary */
-	if (alignment_offset &&
-	    (((start1 + mda_size1) % alignment) == 0)) {
-		mda_size1 += alignment_offset;
-		/* Revert if it's now too large */
-		if (start1 + mda_size1 > disk_size)
-			mda_size1 -= alignment_offset;
-	}
-
-	/* Ensure it's not going to be bigger than the disk! */
-	if (start1 + mda_size1 > disk_size) {
-		log_warn("WARNING: metadata area fills disk leaving no "
-			 "space for data on %s.", pv_dev_name(pv));
-		/* Leave some free space for rounding */
-		/* Avoid empty data area as could cause tools problems */
-		mda_size1 = disk_size - start1 - alignment * 2;
-		if (start1 + mda_size1 > disk_size) {
-			log_error("Insufficient space for first mda on %s",
-				  pv_dev_name(pv));
-			return 0;
-		}
-		/* Round up to pe_align boundary */
-		mda_adjustment = (mda_size1 + start1) % alignment;
-		if (mda_adjustment)
-			mda_size1 += (alignment - mda_adjustment);
-		/* Only have 1 mda in this case */
-		pvmetadatacopies = 1;
-	}
-
-	/* If we already have PEs, avoid overlap */
-	if (pe_start || pe_end) {
-		if (pe_start <= start1)
-			mda_size1 = 0;
-		else if (start1 + mda_size1 > pe_start)
-			mda_size1 = pe_start - start1;
-	}
-
-	/* FIXME If creating new mdas, wipe them! */
-	if (mda_size1) {
-		if (!add_mda(fmt, fmt->cmd->mem, mdas, pv->dev, start1,
-			     mda_size1, metadataignore))
-			return 0;
-
-		if (!dev_set((struct device *) pv->dev, start1,
-			     (size_t) (mda_size1 >
-				       wipe_size ? : mda_size1), 0)) {
-			log_error("Failed to wipe new metadata area");
-			return 0;
-		}
-
-		if (pvmetadatacopies == 1)
-			return 1;
-	} else
-		start1 = 0;
-
-	/* A second copy at end of disk */
-	mda_size2 = pvmetadatasize << SECTOR_SHIFT;
-
-	/* Ensure it's not going to be bigger than the disk! */
-	if (mda_size2 > disk_size)
-		mda_size2 = disk_size - start1 - mda_size1;
-
-	mda_adjustment = (disk_size - mda_size2) % alignment;
-	if (mda_adjustment)
-		mda_size2 += mda_adjustment;
-
-	start2 = disk_size - mda_size2;
-
-	/* If we already have PEs, avoid overlap */
-	if (pe_start || pe_end) {
-		if (start2 < pe_end) {
-			mda_size2 -= (pe_end - start2);
-			start2 = pe_end;
-		}
-	}
-
-	/* If we already have a first mda, avoid overlap */
-	if (mda_size1) {
-		if (start2 < start1 + mda_size1) {
-			mda_size2 -= (start1 + mda_size1 - start2);
-			start2 = start1 + mda_size1;
-		}
-		/* No room for any PEs here now! */
-	}
-
-	if (mda_size2) {
-		if (!add_mda(fmt, fmt->cmd->mem, mdas, pv->dev, start2,
-			     mda_size2, metadataignore)) return 0;
-		if (!dev_set(pv->dev, start2,
-			     (size_t) (mda_size1 >
-				       wipe_size ? : mda_size1), 0)) {
-			log_error("Failed to wipe new metadata area");
-			return 0;
-		}
-	} else
-		return 0;
-
-	return 1;
-}
-
 /* Only for orphans */
 /* Set label_sector to -1 if rewriting existing label into same sector */
 /* If mdas is supplied it overwrites existing mdas e.g. used with pvcreate */
-- 
1.7.3.4



^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 13/17] Cleanup pv_write code to use recent changes in metadata handling interface.
  2011-01-24 11:03 [PATCH 00/17] Add interface to support adding and removing metadata areas on demand (v2) Peter Rajnoha
                   ` (11 preceding siblings ...)
  2011-01-24 11:04 ` [PATCH 12/17] Remove unused _mda_setup code Peter Rajnoha
@ 2011-01-24 11:04 ` Peter Rajnoha
  2011-01-24 11:04 ` [PATCH 14/17] Use new metadata handling interface to provide better support for PV resize Peter Rajnoha
                   ` (4 subsequent siblings)
  17 siblings, 0 replies; 36+ messages in thread
From: Peter Rajnoha @ 2011-01-24 11:04 UTC (permalink / raw)
  To: lvm-devel

Now, we use the format_instance to retrieve the metadata areas to write
to. Also, we sync the cache here (like we did before, but now with the format_instance).

Signed-off-by: Peter Rajnoha <prajnoha@redhat.com>
---
 lib/format1/format1.c            |    3 +-
 lib/format_text/format-text.c    |  147 ++++++++++++-------------------------
 lib/metadata/metadata-exported.h |    3 +-
 lib/metadata/metadata.c          |   11 ++--
 lib/metadata/metadata.h          |    3 +-
 tools/pvchange.c                 |    4 +-
 tools/pvresize.c                 |    2 +-
 tools/vgconvert.c                |    4 +-
 tools/vgreduce.c                 |    2 +-
 9 files changed, 61 insertions(+), 118 deletions(-)

diff --git a/lib/format1/format1.c b/lib/format1/format1.c
index cbb9e76..b3eb8f5 100644
--- a/lib/format1/format1.c
+++ b/lib/format1/format1.c
@@ -427,8 +427,7 @@ static int _format1_lv_setup(struct format_instance *fid, struct logical_volume
 	return 1;
 }
 
-static int _format1_pv_write(const struct format_type *fmt, struct physical_volume *pv,
-		     struct dm_list *mdas __attribute__((unused)), int64_t sector __attribute__((unused)))
+static int _format1_pv_write(const struct format_type *fmt, struct physical_volume *pv)
 {
 	struct dm_pool *mem;
 	struct disk_list *dl;
diff --git a/lib/format_text/format-text.c b/lib/format_text/format-text.c
index 4cc6364..521e346 100644
--- a/lib/format_text/format-text.c
+++ b/lib/format_text/format-text.c
@@ -1257,129 +1257,72 @@ static int _text_scan(const struct format_type *fmt, const char *vgname)
 }
 
 /* Only for orphans */
-/* Set label_sector to -1 if rewriting existing label into same sector */
-/* If mdas is supplied it overwrites existing mdas e.g. used with pvcreate */
-static int _text_pv_write(const struct format_type *fmt, struct physical_volume *pv,
-		     struct dm_list *mdas, int64_t label_sector)
+static int _text_pv_write(const struct format_type *fmt, struct physical_volume *pv)
 {
+	struct text_fid_pv_context *fid_pv_tc;
+	struct format_instance *fid = pv->fid;
 	struct label *label;
+	int64_t label_sector;
 	struct lvmcache_info *info;
 	struct mda_context *mdac;
 	struct metadata_area *mda;
+	unsigned mda_index;
 	char buf[MDA_HEADER_SIZE] __attribute__((aligned(8)));
 	struct mda_header *mdah = (struct mda_header *) buf;
-	uint64_t adjustment;
-	struct data_area_list *da;
 
-	/* FIXME Test mode don't update cache? */
-
-	if (!(info = lvmcache_add(fmt->labeller, (char *) &pv->id, pv->dev,
-				  FMT_TEXT_ORPHAN_VG_NAME, NULL, 0)))
+	/* Add a new cache entry with PV info or update existing one. */
+	if (!(info = lvmcache_add(fmt->labeller, (const char *) &pv->id,
+			pv->dev, FMT_TEXT_ORPHAN_VG_NAME, NULL, 0)))
 		return_0;
+
 	label = info->label;
 
-	if (label_sector != -1)
+	/*
+	 * We can change the label sector for a
+	 * plain PV that is not part of a VG only!
+	 */
+	if (fid && fid->pv_only &&
+	    (fid_pv_tc = (struct text_fid_pv_context *) pv->fid->private) &&
+	    ((label_sector = fid_pv_tc->label_sector) != -1))
 		label->sector = label_sector;
 
 	info->device_size = pv->size << SECTOR_SHIFT;
 	info->fmt = fmt;
 
-	/* If mdas supplied, use them regardless of existing ones, */
-	/* otherwise retain existing ones */
-	if (mdas) {
-		if (info->mdas.n)
-			del_mdas(&info->mdas);
-		else
-			dm_list_init(&info->mdas);
-		dm_list_iterate_items(mda, mdas) {
-			mdac = mda->metadata_locn;
-			log_debug("Creating metadata area on %s at sector %"
-				  PRIu64 " size %" PRIu64 " sectors",
-				  dev_name(mdac->area.dev),
-				  mdac->area.start >> SECTOR_SHIFT,
-				  mdac->area.size >> SECTOR_SHIFT);
-			add_mda(fmt, NULL, &info->mdas, mdac->area.dev,
-				mdac->area.start, mdac->area.size, mda_is_ignored(mda));
-		}
-		/* FIXME Temporary until mda creation supported by tools */
-	} else if (!info->mdas.n) {
+	/* Flush all cached metadata areas, we will reenter new/modified ones. */
+	if (info->mdas.n)
+		del_mdas(&info->mdas);
+	else
 		dm_list_init(&info->mdas);
-	}
 
 	/*
-	 * If no pe_start supplied but PV already exists,
-	 * get existing value; use-cases include:
-	 * - pvcreate on PV without prior pvremove
-	 * - vgremove on VG with PV(s) that have pe_start=0 (hacked cfg)
+	 * Add all new or modified metadata areas for this PV stored in
+	 * its format instance. If this PV is not part of a VG yet,
+	 * pv->fid will be used. Otherwise pv->vg->fid will be used.
+	 * The fid_get_mda_indexed fn can handle that transparently,
+	 * just pass the right format_instance in.
 	 */
+	for (mda_index = 0; mda_index < FMT_TEXT_MAX_MDAS_PER_PV; mda_index++) {
+		if (!(mda = fid_get_mda_indexed(fid, (const char *) &pv->id,
+							ID_LEN, mda_index)))
+			continue;
+
+		mdac = (struct mda_context *) mda->metadata_locn;
+		log_debug("Creating metadata area on %s at sector %"
+			  PRIu64 " size %" PRIu64 " sectors",
+			  dev_name(mdac->area.dev),
+			  mdac->area.start >> SECTOR_SHIFT,
+			  mdac->area.size >> SECTOR_SHIFT);
+		add_mda(fmt, NULL, &info->mdas, mdac->area.dev,
+			mdac->area.start, mdac->area.size, mda_is_ignored(mda));
+	}
+
 	if (info->das.n) {
-		if (!pv->pe_start)
-			dm_list_iterate_items(da, &info->das)
-				pv->pe_start = da->disk_locn.offset >> SECTOR_SHIFT;
 		del_das(&info->das);
 	} else
 		dm_list_init(&info->das);
 
-#if 0
-	/*
-	 * FIXME: ideally a pre-existing pe_start seen in .pv_write
-	 * would always be preserved BUT 'pvcreate on PV without prior pvremove'
-	 * could easily cause the pe_start to overlap with the first mda!
-	 */
-	if (pv->pe_start) {
-		log_very_verbose("%s: preserving pe_start=%lu",
-				 pv_dev_name(pv), pv->pe_start);
-		goto preserve_pe_start;
-	}
-#endif
-
-	/*
-	 * If pe_start is still unset, set it to first aligned
-	 * sector after any metadata areas that begin before pe_start.
-	 */
-	if (!pv->pe_start) {
-		pv->pe_start = pv->pe_align;
-		if (pv->pe_align_offset)
-			pv->pe_start += pv->pe_align_offset;
-	}
-	dm_list_iterate_items(mda, &info->mdas) {
-		mdac = (struct mda_context *) mda->metadata_locn;
-		if (pv->dev == mdac->area.dev &&
-		    ((mdac->area.start <= (pv->pe_start << SECTOR_SHIFT)) ||
-		    (mdac->area.start <= lvm_getpagesize() &&
-		     pv->pe_start < (lvm_getpagesize() >> SECTOR_SHIFT))) &&
-		    (mdac->area.start + mdac->area.size >
-		     (pv->pe_start << SECTOR_SHIFT))) {
-			pv->pe_start = (mdac->area.start + mdac->area.size)
-			    >> SECTOR_SHIFT;
-			/* Adjust pe_start to: (N * pe_align) + pe_align_offset */
-			if (pv->pe_align) {
-				adjustment =
-				(pv->pe_start - pv->pe_align_offset) % pv->pe_align;
-				if (adjustment)
-					pv->pe_start += (pv->pe_align - adjustment);
-
-				log_very_verbose("%s: setting pe_start=%" PRIu64
-					 " (orig_pe_start=%" PRIu64 ", "
-					 "pe_align=%lu, pe_align_offset=%lu, "
-					 "adjustment=%" PRIu64 ")",
-					 pv_dev_name(pv), pv->pe_start,
-					 (adjustment ?
-					  pv->pe_start - (pv->pe_align - adjustment) :
-					  pv->pe_start),
-					 pv->pe_align, pv->pe_align_offset, adjustment);
-			}
-		}
-	}
-	if (pv->pe_start >= pv->size) {
-		log_error("Data area is beyond end of device %s!",
-			  pv_dev_name(pv));
-		return 0;
-	}
-
-	/* FIXME: preserve_pe_start: */
-	if (!add_da
-	    (NULL, &info->das, pv->pe_start << SECTOR_SHIFT, UINT64_C(0)))
+	if (!add_da(NULL, &info->das, pv->pe_start << SECTOR_SHIFT, UINT64_C(0)))
 		return_0;
 
 	if (!dev_open(pv->dev))
@@ -1398,11 +1341,17 @@ static int _text_pv_write(const struct format_type *fmt, struct physical_volume
 		}
 	}
 
-	if (!label_write(pv->dev, label)) {
+	if (!label_write(pv->dev, info->label)) {
 		dev_close(pv->dev);
 		return_0;
 	}
 
+	/*
+	 *  FIXME: We should probably use the format instance's metadata
+	 *        areas for label_write and only if it's successful,
+	 *        update the cache afterwards?
+	 */
+
 	if (!dev_close(pv->dev))
 		return_0;
 
diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index 398f245..88dd902 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -356,8 +356,7 @@ struct dm_list *get_vgnames(struct cmd_context *cmd, int include_internal);
 struct dm_list *get_vgids(struct cmd_context *cmd, int include_internal);
 int scan_vgs_for_pvs(struct cmd_context *cmd, int warnings);
 
-int pv_write(struct cmd_context *cmd, struct physical_volume *pv,
-	     struct dm_list *mdas, int64_t label_sector);
+int pv_write(struct cmd_context *cmd, struct physical_volume *pv);
 int move_pv(struct volume_group *vg_from, struct volume_group *vg_to,
 	    const char *pv_name);
 int move_pvs_used_by_lv(struct volume_group *vg_from,
diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
index 11dc205..de9960d 100644
--- a/lib/metadata/metadata.c
+++ b/lib/metadata/metadata.c
@@ -586,7 +586,7 @@ int vg_remove(struct volume_group *vg)
 		}
 
 		/* FIXME Write to same sector label was read from */
-		if (!pv_write(vg->cmd, pv, NULL, INT64_C(-1))) {
+		if (!pv_write(vg->cmd, pv)) {
 			log_error("Failed to remove physical volume \"%s\""
 				  " from volume group \"%s\"",
 				  pv_dev_name(pv), vg->name);
@@ -1503,7 +1503,7 @@ struct physical_volume * pvcreate_single(struct cmd_context *cmd,
 	log_very_verbose("Writing physical volume data to disk \"%s\"",
 			 pv_name);
 
-	if (!(pv_write(cmd, pv, &mdas, pp->labelsector))) {
+	if (!(pv_write(cmd, pv))) {
 		log_error("Failed to write physical volume \"%s\"", pv_name);
 		goto error;
 	}
@@ -3517,8 +3517,7 @@ int scan_vgs_for_pvs(struct cmd_context *cmd, int warnings)
 }
 
 int pv_write(struct cmd_context *cmd __attribute__((unused)),
-	     struct physical_volume *pv,
-	     struct dm_list *mdas, int64_t label_sector)
+	     struct physical_volume *pv)
 {
 	if (!pv->fmt->ops->pv_write) {
 		log_error("Format does not support writing physical volumes");
@@ -3531,7 +3530,7 @@ int pv_write(struct cmd_context *cmd __attribute__((unused)),
 		return 0;
 	}
 
-	if (!pv->fmt->ops->pv_write(pv->fmt, pv, mdas, label_sector))
+	if (!pv->fmt->ops->pv_write(pv->fmt, pv))
 		return_0;
 
 	return 1;
@@ -3550,7 +3549,7 @@ int pv_write_orphan(struct cmd_context *cmd, struct physical_volume *pv)
 		return 0;
 	}
 
-	if (!pv_write(cmd, pv, NULL, INT64_C(-1))) {
+	if (!pv_write(cmd, pv)) {
 		log_error("Failed to clear metadata from physical "
 			  "volume \"%s\" after removal from \"%s\"",
 			  pv_dev_name(pv), old_vg_name);
diff --git a/lib/metadata/metadata.h b/lib/metadata/metadata.h
index a4f1fc1..f537671 100644
--- a/lib/metadata/metadata.h
+++ b/lib/metadata/metadata.h
@@ -286,8 +286,7 @@ struct format_handler {
 	 * pv->vg_name must be a valid orphan VG name
 	 */
 	int (*pv_write) (const struct format_type * fmt,
-			 struct physical_volume * pv, struct dm_list * mdas,
-			 int64_t label_sector);
+			 struct physical_volume * pv);
 
 	/*
 	 * Tweak an already filled out a lv eg, check there
diff --git a/tools/pvchange.c b/tools/pvchange.c
index 899a8b9..3f60f54 100644
--- a/tools/pvchange.c
+++ b/tools/pvchange.c
@@ -160,7 +160,7 @@ static int _pvchange_single(struct cmd_context *cmd, struct volume_group *vg,
 
 			pv->vg_name = pv->fmt->orphan_vg_name;
 			pv->pe_alloc_count = 0;
-			if (!(pv_write(cmd, pv, NULL, INT64_C(-1)))) {
+			if (!(pv_write(cmd, pv))) {
 				log_error("pv_write with new uuid failed "
 					  "for %s.", pv_name);
 				goto out;
@@ -182,7 +182,7 @@ static int _pvchange_single(struct cmd_context *cmd, struct volume_group *vg,
 			goto out;
 		}
 		backup(vg);
-	} else if (!(pv_write(cmd, pv, NULL, INT64_C(-1)))) {
+	} else if (!(pv_write(cmd, pv))) {
 		log_error("Failed to store physical volume \"%s\"",
 			  pv_name);
 		goto out;
diff --git a/tools/pvresize.c b/tools/pvresize.c
index 4f1d610..dbec967 100644
--- a/tools/pvresize.c
+++ b/tools/pvresize.c
@@ -150,7 +150,7 @@ static int _pv_resize_single(struct cmd_context *cmd,
 			goto out;
 		}
 		backup(vg);
-	} else if (!(pv_write(cmd, pv, NULL, INT64_C(-1)))) {
+	} else if (!(pv_write(cmd, pv))) {
 		log_error("Failed to store physical volume \"%s\"",
 			  pv_name);
 		goto out;
diff --git a/tools/vgconvert.c b/tools/vgconvert.c
index e747b0e..21c4d1a 100644
--- a/tools/vgconvert.c
+++ b/tools/vgconvert.c
@@ -155,9 +155,7 @@ static int vgconvert_single(struct cmd_context *cmd, const char *vg_name,
 
 		log_very_verbose("Writing physical volume data to disk \"%s\"",
 				 pv_dev_name(pv));
-		if (!(pv_write(cmd, pv, &mdas,
-			       arg_int64_value(cmd, labelsector_ARG,
-					       DEFAULT_LABELSECTOR)))) {
+		if (!(pv_write(cmd, pv))) {
 			log_error("Failed to write physical volume \"%s\"",
 				  pv_dev_name(pv));
 			log_error("Use pvcreate and vgcfgrestore to repair "
diff --git a/tools/vgreduce.c b/tools/vgreduce.c
index 4aa8f01..f85df13 100644
--- a/tools/vgreduce.c
+++ b/tools/vgreduce.c
@@ -438,7 +438,7 @@ static int _vgreduce_single(struct cmd_context *cmd, struct volume_group *vg,
 		goto bad;
 	}
 
-	if (!pv_write(cmd, pv, NULL, INT64_C(-1))) {
+	if (!pv_write(cmd, pv)) {
 		log_error("Failed to clear metadata from physical "
 			  "volume \"%s\" "
 			  "after removal from \"%s\"", name, vg->name);
-- 
1.7.3.4



^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 14/17] Use new metadata handling interface to provide better support for PV resize.
  2011-01-24 11:03 [PATCH 00/17] Add interface to support adding and removing metadata areas on demand (v2) Peter Rajnoha
                   ` (12 preceding siblings ...)
  2011-01-24 11:04 ` [PATCH 13/17] Cleanup pv_write code to use recent changes in metadata handling interface Peter Rajnoha
@ 2011-01-24 11:04 ` Peter Rajnoha
  2011-01-24 11:04 ` [PATCH 15/17] Change vg_convert code to actually work with recent changes in metadata handling interface Peter Rajnoha
                   ` (3 subsequent siblings)
  17 siblings, 0 replies; 36+ messages in thread
From: Peter Rajnoha @ 2011-01-24 11:04 UTC (permalink / raw)
  To: lvm-devel

When resizing a PV that contains the 2nd metadata area at the end of the
disk, we'll just remove the metadata area, do a resize and add the new
one.

We also need a format-specific resize part of the code to be called so
the format_handler interface now includes the pv_resize fn (metadata
location is format-specific as well as the number of supported metadata
area and the metadata layout itself).

The patch moves some parts of the PV resize code a bit to fit the
changes better.

Signed-off-by: Peter Rajnoha <prajnoha@redhat.com>
---
 lib/format_text/format-text.c    |   49 ++++++++++++++++++++++++++
 lib/metadata/metadata-exported.h |    2 +-
 lib/metadata/metadata.h          |    8 ++++
 lib/metadata/pv_manip.c          |   70 +++++++++++++++++++++++++++++---------
 tools/pvresize.c                 |   51 +--------------------------
 5 files changed, 114 insertions(+), 66 deletions(-)

diff --git a/lib/format_text/format-text.c b/lib/format_text/format-text.c
index 521e346..f17bdb1 100644
--- a/lib/format_text/format-text.c
+++ b/lib/format_text/format-text.c
@@ -2083,6 +2083,54 @@ 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 char *pvid,
@@ -2166,6 +2214,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,
diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index 88dd902..74086a2 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -401,7 +401,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);
 
diff --git a/lib/metadata/metadata.h b/lib/metadata/metadata.h
index f537671..5f35333 100644
--- a/lib/metadata/metadata.h
+++ b/lib/metadata/metadata.h
@@ -282,6 +282,14 @@ struct format_handler {
 					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
 	 */
diff --git a/lib/metadata/pv_manip.c b/lib/metadata/pv_manip.c
index e6fe6c2..03ba090 100644
--- a/lib/metadata/pv_manip.c
+++ b/lib/metadata/pv_manip.c
@@ -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 > pv->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;
 }
diff --git a/tools/pvresize.c b/tools/pvresize.c
index dbec967..7cd9267 100644
--- a/tools/pvresize.c
+++ b/tools/pvresize.c
@@ -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,35 +89,8 @@ 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 %ld 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;
-	}
+	if (!pv_resize(pv, vg, size))
+		goto_out;
 
 	log_verbose("Resizing volume \"%s\" to %" PRIu64 " sectors.",
 		    pv_name, pv_size(pv));
-- 
1.7.3.4



^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 15/17] Change vg_convert code to actually work with recent changes in metadata handling interface.
  2011-01-24 11:03 [PATCH 00/17] Add interface to support adding and removing metadata areas on demand (v2) Peter Rajnoha
                   ` (13 preceding siblings ...)
  2011-01-24 11:04 ` [PATCH 14/17] Use new metadata handling interface to provide better support for PV resize Peter Rajnoha
@ 2011-01-24 11:04 ` Peter Rajnoha
  2011-01-24 11:04 ` [PATCH 16/17] Fix pvchange -u to " Peter Rajnoha
                   ` (2 subsequent siblings)
  17 siblings, 0 replies; 36+ messages in thread
From: Peter Rajnoha @ 2011-01-24 11:04 UTC (permalink / raw)
  To: lvm-devel

Well, the problem with vgconvert was that it was a little bit mixed up
code that used new PVs in new format to write PVs out and used former
VG with the PV list to do a vg_write/vg_commit. So there was no
interconnection among newly created PVs and the former VG.

When we pass the metadata area information in format_instance, this
really couldn't work with current vgconvert code (unless I do an ugly
hack :)). I need that PV<->VG interconnection. Otherwise I end up with
no metadata areas to write to.

So, imho, to clean this up, we should probably replace VG's pv list
with the newly created PVs in target format directly as we're creating
those new PVs.

I defined a vg_convert fn that takes a VG and target format parameter
and does the conversion. The converted VG structure could be used after
that since it has also the right PV list with the new PVs in new format.

Signed-off-by: Peter Rajnoha <prajnoha@redhat.com>
---
 lib/format_text/format-text.c    |    9 ++--
 lib/metadata/metadata-exported.h |    3 +
 lib/metadata/metadata.c          |  103 ++++++++++++++++++++++++++++++++++++++
 tools/vgconvert.c                |   93 ++++++++--------------------------
 4 files changed, 133 insertions(+), 75 deletions(-)

diff --git a/lib/format_text/format-text.c b/lib/format_text/format-text.c
index f17bdb1..04abf58 100644
--- a/lib/format_text/format-text.c
+++ b/lib/format_text/format-text.c
@@ -1656,11 +1656,12 @@ static int _text_pv_setup(const struct format_type *fmt,
 	    (pv_mdac = pv_mda->metadata_locn))
 		size_reduction = pv_mdac->area.size >> SECTOR_SHIFT;
 
-	/* VG format instance will be used from now on. */
-	if (pv->fid->pv_only) {
+	/* Destroy PV specific format instance. */
+	if (pv->fid->pv_only)
 		pv->fmt->ops->destroy_instance(pv->fid);
-		pv->fid = vg->fid;
-	}
+
+	/* VG format instance will be used from now on. */
+	pv->fid = vg->fid;
 
 	/* FIXME Cope with genuine pe_count 0 */
 
diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index 74086a2..5a06580 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -415,6 +415,9 @@ void vg_remove_pvs(struct volume_group *vg);
 int vg_remove(struct volume_group *vg);
 int vg_rename(struct cmd_context *cmd, struct volume_group *vg,
 	      const char *new_name);
+int vg_convert(struct cmd_context *cmd, struct volume_group *vg,
+	       const struct format_type *target_fmt, int64_t label_sector,
+	       int pvmetadatacopies, uint64_t pvmetadatasize);
 int vg_extend(struct volume_group *vg, int pv_count, char **pv_names,
 	      struct pvcreate_params *pp);
 int vg_reduce(struct volume_group *vg, char *pv_name);
diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
index de9960d..5332e45 100644
--- a/lib/metadata/metadata.c
+++ b/lib/metadata/metadata.c
@@ -496,6 +496,109 @@ int vg_rename(struct cmd_context *cmd, struct volume_group *vg,
 	return 1;
 }
 
+int vg_convert(struct cmd_context *cmd, struct volume_group *vg,
+	       const struct format_type *target_fmt, int64_t label_sector,
+	       int pvmetadatacopies, uint64_t pvmetadatasize)
+{
+	struct physical_volume *pv, *existing_pv;
+	uint64_t pe_start = 0, pe_end = 0;
+	struct pv_list *pvl;
+	int change_made = 0;
+	const char *vg_name = vg->name;
+
+	/* Replace an old format instance with a new empty one. */
+	vg->fid->fmt->ops->destroy_instance(vg->fid);
+	if (!(vg->fid = target_fmt->ops->create_instance(target_fmt, NULL,
+						vg_name, NULL, NULL, 0))) {
+		log_error("Couldn't create target format instance "
+			  "for VG %s.", vg_name);
+		return 0;
+	}
+
+	/*
+	 * Create new PVs in target format taking original PVs as coimage.
+	 * Write the new PVs out and replace the old PVs in VG structure
+	 * with the new PVs.
+	 */
+	dm_list_iterate_items(pvl, &vg->pvs) {
+		existing_pv = pvl->pv;
+
+		pe_start = pv_pe_start(existing_pv);
+		pe_end = pv_pe_count(existing_pv) * pv_pe_size(existing_pv)
+		    + pe_start - 1;
+
+		if (!(pv = pv_create(cmd, pv_dev(existing_pv),
+				     &existing_pv->id, 0, 0, 0,
+				     pe_start, 1,
+				     pv_pe_count(existing_pv),
+				     pv_pe_size(existing_pv),
+				     label_sector, pvmetadatacopies,
+				     pvmetadatasize, 0))) {
+			log_error("Failed to setup physical volume \"%s\"",
+				  pv_dev_name(existing_pv));
+			if (change_made)
+				goto revert;
+			return 0;
+		}
+
+		/* Need to revert manually if it fails after this point */
+		change_made = 1;
+
+		log_verbose("Set up physical volume for \"%s\" with %" PRIu64
+			    " available sectors", pv_dev_name(pv), pv_size(pv));
+
+		/* Wipe existing label first */
+		if (!label_remove(pv_dev(pv))) {
+			log_error("Failed to wipe existing label on %s",
+				  pv_dev_name(pv));
+		}
+
+		log_very_verbose("Writing physical volume data to disk \"%s\"",
+				 pv_dev_name(pv));
+		/* FIXME: This pv_write will change the VG assignment for the
+		 *	  PV info in the cache to orphan VG! We should just change
+		 *	  the existing VG format information in the cache or throw
+		 *	  the cache away after this pv_write. */
+		if (!(pv_write(cmd, pv))) {
+			log_error("Failed to write physical volume \"%s\"",
+				  pv_dev_name(pv));
+			goto revert;
+		}
+		log_verbose("Physical volume \"%s\" successfully created",
+			    pv_dev_name(pv));
+
+		if (!vg->fid->fmt->ops->pv_setup(vg->fid->fmt, pv, vg)) {
+			log_error("Failed to setup PV %s in new format for VG %s.",
+				  pv_dev_name(pv), vg_name);
+			goto revert;
+		}
+
+		/* FIXME: Free the mem used by the old PV structure? */
+
+		/* Copy relevant fields from old PV and further initialise new PV. */
+		pv->vg = vg;
+		if (!(pv->vg_name = dm_pool_strdup(vg->vgmem, vg_name))) {
+			log_error("vg->name allocation failed for %s",pv_dev_name(pv));
+			goto revert;
+		}
+		memcpy(&pv->vgid, &vg->id, sizeof(vg->id));
+		if (!alloc_pv_segment_whole_pv(vg->vgmem, pv)) {
+			log_error("pv->segments allocation failed for %s", pv_dev_name(pv));
+			goto revert;
+		}
+
+		pvl->pv = pv;
+	}
+
+
+	return 1;
+
+revert:
+	log_error("Use pvcreate and vgcfgrestore to repair "
+		  "from archived metadata.");
+	return 0;
+}
+
 int remove_lvs_in_vg(struct cmd_context *cmd,
 		     struct volume_group *vg,
 		     force_t force)
diff --git a/tools/vgconvert.c b/tools/vgconvert.c
index 21c4d1a..bb48473 100644
--- a/tools/vgconvert.c
+++ b/tools/vgconvert.c
@@ -19,16 +19,11 @@ static int vgconvert_single(struct cmd_context *cmd, const char *vg_name,
 			    struct volume_group *vg,
 			    void *handle __attribute__((unused)))
 {
-	struct physical_volume *pv, *existing_pv;
+	const struct format_type *target_fmt = cmd->fmt;
 	struct logical_volume *lv;
 	struct lv_list *lvl;
-	uint64_t size = 0;
-	struct dm_list mdas;
 	int pvmetadatacopies = 0;
 	uint64_t pvmetadatasize = 0;
-	uint64_t pe_end = 0, pe_start = 0;
-	struct pv_list *pvl;
-	int change_made = 0;
 	struct lvinfo info;
 	int active = 0;
 
@@ -37,13 +32,13 @@ static int vgconvert_single(struct cmd_context *cmd, const char *vg_name,
 		return ECMD_FAILED;
 	}
 
-	if (vg->fid->fmt == cmd->fmt) {
+	if (vg->fid->fmt == target_fmt) {
 		log_error("Volume group \"%s\" already uses format %s",
 			  vg_name, cmd->fmt->name);
 		return ECMD_FAILED;
 	}
 
-	if (cmd->fmt->features & FMT_MDAS) {
+	if (target_fmt->features & FMT_MDAS) {
 		if (arg_sign_value(cmd, metadatasize_ARG, 0) == SIGN_MINUS) {
 			log_error("Metadata size may not be negative");
 			return EINVALID_CMD_LINE;
@@ -72,7 +67,7 @@ static int vgconvert_single(struct cmd_context *cmd, const char *vg_name,
 
 	/* Set PV/LV limit if converting from unlimited metadata format */
 	if (vg->fid->fmt->features & FMT_UNLIMITED_VOLS &&
-	    !(cmd->fmt->features & FMT_UNLIMITED_VOLS)) {
+	    !(target_fmt->features & FMT_UNLIMITED_VOLS)) {
 		if (!vg->max_lv)
 			vg->max_lv = 255;
 		if (!vg->max_pv)
@@ -81,7 +76,7 @@ static int vgconvert_single(struct cmd_context *cmd, const char *vg_name,
 
 	/* If converting to restricted lvid, check if lvid is compatible */
 	if (!(vg->fid->fmt->features & FMT_RESTRICTED_LVIDS) &&
-	    cmd->fmt->features & FMT_RESTRICTED_LVIDS)
+	    target_fmt->features & FMT_RESTRICTED_LVIDS)
 		dm_list_iterate_items(lvl, &vg->lvs)
 			if (!lvid_in_restricted_range(&lvl->lv->lvid)) {
 				log_error("Logical volume %s lvid format is"
@@ -91,7 +86,7 @@ static int vgconvert_single(struct cmd_context *cmd, const char *vg_name,
 			}
 
 	/* Attempt to change any LVIDs that are too big */
-	if (cmd->fmt->features & FMT_RESTRICTED_LVIDS) {
+	if (target_fmt->features & FMT_RESTRICTED_LVIDS) {
 		dm_list_iterate_items(lvl, &vg->lvs) {
 			lv = lvl->lv;
 			if (lv->status & SNAPSHOT)
@@ -115,87 +110,43 @@ static int vgconvert_single(struct cmd_context *cmd, const char *vg_name,
 		return ECMD_FAILED;
 	}
 
-	dm_list_iterate_items(pvl, &vg->pvs) {
-		existing_pv = pvl->pv;
-
-		pe_start = pv_pe_start(existing_pv);
-		pe_end = pv_pe_count(existing_pv) * pv_pe_size(existing_pv)
-		    + pe_start - 1;
-
-		dm_list_init(&mdas);
-		if (!(pv = pv_create(cmd, pv_dev(existing_pv),
-				     &existing_pv->id, size, 0, 0,
-				     pe_start, 1, pv_pe_count(existing_pv),
-				     pv_pe_size(existing_pv),
-				     arg_int64_value(cmd, labelsector_ARG,
-						     DEFAULT_LABELSECTOR),
-				     pvmetadatacopies, pvmetadatasize, 0))) {
-			log_error("Failed to setup physical volume \"%s\"",
-				  pv_dev_name(existing_pv));
-			if (change_made)
-				log_error("Use pvcreate and vgcfgrestore to "
-					  "repair from archived metadata.");
-			return ECMD_FAILED;
-		}
-
-		/* Need to revert manually if it fails after this point */
-		change_made = 1;
-
-		log_verbose("Set up physical volume for \"%s\" with %" PRIu64
-			    " available sectors", pv_dev_name(pv), pv_size(pv));
-
-		/* Wipe existing label first */
-		if (!label_remove(pv_dev(pv))) {
-			log_error("Failed to wipe existing label on %s",
-				  pv_dev_name(pv));
-			log_error("Use pvcreate and vgcfgrestore to repair "
-				  "from archived metadata.");
-			return ECMD_FAILED;
-		}
-
-		log_very_verbose("Writing physical volume data to disk \"%s\"",
-				 pv_dev_name(pv));
-		if (!(pv_write(cmd, pv))) {
-			log_error("Failed to write physical volume \"%s\"",
-				  pv_dev_name(pv));
-			log_error("Use pvcreate and vgcfgrestore to repair "
-				  "from archived metadata.");
-			return ECMD_FAILED;
-		}
-		log_verbose("Physical volume \"%s\" successfully created",
-			    pv_dev_name(pv));
-
-	}
-
 	log_verbose("Deleting existing metadata for VG %s", vg_name);
 	if (!vg_remove_mdas(vg)) {
 		log_error("Removal of existing metadata for %s failed.",
 			  vg_name);
-		log_error("Use pvcreate and vgcfgrestore to repair "
-			  "from archived metadata.");
 		return ECMD_FAILED;
 	}
 
+	if (!vg_convert(cmd, vg, target_fmt,
+			arg_int64_value(cmd, labelsector_ARG,
+					DEFAULT_LABELSECTOR),
+			pvmetadatacopies, pvmetadatasize))
+		return ECMD_FAILED;
+
 	/* FIXME Cache the label format change so we don't have to skip this */
 	if (test_mode()) {
 		log_verbose("Test mode: Skipping metadata writing for VG %s in"
-			    " format %s", vg_name, cmd->fmt->name);
+			    " format %s", vg_name, target_fmt->name);
 		return ECMD_PROCESSED;
 	}
 
 	log_verbose("Writing metadata for VG %s using format %s", vg_name,
-		    cmd->fmt->name);
-	if (!backup_restore_vg(cmd, vg)) {
+		    target_fmt->name);
+	if (!vg_write(vg) || !vg_commit(vg)) {
 		log_error("Conversion failed for volume group %s.", vg_name);
-		log_error("Use pvcreate and vgcfgrestore to repair from "
-			  "archived metadata.");
-		return ECMD_FAILED;
+		goto revert;
 	}
 	log_print("Volume group %s successfully converted", vg_name);
 
 	backup(vg);
 
 	return ECMD_PROCESSED;
+
+revert:
+	log_error("Use pvcreate and vgcfgrestore to repair "
+		  "from archived metadata.");
+	return ECMD_FAILED;
+
 }
 
 int vgconvert(struct cmd_context *cmd, int argc, char **argv)
-- 
1.7.3.4



^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 16/17] Fix pvchange -u to work with recent changes in metadata handling interface.
  2011-01-24 11:03 [PATCH 00/17] Add interface to support adding and removing metadata areas on demand (v2) Peter Rajnoha
                   ` (14 preceding siblings ...)
  2011-01-24 11:04 ` [PATCH 15/17] Change vg_convert code to actually work with recent changes in metadata handling interface Peter Rajnoha
@ 2011-01-24 11:04 ` Peter Rajnoha
  2011-01-24 16:04   ` Peter Rajnoha
  2011-01-24 11:04 ` [PATCH 17/17] Fix pvchange --metadataignore " Peter Rajnoha
  2011-01-24 11:12 ` [PATCH 00/17] Add interface to support adding and removing metadata areas on demand (v2) Peter Rajnoha
  17 siblings, 1 reply; 36+ messages in thread
From: Peter Rajnoha @ 2011-01-24 11:04 UTC (permalink / raw)
  To: lvm-devel

I use PV id as a key for format instance's metadata_areas_index.
But since we change this one, I still need to work with the original
one to access the metadata areas (e.g. in pv_write). So, I defined
the pv->old_id to store that.

Signed-off-by: Peter Rajnoha <prajnoha@redhat.com>
---
 lib/format_text/format-text.c |   10 +++++-----
 lib/metadata/pv.h             |    1 +
 tools/pvchange.c              |    1 +
 3 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/lib/format_text/format-text.c b/lib/format_text/format-text.c
index 04abf58..c0d35f0 100644
--- a/lib/format_text/format-text.c
+++ b/lib/format_text/format-text.c
@@ -1261,6 +1261,7 @@ static int _text_pv_write(const struct format_type *fmt, struct physical_volume
 {
 	struct text_fid_pv_context *fid_pv_tc;
 	struct format_instance *fid = pv->fid;
+	const char *pvid = (const char *) (*pv->old_id.uuid ? &pv->old_id : &pv->id);
 	struct label *label;
 	int64_t label_sector;
 	struct lvmcache_info *info;
@@ -1303,8 +1304,7 @@ static int _text_pv_write(const struct format_type *fmt, struct physical_volume
 	 * just pass the right format_instance in.
 	 */
 	for (mda_index = 0; mda_index < FMT_TEXT_MAX_MDAS_PER_PV; mda_index++) {
-		if (!(mda = fid_get_mda_indexed(fid, (const char *) &pv->id,
-							ID_LEN, mda_index)))
+		if (!(mda = fid_get_mda_indexed(fid, pvid, ID_LEN, mda_index)))
 			continue;
 
 		mdac = (struct mda_context *) mda->metadata_locn;
@@ -1627,7 +1627,7 @@ static int _text_pv_setup(const struct format_type *fmt,
 			  struct volume_group *vg)
 {
 	struct format_instance *fid = pv->fid;
-	const char *pvid = (const char *) &pv->id;
+	const char *pvid = (const char *) (*pv->old_id.uuid ? &pv->old_id : &pv->id);
 	unsigned mda_index;
 	struct metadata_area *pv_mda;
 	struct mda_context *pv_mdac;
@@ -1871,7 +1871,7 @@ static int _text_pv_add_metadata_area(const struct format_type *fmt,
 				      unsigned mda_ignored)
 {
 	struct format_instance *fid = pv->fid;
-	const char *pvid = (char *) &pv->id;
+	const char *pvid = (const char *) (*pv->old_id.uuid ? &pv->old_id : &pv->id);
 	uint64_t pe_start, pe_end;
 	uint64_t alignment, alignment_offset;
 	uint64_t disk_size;
@@ -2090,7 +2090,7 @@ static int _text_pv_resize(const struct format_type *fmt,
 			   uint64_t size)
 {
 	struct format_instance *fid = pv->fid;
-	const char *pvid = (const char *) &pv->id;
+	const char *pvid = (const char *) (*pv->old_id.uuid ? &pv->old_id : &pv->id);
 	struct metadata_area *mda;
 	struct mda_context *mdac;
 	uint64_t size_reduction;
diff --git a/lib/metadata/pv.h b/lib/metadata/pv.h
index a9efcfe..af63610 100644
--- a/lib/metadata/pv.h
+++ b/lib/metadata/pv.h
@@ -22,6 +22,7 @@ struct volume_group;
 
 struct physical_volume {
 	struct id id;
+	struct id old_id;		/* Set during pvchange -u. */
 	struct device *dev;
 	const struct format_type *fmt;
 	struct format_instance *fid;
diff --git a/tools/pvchange.c b/tools/pvchange.c
index 3f60f54..1e11982 100644
--- a/tools/pvchange.c
+++ b/tools/pvchange.c
@@ -141,6 +141,7 @@ static int _pvchange_single(struct cmd_context *cmd, struct volume_group *vg,
 			goto out;
 	} else {
 		/* --uuid: Change PV ID randomly */
+		memcpy(&pv->old_id, &pv->id, sizeof(pv->id));
 		if (!id_create(&pv->id)) {
 			log_error("Failed to generate new random UUID for %s.",
 				  pv_name);
-- 
1.7.3.4



^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 17/17] Fix pvchange --metadataignore to work with recent changes in metadata handling interface.
  2011-01-24 11:03 [PATCH 00/17] Add interface to support adding and removing metadata areas on demand (v2) Peter Rajnoha
                   ` (15 preceding siblings ...)
  2011-01-24 11:04 ` [PATCH 16/17] Fix pvchange -u to " Peter Rajnoha
@ 2011-01-24 11:04 ` Peter Rajnoha
  2011-01-24 11:12 ` [PATCH 00/17] Add interface to support adding and removing metadata areas on demand (v2) Peter Rajnoha
  17 siblings, 0 replies; 36+ messages in thread
From: Peter Rajnoha @ 2011-01-24 11:04 UTC (permalink / raw)
  To: lvm-devel

The pvchange --metadataignore is also hit by recent changes. We use the
format_instance's metadata list, not the cache now (pv_write reads the
format_instance, not the cache, so any changes in the cache would not
take effect!).

Signed-off-by: Peter Rajnoha <prajnoha@redhat.com>
---
 lib/metadata/pv.c |   20 ++++++++++++--------
 1 files changed, 12 insertions(+), 8 deletions(-)

diff --git a/lib/metadata/pv.c b/lib/metadata/pv.c
index e5bb9f0..7386cb1 100644
--- a/lib/metadata/pv.c
+++ b/lib/metadata/pv.c
@@ -248,13 +248,17 @@ unsigned pv_mda_set_ignored(const struct physical_volume *pv, unsigned mda_ignor
 {
 	struct lvmcache_info *info;
 	struct metadata_area *mda, *vg_mda, *tmda;
-	struct dm_list *vg_mdas_in_use, *vg_mdas_ignored;
+	struct dm_list *mdas_in_use, *mdas_ignored, *mdas_to_change;
 
 	if (!(info = info_from_pvid((const char *)&pv->id.uuid, 0)))
 		return_0;
 
+	mdas_in_use = &pv->fid->metadata_areas_in_use;
+	mdas_ignored = &pv->fid->metadata_areas_ignored;
+	mdas_to_change = mda_ignored ? mdas_in_use : mdas_ignored;
+
 	if (is_orphan(pv)) {
-		dm_list_iterate_items(mda, &info->mdas)
+		dm_list_iterate_items(mda, mdas_to_change)
 			mda_set_ignored(mda, mda_ignored);
 		return 1;
 	}
@@ -279,19 +283,19 @@ unsigned pv_mda_set_ignored(const struct physical_volume *pv, unsigned mda_ignor
 	 * list, ensuring the new state will get written to disk in the
 	 * vg_write() path.
 	 */
-	vg_mdas_in_use = &pv->vg->fid->metadata_areas_in_use;
-	vg_mdas_ignored = &pv->vg->fid->metadata_areas_ignored;
-
+	/* FIXME: Try not to update the cache here! Also, try to iterate over
+	 *	  PV mdas only using the format instance's index somehow
+	 * 	  (i.e. try to avoid using mda_locn_match call). */
 	dm_list_iterate_items(mda, &info->mdas) {
 		if (mda_is_ignored(mda) && !mda_ignored)
 			/* Changing an ignored mda to one in_use requires moving it */
-			dm_list_iterate_items_safe(vg_mda, tmda, vg_mdas_ignored)
+			dm_list_iterate_items_safe(vg_mda, tmda, mdas_ignored)
 				if (mda_locns_match(mda, vg_mda)) {
 					mda_set_ignored(vg_mda, mda_ignored);
-					dm_list_move(vg_mdas_in_use, &vg_mda->list);
+					dm_list_move(mdas_in_use, &vg_mda->list);
 				}
 
-		dm_list_iterate_items_safe(vg_mda, tmda, vg_mdas_in_use)
+		dm_list_iterate_items_safe(vg_mda, tmda, mdas_in_use)
 			if (mda_locns_match(mda, vg_mda))
 				/* Don't move mda: needs writing to disk. */
 				mda_set_ignored(vg_mda, mda_ignored);
-- 
1.7.3.4



^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 00/17] Add interface to support adding and removing metadata areas on demand (v2)
  2011-01-24 11:03 [PATCH 00/17] Add interface to support adding and removing metadata areas on demand (v2) Peter Rajnoha
                   ` (16 preceding siblings ...)
  2011-01-24 11:04 ` [PATCH 17/17] Fix pvchange --metadataignore " Peter Rajnoha
@ 2011-01-24 11:12 ` Peter Rajnoha
  17 siblings, 0 replies; 36+ messages in thread
From: Peter Rajnoha @ 2011-01-24 11:12 UTC (permalink / raw)
  To: lvm-devel

On 01/24/2011 12:03 PM +0100, Peter Rajnoha wrote:
> The tests seems to be passing, just one is still failing - it's lvm2 format

...I meant lvm1 :) lvm2 format is fine.

Peter



^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH 16/17] Fix pvchange -u to work with recent changes in metadata handling interface.
  2011-01-24 11:04 ` [PATCH 16/17] Fix pvchange -u to " Peter Rajnoha
@ 2011-01-24 16:04   ` Peter Rajnoha
  0 siblings, 0 replies; 36+ messages in thread
From: Peter Rajnoha @ 2011-01-24 16:04 UTC (permalink / raw)
  To: lvm-devel

On 01/24/2011 12:04 PM +0100, Peter Rajnoha wrote:
> I use PV id as a key for format instance's metadata_areas_index.
> But since we change this one, I still need to work with the original
> one to access the metadata areas (e.g. in pv_write). So, I defined
> the pv->old_id to store that.

One more thing to note. We should probably allow writing non-orphan
PVs directly... The pv_write code calls:

    /* Add a new cache entry with PV info or update existing one. */
        if (!(info = lvmcache_add(fmt->labeller, (const char *) &pv->id,   
                        pv->dev, FMT_TEXT_ORPHAN_VG_NAME, NULL, 0)))
                return_0;

..that changes any existing cache entry to be "orphaned", even if that
PV is already part of a VG!

The code concerned is in outer pv_write fn that calls format specific
pv_write code:

        if (!is_orphan_vg(pv->vg_name) || pv->pe_alloc_count) {
                log_error("Assertion failed: can't _pv_write non-orphan PV "
                          "(in VG %s)", pv->vg_name);
                return 0;
        }

Also, the pvchange -u call is not quite nice today:


          pv->vg_name = pv->fmt->orphan_vg_name;
          pv->pe_alloc_count = 0;
          if (!(pv_write(cmd, pv))) {
                      log_error("pv_write with new uuid failed "
                                          "for %s.", pv_name);
                      goto out;
          }
          pv->vg_name = orig_vg_name;
          pv->pe_alloc_count = orig_pe_alloc_count;


To support calling pv_write on non-orphan PVs, we need to destroy
the old cache item and insert a new one or just update the existing
cache entry. But since the pvid is used as a key to cache pvid hash,
we need to update this entry as well... But I don't see that as a
problem. The change is quite easy, the question is whether it won't
cause any other problems...

Peter



^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH 01/17] Add pvid parameter to create_instance function.
  2011-01-24 11:03 ` [PATCH 01/17] Add pvid parameter to create_instance function Peter Rajnoha
@ 2011-01-25 12:54   ` Petr Rockai
  0 siblings, 0 replies; 36+ messages in thread
From: Petr Rockai @ 2011-01-25 12:54 UTC (permalink / raw)
  To: lvm-devel

Peter Rajnoha <prajnoha@redhat.com> writes:
> The format instance holds the information about current metadata areas and it
> is a snapshot of what we have in the cache at the moment of the instance
> creation. Through the command exection, we use this instance to modify, set
> and access modified metadata areas (like we use it to support the
> --metadataignore and we store the metadata areas that are in use and the
> ones that are ignored).
>
> But to support modifying metadata areas fully (with add/remove metadata
> area support), we need to be able to create format instances for PVs as well.
> Hence, add the pvid parameter for the create_instance function.

> The rules we will follow:
>
>  - the format instance is VG-based or PV-based, but *never both*
>    at the same time,
>
>  - when a PV (structure) is alone, not part of any VG, we will have
>    a PV based format_instance attached to the PV structure,
>
>  - when a PV is part of the VG, any existing PV-based format_instance
>    is destroyed and the PV strucutre will reference VG based format
>    instance instead.
>
>  - whatever we need change for mdas, we'll use the format_instance,
>    we don't touch the cache directly! This will be synchronized with the
>    format instance after pv_write automatically.

Sounds sane. Implementation looks OK too.

> Signed-off-by: Peter Rajnoha <prajnoha@redhat.com>
Reviewed-by: Petr Rockai <prockai@redhat.com>

> ---
>  lib/cache/lvmcache.c          |    2 +-
>  lib/format1/format1.c         |    1 +
>  lib/format_pool/format_pool.c |    1 +
>  lib/format_text/archive.c     |    2 +-
>  lib/format_text/archiver.c    |    8 ++++----
>  lib/format_text/format-text.c |   20 +++++++++++---------
>  lib/metadata/metadata.c       |   10 +++++-----
>  lib/metadata/metadata.h       |    5 +++--
>  8 files changed, 27 insertions(+), 22 deletions(-)
>
> diff --git a/lib/cache/lvmcache.c b/lib/cache/lvmcache.c
> index 0e9cae1..476b176 100644
> --- a/lib/cache/lvmcache.c
> +++ b/lib/cache/lvmcache.c
> @@ -653,7 +653,7 @@ struct volume_group *lvmcache_get_vg(const char *vgid, unsigned precommitted)
>  		return NULL;
>  
>  	if (!(fid = vginfo->fmt->ops->create_instance(vginfo->fmt,
> -						      vginfo->vgname,
> +						      NULL, vginfo->vgname,
>  						      vgid, NULL)))
>  		return_NULL;
>  
> diff --git a/lib/format1/format1.c b/lib/format1/format1.c
> index fc14444..13b757d 100644
> --- a/lib/format1/format1.c
> +++ b/lib/format1/format1.c
> @@ -522,6 +522,7 @@ static struct metadata_area_ops _metadata_format1_ops = {
>  };
>  
>  static struct format_instance *_format1_create_instance(const struct format_type *fmt,
> +						const char *pvid __attribute__((unused)),
>  						const char *vgname __attribute__((unused)),
>  						const char *vgid __attribute__((unused)),
>  						void *private __attribute__((unused)))
> diff --git a/lib/format_pool/format_pool.c b/lib/format_pool/format_pool.c
> index 730da87..814d80c 100644
> --- a/lib/format_pool/format_pool.c
> +++ b/lib/format_pool/format_pool.c
> @@ -249,6 +249,7 @@ static struct metadata_area_ops _metadata_format_pool_ops = {
>  /* *INDENT-ON* */
>  
>  static struct format_instance *_pool_create_instance(const struct format_type *fmt,
> +						const char *pvid __attribute__((unused)),
>  						const char *vgname __attribute__((unused)),
>  						const char *vgid __attribute__((unused)),
>  						void *private __attribute__((unused)))
> diff --git a/lib/format_text/archive.c b/lib/format_text/archive.c
> index 43425dc..760153c 100644
> --- a/lib/format_text/archive.c
> +++ b/lib/format_text/archive.c
> @@ -309,7 +309,7 @@ static void _display_archive(struct cmd_context *cmd, struct archive_file *af)
>  
>  	if (!(context = create_text_context(cmd, af->path, NULL)) ||
>  	    !(tf = cmd->fmt_backup->ops->create_instance(cmd->fmt_backup, NULL,
> -							 NULL, context))) {
> +							 NULL, NULL, context))) {
>  		log_error("Couldn't create text instance object.");
>  		return;
>  	}
> diff --git a/lib/format_text/archiver.c b/lib/format_text/archiver.c
> index e0212a2..b7dcad9 100644
> --- a/lib/format_text/archiver.c
> +++ b/lib/format_text/archiver.c
> @@ -278,7 +278,7 @@ struct volume_group *backup_read_vg(struct cmd_context *cmd,
>  	if (!(context = create_text_context(cmd, file,
>  					    cmd->cmd_line)) ||
>  	    !(tf = cmd->fmt_backup->ops->create_instance(cmd->fmt_backup, NULL,
> -							 NULL, context))) {
> +							 NULL, NULL, context))) {
>  		log_error("Couldn't create text format object.");
>  		return NULL;
>  	}
> @@ -306,8 +306,8 @@ int backup_restore_vg(struct cmd_context *cmd, struct volume_group *vg)
>  	 */
>  
>  	/* Attempt to write out using currently active format */
> -	if (!(vg->fid = cmd->fmt->ops->create_instance(cmd->fmt, vg->name,
> -						       NULL, NULL))) {
> +	if (!(vg->fid = cmd->fmt->ops->create_instance(cmd->fmt, NULL,
> +						vg->name, NULL, NULL))) {
>  		log_error("Failed to allocate format instance");
>  		return 0;
>  	}
> @@ -398,7 +398,7 @@ int backup_to_file(const char *file, const char *desc, struct volume_group *vg)
>  
>  	if (!(context = create_text_context(cmd, file, desc)) ||
>  	    !(tf = cmd->fmt_backup->ops->create_instance(cmd->fmt_backup, NULL,
> -							 NULL, context))) {
> +							 NULL, NULL, context))) {
>  		log_error("Couldn't create backup object.");
>  		return 0;
>  	}
> diff --git a/lib/format_text/format-text.c b/lib/format_text/format-text.c
> index c186757..fda8255 100644
> --- a/lib/format_text/format-text.c
> +++ b/lib/format_text/format-text.c
> @@ -37,10 +37,11 @@
>  #include <dirent.h>
>  #include <ctype.h>
>  
> -static struct format_instance *_text_create_text_instance(const struct format_type
> -						     *fmt, const char *vgname,
> -						     const char *vgid,
> -						     void *context);
> +static struct format_instance *_text_create_text_instance(const struct format_type *fmt,
> +							  const char *pvid,
> +							  const char *vgname,
> +							  const char *vgid,
> +							  void *context);
>  
>  struct text_fid_context {
>  	char *raw_metadata_buf;
> @@ -1085,7 +1086,7 @@ static int _scan_file(const struct format_type *fmt, const char *vgname)
>  
>  				/* FIXME stat file to see if it's changed */
>  				fid = _text_create_text_instance(fmt, NULL, NULL,
> -							    NULL);
> +								 NULL, NULL);
>  				if ((vg = _vg_read_file_name(fid, scanned_vgname,
>  							     path))) {
>  					/* FIXME Store creation host in vg */
> @@ -1912,10 +1913,11 @@ static int _text_pv_setup(const struct format_type *fmt,
>  }
>  
>  /* 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 char *vgname,
> -						     const char *vgid,
> -						     void *context)
> +static struct format_instance *_text_create_text_instance(const struct format_type*fmt,
> +							  const char *pvid,
> +							  const char *vgname,
> +							  const char *vgid,
> +							  void *context)
>  {
>  	struct format_instance *fid;
>  	struct text_fid_context *fidtc;
> diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
> index 771cdb0..fd1948a 100644
> --- a/lib/metadata/metadata.c
> +++ b/lib/metadata/metadata.c
> @@ -974,8 +974,8 @@ struct volume_group *vg_create(struct cmd_context *cmd, const char *vg_name)
>  	/* initialize removed_pvs list */
>  	dm_list_init(&vg->removed_pvs);
>  
> -	if (!(vg->fid = cmd->fmt->ops->create_instance(cmd->fmt, vg_name,
> -						       NULL, NULL))) {
> +	if (!(vg->fid = cmd->fmt->ops->create_instance(cmd->fmt, NULL,
> +						vg_name, NULL, NULL))) {
>  		log_error("Failed to create format instance");
>  		goto bad;
>  	}
> @@ -2629,7 +2629,7 @@ static struct volume_group *_vg_read_orphans(struct cmd_context *cmd,
>  	}
>  
>  	/* create format instance with appropriate metadata area */
> -	if (!(vg->fid = vginfo->fmt->ops->create_instance(vginfo->fmt,
> +	if (!(vg->fid = vginfo->fmt->ops->create_instance(vginfo->fmt, NULL,
>  							  orphan_vgname, NULL,
>  							  NULL))) {
>  		log_error("Failed to create format instance");
> @@ -2808,7 +2808,7 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
>  		use_precommitted = 0;
>  
>  	/* create format instance with appropriate metadata area */
> -	if (!(fid = fmt->ops->create_instance(fmt, vgname, vgid, NULL))) {
> +	if (!(fid = fmt->ops->create_instance(fmt, NULL, vgname, vgid, NULL))) {
>  		log_error("Failed to create format instance");
>  		return NULL;
>  	}
> @@ -2962,7 +2962,7 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
>  			use_precommitted = 0;
>  
>  		/* create format instance with appropriate metadata area */
> -		if (!(fid = fmt->ops->create_instance(fmt, vgname, vgid, NULL))) {
> +		if (!(fid = fmt->ops->create_instance(fmt, NULL, vgname, vgid, NULL))) {
>  			log_error("Failed to create format instance");
>  			return NULL;
>  		}
> diff --git a/lib/metadata/metadata.h b/lib/metadata/metadata.h
> index c0f9148..ab7cff0 100644
> --- a/lib/metadata/metadata.h
> +++ b/lib/metadata/metadata.h
> @@ -279,8 +279,9 @@ struct format_handler {
>  	/*
>  	 * Create format instance with a particular metadata area
>  	 */
> -	struct format_instance *(*create_instance) (const struct format_type *
> -						    fmt, const char *vgname,
> +	struct format_instance *(*create_instance) (const struct format_type *fmt,
> +						    const char *pvid,
> +						    const char *vgname,
>  						    const char *vgid,
>  						    void *context);



^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH 03/17] Add struct format_instance *fid field to struct physical_volume.
  2011-01-24 11:03 ` [PATCH 03/17] Add struct format_instance *fid field to struct physical_volume Peter Rajnoha
@ 2011-01-25 13:03   ` Petr Rockai
  0 siblings, 0 replies; 36+ messages in thread
From: Petr Rockai @ 2011-01-25 13:03 UTC (permalink / raw)
  To: lvm-devel

Peter Rajnoha <prajnoha@redhat.com> writes:

> So PV has also a format instance from now on.
> Also, for starters, let's create a new PV-based format_instance in
> pv_create code.

This one is quite straightforward.

> Signed-off-by: Peter Rajnoha <prajnoha@redhat.com>
Reviewed-by: Petr Rockai <prockai@redhat.com>

> ---
>  lib/metadata/metadata.c |    7 +++++++
>  lib/metadata/pv.h       |    1 +
>  2 files changed, 8 insertions(+), 0 deletions(-)
>
> diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
> index c3accaf..ed2084d 100644
> --- a/lib/metadata/metadata.c
> +++ b/lib/metadata/metadata.c
> @@ -1547,6 +1547,7 @@ static struct physical_volume *_alloc_pv(struct dm_pool *mem, struct device *dev
>  	if (!pv)
>  		return_NULL;
>  
> +	pv->fid = NULL;
>  	pv->pe_size = 0;
>  	pv->pe_start = 0;
>  	pv->pe_count = 0;
> @@ -1638,6 +1639,12 @@ struct physical_volume *pv_create(const struct cmd_context *cmd,
>  		goto bad;
>  	}
>  
> +	if (!(pv->fid = fmt->ops->create_instance(fmt, (const char *) &pv->id,
> +						  NULL, NULL, NULL))) {
> +		log_error("Couldn't create format instance for PV %s.", pv_dev_name(pv));
> +		goto bad;
> +	}
> +
>  	pv->fmt = fmt;
>  	pv->vg_name = fmt->orphan_vg_name;
>  
> diff --git a/lib/metadata/pv.h b/lib/metadata/pv.h
> index a02f6f8..a9efcfe 100644
> --- a/lib/metadata/pv.h
> +++ b/lib/metadata/pv.h
> @@ -24,6 +24,7 @@ struct physical_volume {
>  	struct id id;
>  	struct device *dev;
>  	const struct format_type *fmt;
> +	struct format_instance *fid;
>  
>  	/*
>  	 * vg_name and vgid are used before the parent VG struct exists.



^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH 02/17] Add supporting functions for metadata areas stored in format instance.
  2011-01-24 11:03 ` [PATCH 02/17] Add supporting functions for metadata areas stored in format instance Peter Rajnoha
@ 2011-01-25 13:16   ` Petr Rockai
  2011-01-26 10:38     ` Peter Rajnoha
  0 siblings, 1 reply; 36+ messages in thread
From: Petr Rockai @ 2011-01-25 13:16 UTC (permalink / raw)
  To: lvm-devel

Peter Rajnoha <prajnoha@redhat.com> writes:
> This patch divides current create_instance functionality into PV-based
> and VG-based. We add a simple flag "pv_only" in struct format_instance
> that will help us to identify the type of the format_instance when used
> later on (since we will always have PV/VG separation, I think it would
> be useless to define an interface for this where we would attach supporting
> functions on the fly like we do for mda->ops as an example. In this case,
> a simple flag is fine to switch the functionality).
>
> Another change is the metadata_areas_index we have in the struct
> format_instance. To access a certain metadata area, we need to know
> two keys - PV id and metadta area index within that PV. So a few new
> functions have been modified/added to support this:
> - fid_add_mda (modified)
> - fid_add_mdas (modified)
> - fid_remove_mda (new)
> - fid_get_mda_indexed (new)
>
> Actually, the form of the key that will be used is up to the caller,
> but he needs to remember the key somehow to get the mda back :)
>
> The key is simply made up of the base key (a string) and a subkey
> (an unsigned integer). The actual key used internally is then a string:
>
>   <basekey>_<subkey>
>
> Now, the metadata_areas_index is format specific. This is because
> each format can have different number and types of metadata areas
> it can support and so we'd like to be able to use the most suitable
> index for the specific format. Also, we can use a different indexing
> scheme for PV and VG based format_instance.
>
> For PV based format instance in current lvm2 format, we have only
> 2 metadata areas at maximum. So we use only a simple array. No need
> to use any buldozer-type indexing here :)
>
> For VG based format instance, we can group many many mdas together
> from numerous PVs. So we'll use a hash here (like we use for the cache).
> (but maybe we can add even better indexing in the future!)
>
> If key is not defined, we just store the mda without indexing.
> We'll have it in the metadata_areas_in_use/ignored list directly.
>
> ...but we can change these later if needed, of course. The
> implementation is internal, the interface stays the same)
>
> Also, I kept the format instance's metadata_areas_in_use/ignored for
> now, but eventually, I'd like this to be accessed through the index
> in the future. But that is another step to take later...
>
> Signed-off-by: Peter Rajnoha <prajnoha@redhat.com>

Comments below. I think this patch could be improved. On the other hand,
none of the issues are a serious showstopper, but I would definitely
like to see at least the pv_only thing addressed before proceeding. (See
below.)

Reviewed-by: Petr Rockai <prockai@redhat.com>

Yours,
   Petr

> ---
>  lib/format1/format1.c            |    1 +
>  lib/format_text/format-text.c    |  137 ++++++++++++++++++++++++++++----------
>  lib/format_text/format-text.h    |    1 +
>  lib/metadata/metadata-exported.h |    3 +
>  lib/metadata/metadata.c          |  103 +++++++++++++++++++++++++++-
>  lib/metadata/metadata.h          |   10 ++-
>  6 files changed, 213 insertions(+), 42 deletions(-)
>
> diff --git a/lib/format1/format1.c b/lib/format1/format1.c
> index 13b757d..ff5b0f5 100644
> --- a/lib/format1/format1.c
> +++ b/lib/format1/format1.c
> @@ -534,6 +534,7 @@ static struct format_instance *_format1_create_instance(const struct format_type
>  		return_NULL;
>  
>  	fid->fmt = fmt;
> +	fid->metadata_areas_index = NULL;
>  	dm_list_init(&fid->metadata_areas_in_use);
>  	dm_list_init(&fid->metadata_areas_ignored);
>  
> diff --git a/lib/format_text/format-text.c b/lib/format_text/format-text.c
> index fda8255..c8c56f7 100644
> --- a/lib/format_text/format-text.c
> +++ b/lib/format_text/format-text.c
> @@ -48,6 +48,10 @@ struct text_fid_context {
>  	uint32_t raw_metadata_buf_size;
>  };
>  
> +struct text_fid_pv_context {
> +	int64_t label_sector;
> +};
> +
>  struct dir_list {
>  	struct dm_list list;
>  	char dir[0];
> @@ -1912,14 +1916,38 @@ static int _text_pv_setup(const struct format_type *fmt,
>  	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 char *pvid,
> -							  const char *vgname,
> -							  const char *vgid,
> -							  void *context)
> +static int _create_pv_text_instance(struct format_instance *fid, const char *pvid)
> +{
> +	struct text_fid_pv_context *fid_pv_tc;
> +	struct lvmcache_info *info;
> +
> +	fid->pv_only = 1;
> +
> +	if (!(fid_pv_tc = (struct text_fid_pv_context *)
> +			  dm_pool_zalloc(fid->fmt->cmd->mem, sizeof(*fid_pv_tc)))) {
> +		log_error("Couldn't allocate text_fid_pv_context.");
> +		return 0;
> +	}
> +	fid_pv_tc->label_sector = -1;
> +	fid->private = (void *) fid_pv_tc;
> +
> +	if (!(fid->metadata_areas_index = dm_pool_zalloc(fid->fmt->cmd->mem,
> +						   FMT_TEXT_MAX_MDAS_PER_PV *
> +						   sizeof(struct metadata_area *)))) {
> +		log_error("Couldn't allocate format instance metadata index.");
> +		return 0;
> +	}
> +
> +	if ((info = info_from_pvid(pvid, 0)))
> +		fid_add_mdas(fid, &info->mdas, pvid, ID_LEN);
> +
> +	return 1;
> +}
OK

> +
> +static int _create_vg_text_instance(struct format_instance *fid,
> +				    const char *vgname, const char *vgid,
> +				    void *context)
>  {
> -	struct format_instance *fid;
>  	struct text_fid_context *fidtc;
>  	struct metadata_area *mda;
>  	struct mda_context *mdac;
> @@ -1930,85 +1958,122 @@ static struct format_instance *_text_create_text_instance(const struct format_ty
>  	struct lvmcache_vginfo *vginfo;
>  	struct lvmcache_info *info;
>  
> -	if (!(fid = dm_pool_alloc(fmt->cmd->mem, sizeof(*fid)))) {
> -		log_error("Couldn't allocate format instance object.");
> -		return NULL;
> -	}
> +	fid->pv_only = 0;
>  
>  	if (!(fidtc = (struct text_fid_context *)
> -			dm_pool_zalloc(fmt->cmd->mem,sizeof(*fidtc)))) {
> +			dm_pool_zalloc(fid->fmt->cmd->mem,sizeof(*fidtc)))) {
>  		log_error("Couldn't allocate text_fid_context.");
> -		return NULL;
> +		return 0;
>  	}
>  
>  	fidtc->raw_metadata_buf = NULL;
>  	fid->private = (void *) fidtc;
>  
> -	fid->fmt = fmt;
> -	dm_list_init(&fid->metadata_areas_in_use);
> -	dm_list_init(&fid->metadata_areas_ignored);
> -
>  	if (!vgname) {
> -		if (!(mda = dm_pool_zalloc(fmt->cmd->mem, sizeof(*mda))))
> -			return_NULL;
> +		if (!(mda = dm_pool_zalloc(fid->fmt->cmd->mem, sizeof(*mda))))
> +			return_0;
>  		mda->ops = &_metadata_text_file_backup_ops;
>  		mda->metadata_locn = context;
>  		mda->status = 0;
> -		fid_add_mda(fid, mda);
> +		fid_add_mda(fid, mda, NULL, 0, 0);
>  	} else {
> -		dir_list = &((struct mda_lists *) fmt->private)->dirs;
> +		if (!(fid->metadata_areas_index = dm_hash_create(128))) {
> +			log_error("Couldn't create metadata index for format "
> +				  "instance of VG %s.", vgname);
> +			return 0;
> +		}
> +
> +		dir_list = &((struct mda_lists *) fid->fmt->private)->dirs;
>  
>  		dm_list_iterate_items(dl, dir_list) {
>  			if (dm_snprintf(path, PATH_MAX, "%s/%s",
>  					 dl->dir, vgname) < 0) {
>  				log_error("Name too long %s/%s", dl->dir,
>  					  vgname);
> -				return NULL;
> +				return 0;
>  			}
>  
> -			context = create_text_context(fmt->cmd, path, NULL);
> -			if (!(mda = dm_pool_zalloc(fmt->cmd->mem, sizeof(*mda))))
> -				return_NULL;
> +			context = create_text_context(fid->fmt->cmd, path, NULL);
> +			if (!(mda = dm_pool_zalloc(fid->fmt->cmd->mem, sizeof(*mda))))
> +				return_0;
>  			mda->ops = &_metadata_text_file_ops;
>  			mda->metadata_locn = context;
>  			mda->status = 0;
> -			fid_add_mda(fid, mda);
> +			fid_add_mda(fid, mda, NULL, 0, 0);
>  		}
>  
> -		raw_list = &((struct mda_lists *) fmt->private)->raws;
> +		raw_list = &((struct mda_lists *) fid->fmt->private)->raws;
>  
>  		dm_list_iterate_items(rl, raw_list) {
>  			/* FIXME Cache this; rescan below if some missing */
>  			if (!_raw_holds_vgname(fid, &rl->dev_area, vgname))
>  				continue;
>  
> -			if (!(mda = dm_pool_zalloc(fmt->cmd->mem, sizeof(*mda))))
> -				return_NULL;
> +			if (!(mda = dm_pool_zalloc(fid->fmt->cmd->mem, sizeof(*mda))))
> +				return_0;
>  
> -			if (!(mdac = dm_pool_zalloc(fmt->cmd->mem, sizeof(*mdac))))
> -				return_NULL;
> +			if (!(mdac = dm_pool_zalloc(fid->fmt->cmd->mem, sizeof(*mdac))))
> +				return_0;
>  			mda->metadata_locn = mdac;
>  			/* FIXME Allow multiple dev_areas inside area */
>  			memcpy(&mdac->area, &rl->dev_area, sizeof(mdac->area));
>  			mda->ops = &_metadata_text_raw_ops;
>  			mda->status = 0;
>  			/* FIXME MISTAKE? mda->metadata_locn = context; */
> -			fid_add_mda(fid, mda);
> +			fid_add_mda(fid, mda, NULL, 0, 0);
>  		}
>  
>  		/* Scan PVs in VG for any further MDAs */
> -		lvmcache_label_scan(fmt->cmd, 0);
> +		lvmcache_label_scan(fid->fmt->cmd, 0);
>  		if (!(vginfo = vginfo_from_vgname(vgname, vgid)))
>  			goto_out;
>  		dm_list_iterate_items(info, &vginfo->infos) {
> -			if (!fid_add_mdas(fid, &info->mdas))
> -				return_NULL;
> +			if (!fid_add_mdas(fid, &info->mdas, info->dev->pvid,
> +					  ID_LEN))
> +				return_0;
>  		}
>  		/* FIXME Check raw metadata area count - rescan if required */
>  	}
>  
>        out:
> -	return fid;
> +	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 char *pvid,
> +							  const char *vgname,
> +							  const char *vgid,
> +							  void *context)
> +{
> +	struct format_instance *fid;
> +	int r;
> +
> +	if (pvid && (vgname || vgid)) {
> +		log_error(INTERNAL_ERROR "Format instance must be PV "
> +					 "or VG specific, not both.");
> +		return NULL;
> +	}
> +
> +	if (!(fid = dm_pool_alloc(fmt->cmd->mem, sizeof(*fid)))) {
> +		log_error("Couldn't allocate format instance object.");
> +		return NULL;
> +	}
> +
> +	fid->fmt = fmt;
> +	fid->metadata_areas_index = NULL;
> +	dm_list_init(&fid->metadata_areas_in_use);
> +	dm_list_init(&fid->metadata_areas_ignored);
> +
> +	r = pvid ? _create_pv_text_instance(fid, pvid) :
> +		   _create_vg_text_instance(fid, vgname, vgid, context);
> +
> +	if (r)
> +		return fid;
> +	else {
> +		dm_pool_free(fmt->cmd->mem, fid);
> +		return NULL;
> +	}
>  }

OK, _text_create_text_instance is split into 3. The changes are
relatively straightforward.

>  
>  void *create_text_context(struct cmd_context *cmd, const char *path,
> diff --git a/lib/format_text/format-text.h b/lib/format_text/format-text.h
> index 79365ea..f3cf4f5 100644
> --- a/lib/format_text/format-text.h
> +++ b/lib/format_text/format-text.h
> @@ -22,6 +22,7 @@
>  #define FMT_TEXT_NAME "lvm2"
>  #define FMT_TEXT_ALIAS "text"
>  #define FMT_TEXT_ORPHAN_VG_NAME ORPHAN_VG_NAME(FMT_TEXT_NAME)
> +#define FMT_TEXT_MAX_MDAS_PER_PV 2
>  
>  /*
>   * Archives a vg config.  'retain_days' is the minimum number of
> diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
> index a9709d6..d8247dd 100644
> --- a/lib/metadata/metadata-exported.h
> +++ b/lib/metadata/metadata-exported.h
> @@ -173,6 +173,8 @@ struct pv_segment {
>  
>  struct format_instance {
>  	const struct format_type *fmt;
> +	int pv_only;

Could this be changed to an enumerated "type" field, instead of pv_only?
If I understand correctly, types are mutually exclusive anyway, and
pv_only is rather confusing and non-obvious when reading the code.

> +
>  	/*
>  	 * Each mda in a vg is on exactly one of the below lists.
>  	 * MDAs on the 'in_use' list will be read from / written to
> @@ -181,6 +183,7 @@ struct format_instance {
>  	 */
>  	struct dm_list metadata_areas_in_use;
>  	struct dm_list metadata_areas_ignored;
> +	void *metadata_areas_index;

I don't currently expect that we would need as much genericity as void *
offers (and that we could use a little extra safety). Would an union be
better here, with an explicit list of types that can go in?

>  	void *private;
>  };
>  
> diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
> index fd1948a..c3accaf 100644
> --- a/lib/metadata/metadata.c
> +++ b/lib/metadata/metadata.c
> @@ -2881,7 +2881,8 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
>  					break;
>  				}
>  				if (dm_list_size(&info->mdas)) {
> -					if (!fid_add_mdas(fid, &info->mdas))
> +					if (!fid_add_mdas(fid, &info->mdas,
> +							info->dev->pvid, ID_LEN))
>  						return_NULL;
>  					 
>  					log_debug("Empty mda found for VG %s.", vgname);
> @@ -3912,22 +3913,116 @@ uint32_t vg_lock_newname(struct cmd_context *cmd, const char *vgname)
>  	return FAILED_EXIST;
>  }
>  
> -void fid_add_mda(struct format_instance *fid, struct metadata_area *mda)
> +static int _convert_key_to_string(const char *key, size_t key_len,
> +				  unsigned subkey, char *buf, size_t buf_len)
>  {
> +	memcpy(buf, key, key_len);
> +	buf += key_len;
> +	buf_len -= key_len;
> +	if ((dm_snprintf(buf, buf_len, "_%u", subkey) == -1))
> +		return_0;
> +
> +	return 1;
> +}

Would it be better to require that key is NULL-terminated? It would
simplify a lot of code, by not needing to pass the length as an extra
parameter everywhere. I know that currently we keep the PV/VG/... IDs in
unterminated strings, but I am quite sure this is not a good idea. I
wouldn't expect it to be a *lot* of work to change things to keep a NULL
termination in there as well. Maybe in a followup patch?

> +int fid_add_mda(struct format_instance *fid, struct metadata_area *mda,
> +		 const char *key, size_t key_len, const unsigned subkey)
> +{
> +	char extended_key[PATH_MAX];
> +
>  	dm_list_add(mda_is_ignored(mda) ? &fid->metadata_areas_ignored :
>  					  &fid->metadata_areas_in_use, &mda->list);
> +
> +	/*
> +	 * Return if the mda is not supposed to be
> +	 * indexed or the index itself is not initialised */
> +	if (!key || !fid->metadata_areas_index)
> +		return 1;
> +
> +	if (!_convert_key_to_string(key, key_len, subkey,
> +				    extended_key, PATH_MAX))
> +		return_0;
> +
> +	/* Add metadata area to index. */
> +	if (fid->pv_only)
> +		((struct metadata_area **)fid->metadata_areas_index)[subkey] = mda;

In this branch, all the extended_key logic above is useless. It could be
made more obvious that only the else branch needs extended_key, by
restructuring the code. Also, is key, subkey and extended_key the right
naming scheme? Maybe full_key instead of extended? And maybe sub_key,
for consistency?

> +	else
> +		dm_hash_insert(fid->metadata_areas_index, extended_key, mda);
> +
> +	return 1;
>  }
>  
> -int fid_add_mdas(struct format_instance *fid, struct dm_list *mdas)
> +int fid_add_mdas(struct format_instance *fid, struct dm_list *mdas,
> +		 const char *key, size_t key_len)
>  {
>  	struct metadata_area *mda, *mda_new;
> +	unsigned mda_index = 0;
>  
>  	dm_list_iterate_items(mda, mdas) {
>  		mda_new = mda_copy(fid->fmt->cmd->mem, mda);
>  		if (!mda_new)
>  			return_0;
> -		fid_add_mda(fid, mda_new);
> +
> +		fid_add_mda(fid, mda_new, key, key_len, mda_index);
> +		mda_index++;
>  	}
> +
> +	return 1;
> +}
> +
> +struct metadata_area *fid_get_mda_indexed(struct format_instance *fid,
> +					  const char *key, size_t key_len,
> +					  const unsigned subkey)
> +{
> +	char extended_key[PATH_MAX];
> +	struct metadata_area *mda = NULL;
> +
> +	if (!_convert_key_to_string(key, key_len, subkey,
> +				    extended_key, PATH_MAX))
> +		return_NULL;
> +
> +	if (fid->pv_only)
> +		mda = ((struct metadata_area **)fid->metadata_areas_index)[subkey];
> +	else
> +		mda = (struct metadata_area *) dm_hash_lookup(fid->metadata_areas_index,
> +							      extended_key);

Same about extended_key as above (both path coverage and naming).

> +	return mda;
> +}
> +
> +int fid_remove_mda(struct format_instance *fid, struct metadata_area *mda,
> +		   const char *key, size_t key_len, const unsigned subkey)
> +{
> +	struct metadata_area *mda_indexed = NULL;
> +	char extended_key[PATH_MAX];
> +
> +	/* At least one of mda or key must be specified. */
> +	if (!mda && !key)
> +		return 1;
> +
> +	if (key) {
> +		/*
> +		 * If both mda and key specified, check given mda
> +		 * with what we find using the index and return
> +		 * immediately if these two do not match.
> +		 */
> +		if (!(mda_indexed = fid_get_mda_indexed(fid, key, key_len, subkey)) ||
> +		     (mda && mda != mda_indexed))
> +			return 1;
> +
> +		if (!_convert_key_to_string(key, key_len, subkey,
> +					    extended_key, PATH_MAX))
> +			return_0;
> +
> +		mda = mda_indexed;
> +
> +		if (fid->pv_only)
> +			((struct metadata_area**)fid->metadata_areas_index)[subkey] = NULL;
> +		else
> +			dm_hash_remove(fid->metadata_areas_index, extended_key);

Redundant code paths again.

> +	}
> +
> +	dm_list_del(&mda->list);
> +
>  	return 1;
>  }
>  
> diff --git a/lib/metadata/metadata.h b/lib/metadata/metadata.h
> index ab7cff0..0fbc954 100644
> --- a/lib/metadata/metadata.h
> +++ b/lib/metadata/metadata.h
> @@ -191,8 +191,14 @@ struct metadata_area *mda_copy(struct dm_pool *mem,
>  unsigned mda_is_ignored(struct metadata_area *mda);
>  void mda_set_ignored(struct metadata_area *mda, unsigned ignored);
>  unsigned mda_locns_match(struct metadata_area *mda1, struct metadata_area *mda2);
> -void fid_add_mda(struct format_instance *fid, struct metadata_area *mda);
> -int fid_add_mdas(struct format_instance *fid, struct dm_list *mdas);
> +int fid_add_mda(struct format_instance *fid, struct metadata_area *mda,
> +		 const char *key, size_t key_len, const unsigned subkey);
> +int fid_add_mdas(struct format_instance *fid, struct dm_list *mdas,
> +		 const char *key, size_t key_len);
> +int fid_remove_mda(struct format_instance *fid, struct metadata_area *mda,
> +		   const char *key, size_t key_len, const unsigned subkey);
> +struct metadata_area *fid_get_mda_indexed(struct format_instance *fid,
> +		const char *key, size_t key_len, const unsigned subkey);
>  int mdas_empty_or_ignored(struct dm_list *mdas);
>  
>  #define seg_pvseg(seg, s)	(seg)->areas[(s)].u.pv.pvseg



^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH 04/17] Add format_instance support for pv_read.
  2011-01-24 11:03 ` [PATCH 04/17] Add format_instance support for pv_read Peter Rajnoha
@ 2011-01-25 13:30   ` Petr Rockai
  2011-01-26 11:05     ` Peter Rajnoha
  0 siblings, 1 reply; 36+ messages in thread
From: Petr Rockai @ 2011-01-25 13:30 UTC (permalink / raw)
  To: lvm-devel

Peter Rajnoha <prajnoha@redhat.com> writes:

> We don't need to store metadata areas in a separate "mdas" parameter
> since it is in the pv->fid now. If the fid is not defined yet and is
> NULL, pv_read code will create a new one (if there's no VG fid yet
> where the metadata areas read off of a PV should be attached to).

This is somewhat hairy... With this patch, it's starting to seem that PV
will sometimes point to a VG FID and other times to PV FID. Is there a
good reason for that? Is the PV FID only used with orphan PVs?

I think this is something that really needs to be documented. If nothing
else, the format_instance type value (as suggested in an earlier
comment) should read ORPHAN_PV_FID and VG_FID. It also does raise the
question, why we don't always use VG_FID even for orphans, given how we
have an orphans VG? Would simply using the orphans VG FID be more
consistent overall?

Please also see below.

> ---
>  lib/metadata/metadata.c |   26 +++++++++++++++++++++-----
>  1 files changed, 21 insertions(+), 5 deletions(-)
>
> diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
> index ed2084d..f6ea0e5 100644
> --- a/lib/metadata/metadata.c
> +++ b/lib/metadata/metadata.c
> @@ -37,6 +37,7 @@
>  static struct physical_volume *_pv_read(struct cmd_context *cmd,
>  					struct dm_pool *pvmem,
>  					const char *pv_name,
> +					struct format_instance *fid,
>  					struct dm_list *mdas,
>  					uint64_t *label_sector,
>  					int warnings, int scan_label_only);
> @@ -166,6 +167,7 @@ void add_pvl_to_vgs(struct volume_group *vg, struct pv_list *pvl)
>  	dm_list_add(&vg->pvs, &pvl->list);
>  	vg->pv_count++;
>  	pvl->pv->vg = vg;
> +	pvl->pv->fid = vg->fid;
>  }
>  
>  void del_pvl_from_vgs(struct volume_group *vg, struct pv_list *pvl)
> @@ -1813,7 +1815,7 @@ static struct physical_volume *_find_pv_by_name(struct cmd_context *cmd,
>  	struct physical_volume *pv;
>  
>  	dm_list_init(&mdas);
> -	if (!(pv = _pv_read(cmd, cmd->mem, pv_name, &mdas, NULL, 1, 0))) {
> +	if (!(pv = _pv_read(cmd, cmd->mem, pv_name, NULL, &mdas, NULL, 1, 0))) {
>  		log_error("Physical volume %s not found", pv_name);
>  		return NULL;
>  	}
> @@ -1822,7 +1824,7 @@ static struct physical_volume *_find_pv_by_name(struct cmd_context *cmd,
>  		/* If a PV has no MDAs - need to search all VGs for it */
>  		if (!scan_vgs_for_pvs(cmd, 1))
>  			return_NULL;
> -		if (!(pv = _pv_read(cmd, cmd->mem, pv_name, NULL, NULL, 1, 0))) {
> +		if (!(pv = _pv_read(cmd, cmd->mem, pv_name, NULL, NULL, NULL, 1, 0))) {
>  			log_error("Physical volume %s not found", pv_name);
>  			return NULL;
>  		}
> @@ -2644,7 +2646,8 @@ static struct volume_group *_vg_read_orphans(struct cmd_context *cmd,
>  	}
>  
>  	dm_list_iterate_items(info, &vginfo->infos) {
> -		if (!(pv = _pv_read(cmd, mem, dev_name(info->dev), NULL, NULL, warnings, 0))) {
> +		if (!(pv = _pv_read(cmd, mem, dev_name(info->dev), vg->fid,
> +				    NULL, NULL, warnings, 0))) {
>  			continue;
>  		}
>  		if (!(pvl = dm_pool_zalloc(mem, sizeof(*pvl)))) {
> @@ -3357,13 +3360,14 @@ struct physical_volume *pv_read(struct cmd_context *cmd, const char *pv_name,
>  				struct dm_list *mdas, uint64_t *label_sector,
>  				int warnings, int scan_label_only)
>  {
> -	return _pv_read(cmd, cmd->mem, pv_name, mdas, label_sector, warnings, scan_label_only);
> +	return _pv_read(cmd, cmd->mem, pv_name, NULL, mdas, label_sector, warnings, scan_label_only);
>  }
>  
>  /* FIXME Use label functions instead of PV functions */
>  static struct physical_volume *_pv_read(struct cmd_context *cmd,
>  					struct dm_pool *pvmem,
>  					const char *pv_name,
> +					struct format_instance *fid,
>  					struct dm_list *mdas,
>  					uint64_t *label_sector,
>  					int warnings, int scan_label_only)
> @@ -3407,6 +3411,18 @@ static struct physical_volume *_pv_read(struct cmd_context *cmd,
>  	if (!alloc_pv_segment_whole_pv(pvmem, pv))
>  		goto_bad;
>  
> +	if (fid)
> +		fid_add_mdas(fid, &info->mdas, (const char *) &pv->id, ID_LEN);
> +	else {
> +		if (!(pv->fid = pv->fmt->ops->create_instance(pv->fmt,
> +						(const char *) &pv->id,
> +						NULL, NULL, NULL))) {
> +			log_error("_pv_read: Couldn't create format instance "
> +				  "for PV %s", pv_name);
> +			goto bad;
> +		}
> +	}
> +

The code above is certainly confusing. A comment is needed, explaining
what is going on. Please explain that non-NULL "fid" means that this PV
belongs to a VG, and the fid variable points to that VG's fid.

Also, why mdas are added to the VG fid, but the (orphan) PV fid is left
empty? Should the code read

if (!fid) {
    if (!(fid = pv->fid = ...
}

fid_add_mdas(fid, ...)

?

If, as I suspect, it's because create_instance adds the MDA's itself,
please add a comment to that effect. (Also, is it necessary that
create_instance does this? I am not sure it is entirely intuitive...)

>  	return pv;
>  bad:
>  	_free_pv(pvmem, pv);
> @@ -4213,5 +4229,5 @@ struct physical_volume *pv_by_path(struct cmd_context *cmd, const char *pv_name)
>  	struct dm_list mdas;
>  
>  	dm_list_init(&mdas);
> -	return _pv_read(cmd, cmd->mem, pv_name, &mdas, NULL, 1, 0);
> +	return _pv_read(cmd, cmd->mem, pv_name, NULL, &mdas, NULL, 1, 0);
>  }

Yours,
   Petr



^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH 05/17] Add attach_existing_mdas parameter to create_instance fn.
  2011-01-24 11:03 ` [PATCH 05/17] Add attach_existing_mdas parameter to create_instance fn Peter Rajnoha
@ 2011-01-25 14:43   ` Petr Rockai
  2011-01-26 13:24     ` Peter Rajnoha
  0 siblings, 1 reply; 36+ messages in thread
From: Petr Rockai @ 2011-01-25 14:43 UTC (permalink / raw)
  To: lvm-devel

Peter Rajnoha <prajnoha@redhat.com> writes:

> If attach_existing_mdas parameter is set, we'll attach any existing
> metadata areas found in the cache to the format_instance. Otherwise,
> we will only initialise the format_instance and keep the metadata
> areas list empty (so we can fill that later if that's needed).

As hinted in previous comment, I think it would be better to never
attach existing MDAs in create_instance and simply have a single call to
do that when it is needed. create_instance parameter list is already a
mess...

Yours,
   Petr

>
> Signed-off-by: Peter Rajnoha <prajnoha@redhat.com>
> ---
>  lib/cache/lvmcache.c          |    2 +-
>  lib/format1/format1.c         |    3 ++-
>  lib/format_pool/format_pool.c |    3 ++-
>  lib/format_text/archive.c     |    2 +-
>  lib/format_text/archiver.c    |   10 ++++++----
>  lib/format_text/format-text.c |   34 ++++++++++++++++++++--------------
>  lib/metadata/metadata.c       |   27 ++++++++++++++++++++-------
>  lib/metadata/metadata.h       |    4 +++-
>  8 files changed, 55 insertions(+), 30 deletions(-)
>
> diff --git a/lib/cache/lvmcache.c b/lib/cache/lvmcache.c
> index 476b176..e3ac4f2 100644
> --- a/lib/cache/lvmcache.c
> +++ b/lib/cache/lvmcache.c
> @@ -654,7 +654,7 @@ struct volume_group *lvmcache_get_vg(const char *vgid, unsigned precommitted)
>  
>  	if (!(fid = vginfo->fmt->ops->create_instance(vginfo->fmt,
>  						      NULL, vginfo->vgname,
> -						      vgid, NULL)))
> +						      vgid, NULL, 1)))
>  		return_NULL;
>  
>  	/* Build config tree from vgmetadata, if not yet cached */
> diff --git a/lib/format1/format1.c b/lib/format1/format1.c
> index ff5b0f5..b79bd56 100644
> --- a/lib/format1/format1.c
> +++ b/lib/format1/format1.c
> @@ -525,7 +525,8 @@ static struct format_instance *_format1_create_instance(const struct format_type
>  						const char *pvid __attribute__((unused)),
>  						const char *vgname __attribute__((unused)),
>  						const char *vgid __attribute__((unused)),
> -						void *private __attribute__((unused)))
> +						void *private __attribute__((unused)),
> +						int attach_existing_mdas __attribute((unused)))
>  {
>  	struct format_instance *fid;
>  	struct metadata_area *mda;
> diff --git a/lib/format_pool/format_pool.c b/lib/format_pool/format_pool.c
> index 814d80c..3ecbfe9 100644
> --- a/lib/format_pool/format_pool.c
> +++ b/lib/format_pool/format_pool.c
> @@ -252,7 +252,8 @@ static struct format_instance *_pool_create_instance(const struct format_type *f
>  						const char *pvid __attribute__((unused)),
>  						const char *vgname __attribute__((unused)),
>  						const char *vgid __attribute__((unused)),
> -						void *private __attribute__((unused)))
> +						void *private __attribute__((unused)),
> +						int attach_existing_mdas __attribute__((unused)))
>  {
>  	struct format_instance *fid;
>  	struct metadata_area *mda;
> diff --git a/lib/format_text/archive.c b/lib/format_text/archive.c
> index 760153c..8d55988 100644
> --- a/lib/format_text/archive.c
> +++ b/lib/format_text/archive.c
> @@ -309,7 +309,7 @@ static void _display_archive(struct cmd_context *cmd, struct archive_file *af)
>  
>  	if (!(context = create_text_context(cmd, af->path, NULL)) ||
>  	    !(tf = cmd->fmt_backup->ops->create_instance(cmd->fmt_backup, NULL,
> -							 NULL, NULL, context))) {
> +						NULL, NULL, context, 1))) {
>  		log_error("Couldn't create text instance object.");
>  		return;
>  	}
> diff --git a/lib/format_text/archiver.c b/lib/format_text/archiver.c
> index b7dcad9..ec65794 100644
> --- a/lib/format_text/archiver.c
> +++ b/lib/format_text/archiver.c
> @@ -278,7 +278,7 @@ struct volume_group *backup_read_vg(struct cmd_context *cmd,
>  	if (!(context = create_text_context(cmd, file,
>  					    cmd->cmd_line)) ||
>  	    !(tf = cmd->fmt_backup->ops->create_instance(cmd->fmt_backup, NULL,
> -							 NULL, NULL, context))) {
> +						NULL, NULL, context, 1))) {
>  		log_error("Couldn't create text format object.");
>  		return NULL;
>  	}
> @@ -299,6 +299,7 @@ int backup_restore_vg(struct cmd_context *cmd, struct volume_group *vg)
>  	struct pv_list *pvl;
>  	struct physical_volume *pv;
>  	struct lvmcache_info *info;
> +	struct format_instance *fid;
>  
>  	/*
>  	 * FIXME: Check that the PVs referenced in the backup are
> @@ -306,11 +307,12 @@ int backup_restore_vg(struct cmd_context *cmd, struct volume_group *vg)
>  	 */
>  
>  	/* Attempt to write out using currently active format */
> -	if (!(vg->fid = cmd->fmt->ops->create_instance(cmd->fmt, NULL,
> -						vg->name, NULL, NULL))) {
> +	if (!(fid = cmd->fmt->ops->create_instance(cmd->fmt, NULL,
> +						vg->name, NULL, NULL, 1))) {
>  		log_error("Failed to allocate format instance");
>  		return 0;
>  	}
> +	change_vg_format_instance(vg, fid);
>  
>  	/*
>  	 * Setting vg->old_name to a blank value will explicitly
> @@ -398,7 +400,7 @@ int backup_to_file(const char *file, const char *desc, struct volume_group *vg)
>  
>  	if (!(context = create_text_context(cmd, file, desc)) ||
>  	    !(tf = cmd->fmt_backup->ops->create_instance(cmd->fmt_backup, NULL,
> -							 NULL, NULL, context))) {
> +						NULL, NULL, context, 1))) {
>  		log_error("Couldn't create backup object.");
>  		return 0;
>  	}
> diff --git a/lib/format_text/format-text.c b/lib/format_text/format-text.c
> index c8c56f7..a2f3d74 100644
> --- a/lib/format_text/format-text.c
> +++ b/lib/format_text/format-text.c
> @@ -41,7 +41,8 @@ static struct format_instance *_text_create_text_instance(const struct format_ty
>  							  const char *pvid,
>  							  const char *vgname,
>  							  const char *vgid,
> -							  void *context);
> +							  void *context,
> +							  int attach_existing_mdas);
>  
>  struct text_fid_context {
>  	char *raw_metadata_buf;
> @@ -1090,7 +1091,7 @@ static int _scan_file(const struct format_type *fmt, const char *vgname)
>  
>  				/* FIXME stat file to see if it's changed */
>  				fid = _text_create_text_instance(fmt, NULL, NULL,
> -								 NULL, NULL);
> +								 NULL, NULL, 1);
>  				if ((vg = _vg_read_file_name(fid, scanned_vgname,
>  							     path))) {
>  					/* FIXME Store creation host in vg */
> @@ -1916,7 +1917,8 @@ static int _text_pv_setup(const struct format_type *fmt,
>  	return 1;
>  }
>  
> -static int _create_pv_text_instance(struct format_instance *fid, const char *pvid)
> +static int _create_pv_text_instance(struct format_instance *fid, const char *pvid,
> +				    int attach_existing_mdas)
>  {
>  	struct text_fid_pv_context *fid_pv_tc;
>  	struct lvmcache_info *info;
> @@ -1938,7 +1940,7 @@ static int _create_pv_text_instance(struct format_instance *fid, const char *pvi
>  		return 0;
>  	}
>  
> -	if ((info = info_from_pvid(pvid, 0)))
> +	if (attach_existing_mdas && (info = info_from_pvid(pvid, 0)))
>  		fid_add_mdas(fid, &info->mdas, pvid, ID_LEN);
>  
>  	return 1;
> @@ -1946,7 +1948,7 @@ static int _create_pv_text_instance(struct format_instance *fid, const char *pvi
>  
>  static int _create_vg_text_instance(struct format_instance *fid,
>  				    const char *vgname, const char *vgid,
> -				    void *context)
> +				    void *context, int attach_existing_mdas)
>  {
>  	struct text_fid_context *fidtc;
>  	struct metadata_area *mda;
> @@ -1969,6 +1971,15 @@ static int _create_vg_text_instance(struct format_instance *fid,
>  	fidtc->raw_metadata_buf = NULL;
>  	fid->private = (void *) fidtc;
>  
> +	if (!(fid->metadata_areas_index = dm_hash_create(128))) {
> +		log_error("Couldn't create metadata index for format "
> +			  "instance of VG %s.", vgname);
> +		return 0;
> +	}
> +
> +	if (!attach_existing_mdas)
> +		goto out;
> +
>  	if (!vgname) {
>  		if (!(mda = dm_pool_zalloc(fid->fmt->cmd->mem, sizeof(*mda))))
>  			return_0;
> @@ -1977,12 +1988,6 @@ static int _create_vg_text_instance(struct format_instance *fid,
>  		mda->status = 0;
>  		fid_add_mda(fid, mda, NULL, 0, 0);
>  	} else {
> -		if (!(fid->metadata_areas_index = dm_hash_create(128))) {
> -			log_error("Couldn't create metadata index for format "
> -				  "instance of VG %s.", vgname);
> -			return 0;
> -		}
> -
>  		dir_list = &((struct mda_lists *) fid->fmt->private)->dirs;
>  
>  		dm_list_iterate_items(dl, dir_list) {
> @@ -2044,7 +2049,8 @@ static struct format_instance *_text_create_text_instance(const struct format_ty
>  							  const char *pvid,
>  							  const char *vgname,
>  							  const char *vgid,
> -							  void *context)
> +							  void *context,
> +							  int attach_existing_mdas)
>  {
>  	struct format_instance *fid;
>  	int r;
> @@ -2065,8 +2071,8 @@ static struct format_instance *_text_create_text_instance(const struct format_ty
>  	dm_list_init(&fid->metadata_areas_in_use);
>  	dm_list_init(&fid->metadata_areas_ignored);
>  
> -	r = pvid ? _create_pv_text_instance(fid, pvid) :
> -		   _create_vg_text_instance(fid, vgname, vgid, context);
> +	r = pvid ? _create_pv_text_instance(fid, pvid, attach_existing_mdas) :
> +		   _create_vg_text_instance(fid, vgname, vgid, context, attach_existing_mdas);
>  
>  	if (r)
>  		return fid;
> diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
> index f6ea0e5..dccc3af 100644
> --- a/lib/metadata/metadata.c
> +++ b/lib/metadata/metadata.c
> @@ -977,7 +977,7 @@ struct volume_group *vg_create(struct cmd_context *cmd, const char *vg_name)
>  	dm_list_init(&vg->removed_pvs);
>  
>  	if (!(vg->fid = cmd->fmt->ops->create_instance(cmd->fmt, NULL,
> -						vg_name, NULL, NULL))) {
> +					vg_name, NULL, NULL, 1))) {
>  		log_error("Failed to create format instance");
>  		goto bad;
>  	}
> @@ -1642,7 +1642,7 @@ struct physical_volume *pv_create(const struct cmd_context *cmd,
>  	}
>  
>  	if (!(pv->fid = fmt->ops->create_instance(fmt, (const char *) &pv->id,
> -						  NULL, NULL, NULL))) {
> +						  NULL, NULL, NULL, 0))) {
>  		log_error("Couldn't create format instance for PV %s.", pv_dev_name(pv));
>  		goto bad;
>  	}
> @@ -2637,10 +2637,13 @@ static struct volume_group *_vg_read_orphans(struct cmd_context *cmd,
>  		goto bad;
>  	}
>  
> -	/* create format instance with appropriate metadata area */
> +	/*
> +	 * Create an empty format instance. Metadata areas
> +	 * will be attached using consequent PV read calls.
> +	 */
>  	if (!(vg->fid = vginfo->fmt->ops->create_instance(vginfo->fmt, NULL,
>  							  orphan_vgname, NULL,
> -							  NULL))) {
> +							  NULL, 0))) {
>  		log_error("Failed to create format instance");
>  		goto bad;
>  	}
> @@ -2818,7 +2821,7 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
>  		use_precommitted = 0;
>  
>  	/* create format instance with appropriate metadata area */
> -	if (!(fid = fmt->ops->create_instance(fmt, NULL, vgname, vgid, NULL))) {
> +	if (!(fid = fmt->ops->create_instance(fmt, NULL, vgname, vgid, NULL, 1))) {
>  		log_error("Failed to create format instance");
>  		return NULL;
>  	}
> @@ -2973,7 +2976,7 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
>  			use_precommitted = 0;
>  
>  		/* create format instance with appropriate metadata area */
> -		if (!(fid = fmt->ops->create_instance(fmt, NULL, vgname, vgid, NULL))) {
> +		if (!(fid = fmt->ops->create_instance(fmt, NULL, vgname, vgid, NULL, 1))) {
>  			log_error("Failed to create format instance");
>  			return NULL;
>  		}
> @@ -3416,7 +3419,7 @@ static struct physical_volume *_pv_read(struct cmd_context *cmd,
>  	else {
>  		if (!(pv->fid = pv->fmt->ops->create_instance(pv->fmt,
>  						(const char *) &pv->id,
> -						NULL, NULL, NULL))) {
> +						NULL, NULL, NULL, 1))) {
>  			log_error("_pv_read: Couldn't create format instance "
>  				  "for PV %s", pv_name);
>  			goto bad;
> @@ -3936,6 +3939,16 @@ uint32_t vg_lock_newname(struct cmd_context *cmd, const char *vgname)
>  	return FAILED_EXIST;
>  }
>  
> +void change_vg_format_instance(struct volume_group *vg,
> +			       struct format_instance *fid)
> +{
> +	struct pv_list *pvl;
> +
> +	vg->fid = fid;
> +	dm_list_iterate_items(pvl, &vg->pvs)
> +		pvl->pv->fid = fid;
> +}
> +
>  static int _convert_key_to_string(const char *key, size_t key_len,
>  				  unsigned subkey, char *buf, size_t buf_len)
>  {
> diff --git a/lib/metadata/metadata.h b/lib/metadata/metadata.h
> index 0fbc954..bd638b5 100644
> --- a/lib/metadata/metadata.h
> +++ b/lib/metadata/metadata.h
> @@ -191,6 +191,7 @@ struct metadata_area *mda_copy(struct dm_pool *mem,
>  unsigned mda_is_ignored(struct metadata_area *mda);
>  void mda_set_ignored(struct metadata_area *mda, unsigned ignored);
>  unsigned mda_locns_match(struct metadata_area *mda1, struct metadata_area *mda2);
> +void change_vg_format_instance(struct volume_group *vg, struct format_instance *fid);
>  int fid_add_mda(struct format_instance *fid, struct metadata_area *mda,
>  		 const char *key, size_t key_len, const unsigned subkey);
>  int fid_add_mdas(struct format_instance *fid, struct dm_list *mdas,
> @@ -289,7 +290,8 @@ struct format_handler {
>  						    const char *pvid,
>  						    const char *vgname,
>  						    const char *vgid,
> -						    void *context);
> +						    void *context,
> +						    int attach_existing_mdas);
>  
>  	/*
>  	 * Destructor for format instance



^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH 06/17] Remove useless mdas parameter from PV read functions.
  2011-01-24 11:03 ` [PATCH 06/17] Remove useless mdas parameter from PV read functions Peter Rajnoha
@ 2011-01-25 14:44   ` Petr Rockai
  0 siblings, 0 replies; 36+ messages in thread
From: Petr Rockai @ 2011-01-25 14:44 UTC (permalink / raw)
  To: lvm-devel

Peter Rajnoha <prajnoha@redhat.com> writes:
> ...metadata areas are now stored within pv->fid.

looks OK

> Signed-off-by: Peter Rajnoha <prajnoha@redhat.com>
Reviewed-by: Petr Rockai <prockai@redhat.com>

> ---
>  lib/format1/format1.c            |    3 +--
>  lib/format_pool/format_pool.c    |    1 -
>  lib/format_text/format-text.c    |   15 +--------------
>  lib/metadata/metadata-exported.h |    4 ++--
>  lib/metadata/metadata.c          |   37 +++++++++++++------------------------
>  lib/metadata/metadata.h          |    3 +--
>  tools/pvremove.c                 |   10 ++++------
>  tools/pvresize.c                 |    8 +++-----
>  tools/toollib.c                  |   14 ++++++--------
>  9 files changed, 31 insertions(+), 64 deletions(-)
>
> diff --git a/lib/format1/format1.c b/lib/format1/format1.c
> index b79bd56..4f66cdc 100644
> --- a/lib/format1/format1.c
> +++ b/lib/format1/format1.c
> @@ -331,8 +331,7 @@ static int _format1_vg_write(struct format_instance *fid, struct volume_group *v
>  }
>  
>  static int _format1_pv_read(const struct format_type *fmt, const char *pv_name,
> -		    struct physical_volume *pv, struct dm_list *mdas __attribute__((unused)),
> -		    int scan_label_only __attribute__((unused)))
> +		    struct physical_volume *pv, int scan_label_only __attribute__((unused)))
>  {
>  	struct dm_pool *mem = dm_pool_create("lvm1 pv_read", 1024);
>  	struct disk_list *dl;
> diff --git a/lib/format_pool/format_pool.c b/lib/format_pool/format_pool.c
> index 3ecbfe9..24ccfc2 100644
> --- a/lib/format_pool/format_pool.c
> +++ b/lib/format_pool/format_pool.c
> @@ -206,7 +206,6 @@ static int _pool_pv_setup(const struct format_type *fmt __attribute__((unused)),
>  
>  static int _pool_pv_read(const struct format_type *fmt, const char *pv_name,
>  			 struct physical_volume *pv,
> -			 struct dm_list *mdas __attribute__((unused)),
>  			 int scan_label_only __attribute__((unused)))
>  {
>  	struct dm_pool *mem = dm_pool_create("pool pv_read", 1024);
> diff --git a/lib/format_text/format-text.c b/lib/format_text/format-text.c
> index a2f3d74..5dfe0b8 100644
> --- a/lib/format_text/format-text.c
> +++ b/lib/format_text/format-text.c
> @@ -1669,10 +1669,8 @@ static uint64_t _metadata_locn_offset_raw(void *metadata_locn)
>  }
>  
>  static int _text_pv_read(const struct format_type *fmt, const char *pv_name,
> -		    struct physical_volume *pv, struct dm_list *mdas,
> -		    int scan_label_only)
> +		    struct physical_volume *pv, int scan_label_only)
>  {
> -	struct metadata_area *mda, *mda_new;
>  	struct label *label;
>  	struct device *dev;
>  	struct lvmcache_info *info;
> @@ -1687,17 +1685,6 @@ static int _text_pv_read(const struct format_type *fmt, const char *pv_name,
>  	if (!_populate_pv_fields(info, pv, scan_label_only))
>  		return 0;
>  
> -	if (!mdas)
> -		return 1;
> -
> -	/* Add copy of mdas to supplied list */
> -	dm_list_iterate_items(mda, &info->mdas) {
> -		mda_new = mda_copy(fmt->cmd->mem, mda);
> -		if (!mda_new)
> -			return 0;
> -		dm_list_add(mdas, &mda_new->list);
> -	}
> -
>  	return 1;
>  }
>  
> diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
> index d8247dd..da62764 100644
> --- a/lib/metadata/metadata-exported.h
> +++ b/lib/metadata/metadata-exported.h
> @@ -340,8 +340,8 @@ int vg_revert(struct volume_group *vg);
>  struct volume_group *vg_read_internal(struct cmd_context *cmd, const char *vg_name,
>  			     const char *vgid, int warnings, int *consistent);
>  struct physical_volume *pv_read(struct cmd_context *cmd, const char *pv_name,
> -				struct dm_list *mdas, uint64_t *label_sector,
> -				int warnings, int scan_label_only);
> +				uint64_t *label_sector, int warnings,
> +				int scan_label_only);
>  struct dm_list *get_pvs(struct cmd_context *cmd);
>  
>  /*
> diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
> index dccc3af..591f7b5 100644
> --- a/lib/metadata/metadata.c
> +++ b/lib/metadata/metadata.c
> @@ -38,7 +38,6 @@ static struct physical_volume *_pv_read(struct cmd_context *cmd,
>  					struct dm_pool *pvmem,
>  					const char *pv_name,
>  					struct format_instance *fid,
> -					struct dm_list *mdas,
>  					uint64_t *label_sector,
>  					int warnings, int scan_label_only);
>  
> @@ -1330,14 +1329,11 @@ static int pvcreate_check(struct cmd_context *cmd, const char *name,
>  {
>  	struct physical_volume *pv;
>  	struct device *dev;
> -	struct dm_list mdas;
> -
> -	dm_list_init(&mdas);
>  
>  	/* FIXME Check partition type is LVM unless --force is given */
>  
>  	/* Is there a pv here already? */
> -	pv = pv_read(cmd, name, &mdas, NULL, 0, 0);
> +	pv = pv_read(cmd, name, NULL, 0, 0);
>  
>  	/*
>  	 * If a PV has no MDAs it may appear to be an orphan until the
> @@ -1345,10 +1341,10 @@ static int pvcreate_check(struct cmd_context *cmd, const char *name,
>  	 * this means checking every VG by scanning every PV on the
>  	 * system.
>  	 */
> -	if (pv && is_orphan(pv) && mdas_empty_or_ignored(&mdas)) {
> +	if (pv && is_orphan(pv) && !dm_list_size(&pv->fid->metadata_areas_in_use)) {
>  		if (!scan_vgs_for_pvs(cmd, 0))
>  			return_0;
> -		pv = pv_read(cmd, name, NULL, NULL, 0, 0);
> +		pv = pv_read(cmd, name, NULL, 0, 0);
>  	}
>  
>  	/* Allow partial & exported VGs to be destroyed. */
> @@ -1811,20 +1807,18 @@ struct physical_volume *find_pv_by_name(struct cmd_context *cmd,
>  static struct physical_volume *_find_pv_by_name(struct cmd_context *cmd,
>  			 			const char *pv_name)
>  {
> -	struct dm_list mdas;
>  	struct physical_volume *pv;
>  
> -	dm_list_init(&mdas);
> -	if (!(pv = _pv_read(cmd, cmd->mem, pv_name, NULL, &mdas, NULL, 1, 0))) {
> +	if (!(pv = _pv_read(cmd, cmd->mem, pv_name, NULL, NULL, 1, 0))) {
>  		log_error("Physical volume %s not found", pv_name);
>  		return NULL;
>  	}
>  
> -	if (is_orphan_vg(pv->vg_name) && mdas_empty_or_ignored(&mdas)) {
> +	if (is_orphan_vg(pv->vg_name) && !dm_list_size(&pv->fid->metadata_areas_in_use)) {
>  		/* If a PV has no MDAs - need to search all VGs for it */
>  		if (!scan_vgs_for_pvs(cmd, 1))
>  			return_NULL;
> -		if (!(pv = _pv_read(cmd, cmd->mem, pv_name, NULL, NULL, NULL, 1, 0))) {
> +		if (!(pv = _pv_read(cmd, cmd->mem, pv_name, NULL, NULL, 1, 0))) {
>  			log_error("Physical volume %s not found", pv_name);
>  			return NULL;
>  		}
> @@ -2649,8 +2643,8 @@ static struct volume_group *_vg_read_orphans(struct cmd_context *cmd,
>  	}
>  
>  	dm_list_iterate_items(info, &vginfo->infos) {
> -		if (!(pv = _pv_read(cmd, mem, dev_name(info->dev), vg->fid,
> -				    NULL, NULL, warnings, 0))) {
> +		if (!(pv = _pv_read(cmd, mem, dev_name(info->dev),
> +				    vg->fid, NULL, warnings, 0))) {
>  			continue;
>  		}
>  		if (!(pvl = dm_pool_zalloc(mem, sizeof(*pvl)))) {
> @@ -3360,10 +3354,10 @@ const char *find_vgname_from_pvname(struct cmd_context *cmd,
>   *   FIXME - liblvm todo - make into function that returns handle
>   */
>  struct physical_volume *pv_read(struct cmd_context *cmd, const char *pv_name,
> -				struct dm_list *mdas, uint64_t *label_sector,
> -				int warnings, int scan_label_only)
> +				uint64_t *label_sector, int warnings,
> +				int scan_label_only)
>  {
> -	return _pv_read(cmd, cmd->mem, pv_name, NULL, mdas, label_sector, warnings, scan_label_only);
> +	return _pv_read(cmd, cmd->mem, pv_name, NULL, label_sector, warnings, scan_label_only);
>  }
>  
>  /* FIXME Use label functions instead of PV functions */
> @@ -3371,7 +3365,6 @@ static struct physical_volume *_pv_read(struct cmd_context *cmd,
>  					struct dm_pool *pvmem,
>  					const char *pv_name,
>  					struct format_instance *fid,
> -					struct dm_list *mdas,
>  					uint64_t *label_sector,
>  					int warnings, int scan_label_only)
>  {
> @@ -3401,8 +3394,7 @@ static struct physical_volume *_pv_read(struct cmd_context *cmd,
>  	}
>  
>  	/* FIXME Move more common code up here */
> -	if (!(info->fmt->ops->pv_read(info->fmt, pv_name, pv, mdas,
> -	      scan_label_only))) {
> +	if (!(info->fmt->ops->pv_read(info->fmt, pv_name, pv, scan_label_only))) {
>  		log_error("Failed to read existing physical volume '%s'",
>  			  pv_name);
>  		goto bad;
> @@ -4239,8 +4231,5 @@ char *tags_format_and_copy(struct dm_pool *mem, const struct dm_list *tags)
>   */
>  struct physical_volume *pv_by_path(struct cmd_context *cmd, const char *pv_name)
>  {
> -	struct dm_list mdas;
> -
> -	dm_list_init(&mdas);
> -	return _pv_read(cmd, cmd->mem, pv_name, NULL, &mdas, NULL, 1, 0);
> +	return _pv_read(cmd, cmd->mem, pv_name, NULL, NULL, 1, 0);
>  }
> diff --git a/lib/metadata/metadata.h b/lib/metadata/metadata.h
> index bd638b5..7ebf85c 100644
> --- a/lib/metadata/metadata.h
> +++ b/lib/metadata/metadata.h
> @@ -241,8 +241,7 @@ struct format_handler {
>  	 * Return PV with given path.
>  	 */
>  	int (*pv_read) (const struct format_type * fmt, const char *pv_name,
> -			struct physical_volume * pv, struct dm_list *mdas,
> -			int scan_label_only);
> +			struct physical_volume * pv, int scan_label_only);
>  
>  	/*
>  	 * Tweak an already filled out a pv ready for importing into a
> diff --git a/tools/pvremove.c b/tools/pvremove.c
> index a8717e0..ace3c1d 100644
> --- a/tools/pvremove.c
> +++ b/tools/pvremove.c
> @@ -25,15 +25,12 @@ const char _really_wipe[] =
>  static int pvremove_check(struct cmd_context *cmd, const char *name)
>  {
>  	struct physical_volume *pv;
> -	struct dm_list mdas;
> -
> -	dm_list_init(&mdas);
>  
>  	/* FIXME Check partition type is LVM unless --force is given */
>  
>  	/* Is there a pv here already? */
>  	/* If not, this is an error unless you used -f. */
> -	if (!(pv = pv_read(cmd, name, &mdas, NULL, 1, 0))) {
> +	if (!(pv = pv_read(cmd, name, NULL, 1, 0))) {
>  		if (arg_count(cmd, force_ARG))
>  			return 1;
>  		log_error("Physical Volume %s not found", name);
> @@ -47,13 +44,14 @@ static int pvremove_check(struct cmd_context *cmd, const char *name)
>  	 * means checking every VG by scanning every
>  	 * PV on the system.
>  	 */
> -	if (is_orphan(pv) && !dm_list_size(&mdas)) {
> +	if (is_orphan(pv) && !dm_list_size(&pv->fid->metadata_areas_in_use) &&
> +	    !dm_list_size(&pv->fid->metadata_areas_ignored)) {
>  		if (!scan_vgs_for_pvs(cmd, 0)) {
>  			log_error("Rescan for PVs without metadata areas "
>  				  "failed.");
>  			return 0;
>  		}
> -		if (!(pv = pv_read(cmd, name, NULL, NULL, 1, 0))) {
> +		if (!(pv = pv_read(cmd, name, NULL, 1, 0))) {
>  			log_error("Failed to read physical volume %s", name);
>  			return 0;
>  		}
> diff --git a/tools/pvresize.c b/tools/pvresize.c
> index 8582ef4..4f1d610 100644
> --- a/tools/pvresize.c
> +++ b/tools/pvresize.c
> @@ -32,28 +32,26 @@ static int _pv_resize_single(struct cmd_context *cmd,
>  	uint64_t size = 0;
>  	uint32_t new_pe_count = 0;
>  	int r = 0;
> -	struct dm_list mdas;
>  	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;
>  
> -	dm_list_init(&mdas);
> -
>  	if (is_orphan_vg(vg_name)) {
>  		if (!lock_vol(cmd, vg_name, LCK_VG_WRITE)) {
>  			log_error("Can't get lock for orphans");
>  			return 0;
>  		}
>  
> -		if (!(pv = pv_read(cmd, pv_name, &mdas, NULL, 1, 0))) {
> +		if (!(pv = pv_read(cmd, pv_name, NULL, 1, 0))) {
>  			unlock_vg(cmd, vg_name);
>  			log_error("Unable to read PV \"%s\"", pv_name);
>  			return 0;
>  		}
>  
> -		mda_count = dm_list_size(&mdas);
> +		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);
>  
> diff --git a/tools/toollib.c b/tools/toollib.c
> index f76aacd..48f8ed5 100644
> --- a/tools/toollib.c
> +++ b/tools/toollib.c
> @@ -640,7 +640,7 @@ static int _process_all_devs(struct cmd_context *cmd, void *handle,
>  	}
>  
>  	while ((dev = dev_iter_get(iter))) {
> -		if (!(pv = pv_read(cmd, dev_name(dev), NULL, NULL, 0, 0))) {
> +		if (!(pv = pv_read(cmd, dev_name(dev), NULL, 0, 0))) {
>  			memset(&pv_dummy, 0, sizeof(pv_dummy));
>  			dm_list_init(&pv_dummy.tags);
>  			dm_list_init(&pv_dummy.segments);
> @@ -682,7 +682,6 @@ int process_each_pv(struct cmd_context *cmd, int argc, char **argv,
>  	struct str_list *sll;
>  	char *at_sign, *tagname;
>  	int scanned = 0;
> -	struct dm_list mdas;
>  
>  	dm_list_init(&tags);
>  
> @@ -724,10 +723,8 @@ int process_each_pv(struct cmd_context *cmd, int argc, char **argv,
>  				}
>  				pv = pvl->pv;
>  			} else {
> -
> -				dm_list_init(&mdas);
> -				if (!(pv = pv_read(cmd, argv[opt], &mdas,
> -						   NULL, 1, scan_label_only))) {
> +				if (!(pv = pv_read(cmd, argv[opt], NULL,
> +						   1, scan_label_only))) {
>  					log_error("Failed to read physical "
>  						  "volume \"%s\"", argv[opt]);
>  					ret_max = ECMD_FAILED;
> @@ -742,7 +739,8 @@ int process_each_pv(struct cmd_context *cmd, int argc, char **argv,
>  				 * PV on the system.
>  				 */
>  				if (!scanned && is_orphan(pv) &&
> -				    !dm_list_size(&mdas)) {
> +				    !dm_list_size(&pv->fid->metadata_areas_in_use) &&
> +				    !dm_list_size(&pv->fid->metadata_areas_ignored)) {
>  					if (!scan_label_only &&
>  					    !scan_vgs_for_pvs(cmd, 1)) {
>  						stack;
> @@ -751,7 +749,7 @@ int process_each_pv(struct cmd_context *cmd, int argc, char **argv,
>  					}
>  					scanned = 1;
>  					if (!(pv = pv_read(cmd, argv[opt],
> -							   NULL, NULL, 1,
> +							   NULL, 1,
>  							   scan_label_only))) {
>  						log_error("Failed to read "
>  							  "physical volume "



^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH 07/17] Add pv_add_metadata_area fn to support adding metadata areas on demand.
  2011-01-24 11:03 ` [PATCH 07/17] Add pv_add_metadata_area fn to support adding metadata areas on demand Peter Rajnoha
@ 2011-01-25 14:48   ` Petr Rockai
  0 siblings, 0 replies; 36+ messages in thread
From: Petr Rockai @ 2011-01-25 14:48 UTC (permalink / raw)
  To: lvm-devel

Peter Rajnoha <prajnoha@redhat.com> writes:

> My previous version of the patch used the cache and that was not quite
> a happy solution (but it was easy to use :)) since any revert would
> be quite complex (or we'd need to destroy the cache item and rescan).

> Now, we can use the format_instance to store metadata areas. If anything
> goes wrong, we can just throw the instance away and create a new one to
> work with (so we don't need to revert the cache or rescan).

This one looks OK. I see a lot of overlap with existing PV manipulation
code, but from scanning the whole bundle I think this is addressed in a
later patch.

> Signed-off-by: Peter Rajnoha <prajnoha@redhat.com>
Reviewed-by: Petr Rockai <prockai@redhat.com>

(One minor tweak below)

> ---
>  lib/format_text/format-text.c |  245 +++++++++++++++++++++++++++++++++++++++++
>  lib/format_text/format-text.h |    5 +
>  lib/metadata/metadata.h       |   10 ++
>  3 files changed, 260 insertions(+), 0 deletions(-)
>
> diff --git a/lib/format_text/format-text.c b/lib/format_text/format-text.c
> index 5dfe0b8..cf18f25 100644
> --- a/lib/format_text/format-text.c
> +++ b/lib/format_text/format-text.c
> @@ -2031,6 +2031,250 @@ static int _create_vg_text_instance(struct format_instance *fid,
>  	return 1;
>  }
>  
> +int add_metadata_area_to_pv(struct physical_volume *pv,
> +			    unsigned mda_index,
> +			    uint64_t mda_start,
> +			    uint64_t mda_size,
> +			    unsigned mda_ignored)
> +{
> +	struct metadata_area *mda;
> +	struct mda_context *mdac;
> +	struct mda_lists *mda_lists = (struct mda_lists *) pv->fmt->private;
> +
> +	if (mda_index >= FMT_TEXT_MAX_MDAS_PER_PV) {
> +		log_error(INTERNAL_ERROR "can't add metadata area with "
> +					 "index %u to PV %s. Metadata "
> +					 "layout not supported by %s format.",
> +					  mda_index, dev_name(pv->dev),
> +					  pv->fmt->name);
> +	}
> +
> +	if (!(mda = dm_malloc(sizeof(struct metadata_area)))) {
> +		log_error("struct metadata_area allocation failed");
> +		return 0;
> +	}
> +
> +	if (!(mdac = dm_malloc(sizeof(struct mda_context)))) {
> +		log_error("struct mda_context allocation failed");
> +		dm_free(mda);
> +		return 0;
> +	}
> +
> +	mda->ops = mda_lists->raw_ops;
> +	mda->metadata_locn = mdac;
> +	mda->status = 0;
> +
> +	mdac->area.dev = pv->dev;
> +	mdac->area.start = mda_start;
> +	mdac->area.size = mda_size;
> +	mdac->free_sectors = UINT64_C(0);
> +	memset(&mdac->rlocn, 0, sizeof(mdac->rlocn));
> +	mda_set_ignored(mda, mda_ignored);
> +
> +	fid_add_mda(pv->fid ? pv->fid : pv->vg->fid, mda,
> +		    (char *) &pv->id, ID_LEN, mda_index);
> +
> +	return 1;
> +}
> +
> +static int _text_pv_add_metadata_area(const struct format_type *fmt,
> +				      struct physical_volume *pv,
> +				      int pe_start_locked,
> +				      unsigned mda_index,
> +				      uint64_t mda_size,
> +				      unsigned mda_ignored)
> +{
> +	struct format_instance *fid = pv->fid;
> +	const char *pvid = (char *) &pv->id;
> +	uint64_t pe_start, pe_end;
> +	uint64_t alignment, alignment_offset;
> +	uint64_t disk_size;
> +	uint64_t mda_start;
> +	uint64_t adjustment, limit;
> +	uint64_t wipe_size = 8 << SECTOR_SHIFT;
> +	size_t page_size = lvm_getpagesize();
> +	struct metadata_area *mda;
> +	struct mda_context *mdac;
> +
> +	if (mda_index >= FMT_TEXT_MAX_MDAS_PER_PV) {
> +		log_error(INTERNAL_ERROR "invalid index of value %u used "
> +			      "while trying to add metadata area on PV %s. "
> +			      "Metadata layout not supported by %s format.",
> +			       mda_index, pv_dev_name(pv), fmt->name);
> +		return 0;
> +	}
> +
> +	pe_start = pv->pe_start << SECTOR_SHIFT;
> +	alignment = pv->pe_align << SECTOR_SHIFT;
> +	alignment_offset = pv->pe_align_offset << SECTOR_SHIFT;
> +	disk_size = pv->size << SECTOR_SHIFT;
> +	mda_size = mda_size << SECTOR_SHIFT;
> +
> +	if (fid_get_mda_indexed(fid, pvid, ID_LEN, mda_index)) {
> +		log_error(INTERNAL_ERROR "metadata area with index %u already "
> +			"exists on PV %s.", mda_index, pv_dev_name(pv));
> +		return 0;
> +	}
> +
> +	/* First metadata area at the start of the device. */
> +	if (mda_index == 0) {
> +		/*
> +		 * Try to fit MDA0 end within given pe_start limit if its value
> +		 * is locked. If it's not locked, count with any existing MDA1.
> +		 * If there's no MDA1, just use disk size as the limit.
> +		 */
> +		if (pe_start_locked)
> +			limit = pe_start;
> +		else if ((mda = fid_get_mda_indexed(fid, pvid, ID_LEN, 1)) &&
> +			 (mdac = mda->metadata_locn))
> +			limit = mdac->area.start;
> +		else
> +			limit = disk_size;
> +
> +		if (limit > disk_size)
> +			goto bad;
> +
> +		mda_start = LABEL_SCAN_SIZE;
> +
> +		/* Align MDA0 start with page size if possible. */
> +		if (limit - mda_start >= MDA_SIZE_MIN) {
> +			if ((adjustment = mda_start % page_size))
> +				mda_start += (page_size - adjustment);
> +		}
> +
> +		/* Align MDA0 end position with given alignment if possible. */
> +		if (alignment) {
> +			if ((adjustment = (mda_start + mda_size) % alignment)) {
> +				mda_size += (alignment - adjustment);
> +				if (mda_start + mda_size > limit)
> +					mda_size -= (alignment - adjustment);
> +			}
> +		}
> +
> +		/* Align MDA0 end position with given alignment offset if possible. */
> +		if (alignment_offset &&
> +		    (((mda_start + mda_size) % alignment) == 0)) {
> +			mda_size += alignment_offset;
> +			if (mda_start + mda_size > limit)
> +				mda_size -= alignment_offset;
> +		}
> +
> +		if (mda_start + mda_size > limit) {
> +			log_warn("WARNING: metadata area size outreaches "
> +				 "a limit on PV %s specified by its %s. "
> +				 "Trying to adjust metadata area size.",
> +				  pv_dev_name(pv),
> +				  pe_start_locked ? "PE start" : "disk size");
> +
> +			/*
> +			 * Try to decrease the MDA0 size with twice the
> +			 * alignment and then align with given alignment.
> +			 * If pe_start is locked, skip this type of
> +			 * alignment since it would be useless.
> +			 * Check first whether we can apply that!
> +			 */
> +			if (!pe_start_locked &&
> +			    ((limit - mda_start) > alignment * 2)) {
> +				mda_size = limit - mda_start - alignment * 2;
> +
> +				if ((adjustment = (mda_start + mda_size) % alignment))
> +					mda_size += (alignment - adjustment);
> +
> +				/* Still too much? Then there's nothing else to do. */
> +				if (mda_start + mda_size > limit)
> +					goto bad;
> +			}
> +			/* Otherwise, give up and take any usable space. */
> +			/* FIXME: We should probably check for some minimum MDA size here. */
> +			else
> +				mda_size = limit - mda_start;
> +		}
> +
> +		/*
> +		 * If PV's pe_start is not locked, update pe_start value with the
> +		 * start of the area that follows the MDA0 we've just calculated.
> +		 */
> +		if (!pe_start_locked) {
> +			pe_start = mda_start + mda_size;
> +			pv->pe_start = pe_start >> SECTOR_SHIFT;
> +		}
> +	}
> +	/* Second metadata area at the end of the device. */
> +	else {
> +		/*
> +		 * Try to fit MDA1 start within given pe_end or pe_start limit
> +		 * if it's locked. If pe_start and pe_end are not defined yet,
> +		 * count with any existing MDA0 and pe_start. If MDA0 does not
> +		 * exist, just use LABEL_SCAN_SIZE.
> +		 */
> +		pe_end = pv->pe_count ? (pv->pe_start +
> +					 pv->pe_count * pv->pe_size - 1) << SECTOR_SHIFT
> +				      : 0;
> +		if (pe_start_locked)
> +			limit = pe_end ? pe_end : pe_start;
> +		else if (pe_start)
> +			limit = pe_start;
> +		/*
> +		 * Normally MDA0's start + size should be pe_start.
> +		 * The statemet here is probably useless since the
> +		 * situation is covered by previous statement.
> +		 */
> +		else if ((mda = fid_get_mda_indexed(fid, pvid, ID_LEN, 0)) &&
> +			 (mdac = mda->metadata_locn))
> +			limit = mdac->area.start + mdac->area.size;
> +		else
> +			limit = LABEL_SCAN_SIZE;
> +
> +		if (limit > disk_size || mda_size > disk_size)
> +			goto bad;
> +
> +		mda_start = disk_size - mda_size;
> +
> +		if (alignment) {
> +			adjustment = mda_start % alignment;
> +			if (adjustment)
> +				mda_size += adjustment;
> +		}
> +
> +		if (disk_size - mda_size < limit)
> +			mda_size = disk_size - limit;
> +
> +		/*
> +		 * If PV's pe_end not set yet, set it to the end of the
> +		 * area that precedes the MDA1 we've just calculated.
> +		 * FIXME: do we need to set this? Isn't it always set before?
> +		 */
> +		/*if (!pe_end) {
> +			pe_end = mda_start;
> +			pv->pe_end = pe_end >> SECTOR_SHIFT;
> +		}*/
> +	}
> +
> +	if (mda_size) {
> +		/* Wipe metadata area with zeroes. */
> +		if (!dev_set((struct device *) pv->dev, mda_start,
> +			(size_t) (mda_size > wipe_size ? : mda_size), 0)) {
> +				log_error("Failed to wipe new metadata area "
> +					  "at the %s of the %s",
> +					   mda_index ? "end" : "start",
> +					   pv_dev_name(pv));
> +				return 0;
> +		}
> +
> +		/* Finally, add new metadata area to PV's format instance. */
> +		if (!add_metadata_area_to_pv(pv, mda_index, mda_start,
> +					     mda_size, mda_ignored))
> +			return_0;
> +	}
> +
> +	return 1;
> +
> +bad:

^^ Should this label be renamed to nospace or no_space for clarity?

> +	log_error("Not enough space available for metadata area "
> +		  "with index %u on PV %s.", mda_index, pv_dev_name(pv));
> +	return 0;
> +}
> +
>  /* 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 char *pvid,
> @@ -2111,6 +2355,7 @@ static struct format_handler _text_handler = {
>  	.scan = _text_scan,
>  	.pv_read = _text_pv_read,
>  	.pv_setup = _text_pv_setup,
> +	.pv_add_metadata_area = _text_pv_add_metadata_area,
>  	.pv_write = _text_pv_write,
>  	.vg_setup = _text_vg_setup,
>  	.lv_setup = _text_lv_setup,
> diff --git a/lib/format_text/format-text.h b/lib/format_text/format-text.h
> index f3cf4f5..f65be74 100644
> --- a/lib/format_text/format-text.h
> +++ b/lib/format_text/format-text.h
> @@ -56,6 +56,11 @@ int add_da(struct dm_pool *mem, struct dm_list *das,
>  	   uint64_t start, uint64_t size);
>  void del_das(struct dm_list *das);
>  
> +int add_metadata_area_to_pv(struct physical_volume *pv,
> +			    unsigned mda_index,
> +			    uint64_t mda_start,
> +			    uint64_t mda_size,
> +			    unsigned mda_ignored);
>  int add_mda(const struct format_type *fmt, struct dm_pool *mem, struct dm_list *mdas,
>  	    struct device *dev, uint64_t start, uint64_t size, unsigned ignored);
>  void del_mdas(struct dm_list *mdas);
> diff --git a/lib/metadata/metadata.h b/lib/metadata/metadata.h
> index 7ebf85c..0da8b3d 100644
> --- a/lib/metadata/metadata.h
> +++ b/lib/metadata/metadata.h
> @@ -256,6 +256,16 @@ struct format_handler {
>  			 struct physical_volume * pv, struct volume_group * vg);
>  
>  	/*
> +	 * Add metadata area to a PV. Changes will take effect on pv_write.
> +	 */
> +	int (*pv_add_metadata_area) (const struct format_type * fmt,
> +				     struct physical_volume * pv,
> +				     int pe_start_locked,
> +				     unsigned metadata_index,
> +				     uint64_t metadata_size,
> +				     unsigned metadata_ignored);
> +
> +	/*
>  	 * 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
>  	 */



^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH 02/17] Add supporting functions for metadata areas stored in format instance.
  2011-01-25 13:16   ` Petr Rockai
@ 2011-01-26 10:38     ` Peter Rajnoha
  2011-01-26 13:59       ` Petr Rockai
  2011-01-26 14:06       ` Petr Rockai
  0 siblings, 2 replies; 36+ messages in thread
From: Peter Rajnoha @ 2011-01-26 10:38 UTC (permalink / raw)
  To: lvm-devel

On 01/25/2011 02:16 PM +0100, Petr Rockai wrote:
>>  struct format_instance {
>>  	const struct format_type *fmt;
>> +	int pv_only;
> 
> Could this be changed to an enumerated "type" field, instead of pv_only?
> If I understand correctly, types are mutually exclusive anyway, and
> pv_only is rather confusing and non-obvious when reading the code.
> 

Yes, these are mutually exclusive and it'll always be only a switch
between PV and VG, or I hope so... Using a enumerated type field - OK,
no problem, whatever that makes the switch...

>> +
>>  	/*
>>  	 * Each mda in a vg is on exactly one of the below lists.
>>  	 * MDAs on the 'in_use' list will be read from / written to
>> @@ -181,6 +183,7 @@ struct format_instance {
>>  	 */
>>  	struct dm_list metadata_areas_in_use;
>>  	struct dm_list metadata_areas_ignored;
>> +	void *metadata_areas_index;
> 
> I don't currently expect that we would need as much genericity as void *
> offers (and that we could use a little extra safety). Would an union be
> better here, with an explicit list of types that can go in?
> 

Well, my incentive here was to keep this for any future changes so the
format-specific code can decide and use any type of index we can imagine.
We have this "metadata.c" layer and then the "format-specific" layer
underneath that. So adding any new format with a brand new indexing
scheme that is fine-tuned and suitable for that one new format would
require breaking the abstraction layer (so defining a new type of index
used in new format in the "metadata.c" layer above). So my incentive was
to make the index transparent for the "metadata.c" layer.

(I know, we have these "fid_{add,remove,get}_mda" functions that work
directly with the index in "metadata.c" now, but that may eventually
evolve into format-specific "fid" functions later. But since we have
only one format that actually make real use of the format instance,
I kept it in that metadata.c layer for now...)

But if we expect to use the same index scheme all the time for all
possible formats, not changing it too much, then sure, we can use a
union there... But I'd like to avoid too much editing in the future :)

>> +static int _convert_key_to_string(const char *key, size_t key_len,
>> +				  unsigned subkey, char *buf, size_t buf_len)
>>  {
>> +	memcpy(buf, key, key_len);
>> +	buf += key_len;
>> +	buf_len -= key_len;
>> +	if ((dm_snprintf(buf, buf_len, "_%u", subkey) == -1))
>> +		return_0;
>> +
>> +	return 1;
>> +}
> 
> Would it be better to require that key is NULL-terminated? It would
> simplify a lot of code, by not needing to pass the length as an extra

...if we can make sure that PV id is always terminated with 0, then OK.
But otherwise we would need to call this "convert_to_string" function
everywhere around the code (actually that was in my original working
version of this patchset, then I decided to put it in one place instead).

> parameter everywhere. I know that currently we keep the PV/VG/... IDs in
> unterminated strings, but I am quite sure this is not a good idea. I
> wouldn't expect it to be a *lot* of work to change things to keep a NULL
> termination in there as well. Maybe in a followup patch?

..thing with PV id is that we store that as a "struct id" which internally
is an array of integeres... Hmm, so you want to put another array item with
0 at the end?

BTW, we also do this "convert_to_string" in the cache code... So yes, maybe
it would be fine to clean this up somehow...

> 
>> +int fid_add_mda(struct format_instance *fid, struct metadata_area *mda,
>> +		 const char *key, size_t key_len, const unsigned subkey)
>> +{
>> +	char extended_key[PATH_MAX];
>> +
>>  	dm_list_add(mda_is_ignored(mda) ? &fid->metadata_areas_ignored :
>>  					  &fid->metadata_areas_in_use, &mda->list);
>> +
>> +	/*
>> +	 * Return if the mda is not supposed to be
>> +	 * indexed or the index itself is not initialised */
>> +	if (!key || !fid->metadata_areas_index)
>> +		return 1;
>> +
>> +	if (!_convert_key_to_string(key, key_len, subkey,
>> +				    extended_key, PATH_MAX))
>> +		return_0;
>> +
>> +	/* Add metadata area to index. */
>> +	if (fid->pv_only)
>> +		((struct metadata_area **)fid->metadata_areas_index)[subkey] = mda;
> 
> In this branch, all the extended_key logic above is useless. It could be
> made more obvious that only the else branch needs extended_key, by
> restructuring the code. Also, is key, subkey and extended_key the right
> naming scheme? Maybe full_key instead of extended? And maybe sub_key,
> for consistency?
> 

OK...

>> +struct metadata_area *fid_get_mda_indexed(struct format_instance *fid,
>> +					  const char *key, size_t key_len,
>> +					  const unsigned subkey)
>> +{
>> +	char extended_key[PATH_MAX];
>> +	struct metadata_area *mda = NULL;
>> +
>> +	if (!_convert_key_to_string(key, key_len, subkey,
>> +				    extended_key, PATH_MAX))
>> +		return_NULL;
>> +
>> +	if (fid->pv_only)
>> +		mda = ((struct metadata_area **)fid->metadata_areas_index)[subkey];
>> +	else
>> +		mda = (struct metadata_area *) dm_hash_lookup(fid->metadata_areas_index,
>> +							      extended_key);
> 
> Same about extended_key as above (both path coverage and naming).
> 

OK...

>> +int fid_remove_mda(struct format_instance *fid, struct metadata_area *mda,
>> +		   const char *key, size_t key_len, const unsigned subkey)
>> +{
>> +	struct metadata_area *mda_indexed = NULL;
>> +	char extended_key[PATH_MAX];
>> +
>> +	/* At least one of mda or key must be specified. */
>> +	if (!mda && !key)
>> +		return 1;
>> +
>> +	if (key) {
>> +		/*
>> +		 * If both mda and key specified, check given mda
>> +		 * with what we find using the index and return
>> +		 * immediately if these two do not match.
>> +		 */
>> +		if (!(mda_indexed = fid_get_mda_indexed(fid, key, key_len, subkey)) ||
>> +		     (mda && mda != mda_indexed))
>> +			return 1;
>> +
>> +		if (!_convert_key_to_string(key, key_len, subkey,
>> +					    extended_key, PATH_MAX))
>> +			return_0;
>> +
>> +		mda = mda_indexed;
>> +
>> +		if (fid->pv_only)
>> +			((struct metadata_area**)fid->metadata_areas_index)[subkey] = NULL;
>> +		else
>> +			dm_hash_remove(fid->metadata_areas_index, extended_key);
> 
> Redundant code paths again.
> 

OK... :)

Peter



^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH 04/17] Add format_instance support for pv_read.
  2011-01-25 13:30   ` Petr Rockai
@ 2011-01-26 11:05     ` Peter Rajnoha
  2011-01-26 11:12       ` Peter Rajnoha
  0 siblings, 1 reply; 36+ messages in thread
From: Peter Rajnoha @ 2011-01-26 11:05 UTC (permalink / raw)
  To: lvm-devel

On 01/25/2011 02:30 PM +0100, Petr Rockai wrote:
> Peter Rajnoha <prajnoha@redhat.com> writes:
> 
>> We don't need to store metadata areas in a separate "mdas" parameter
>> since it is in the pv->fid now. If the fid is not defined yet and is
>> NULL, pv_read code will create a new one (if there's no VG fid yet
>> where the metadata areas read off of a PV should be attached to).
> 
> This is somewhat hairy... With this patch, it's starting to seem that PV
> will sometimes point to a VG FID and other times to PV FID. Is there a
> good reason for that? Is the PV FID only used with orphan PVs?
> 

Well, we have plain PVs that are not part of any real VG yet, the orphan. BUT
we don't want to group them into an orphan VG (that would require collecting
all mdas from all orphan VGs). In this case, we have a pure PV fid defined
(this fid will include *only* the mdas on that PV).

Then we have plain PVs that are not part of any real VG yet, but are grouped
together into a virtual "orphan" VG. From fid's point of view, this is a VG
like any other, so the pv->fid references the VG-based pv->vg->fid.

Then we have PVs that are part of a real VG. These also have the pv->fid
referencing the pv->vg->fid.

This way, we can use the pv->fid transparently - we don't actually care
whether it is PV-based or VG-based fid, we only need to access the
mdas. Whether these mdas are store together in a pool with mdas from
other PVs (when in a VG) or they are just standalone mdas from that
one PV, we don't care. It makes writing the code easier. We don't
need to check that anymore...

> I think this is something that really needs to be documented. If nothing

..OK, I'll try to add some comments.

> else, the format_instance type value (as suggested in an earlier
> comment) should read ORPHAN_PV_FID and VG_FID. It also does raise the

Actually, ORPHAN_VG_FID, VG_FID and PV_FID. But since ORPHAN_VG_FID == VG_FID
from fid's point of view, we have the separation PV_FID and VG_FID only
(which is exactly what the format_instance->pv_only flag is about)

> question, why we don't always use VG_FID even for orphans, given how we

E.g. creating a new PV, modifying just one PV etc. - there's no need to group
and store all the other mdas that are in that "virtual" orphan VG.
If we want to group that for some complex situations, OK. But it's useless
for simple modification done only on one PVs (iow, creating orphan VG fid
means collecting all mdas from all PVs not in a VG yet. And that could
be uselessly time-consuming for simple PV-only operations since we would
throw all that information away anyway).

> have an orphans VG? Would simply using the orphans VG FID be more
> consistent overall?
> 

Please, let's not group into orphan VG where it's not really needed...

>> +	if (fid)
>> +		fid_add_mdas(fid, &info->mdas, (const char *) &pv->id, ID_LEN);
>> +	else {
>> +		if (!(pv->fid = pv->fmt->ops->create_instance(pv->fmt,
>> +						(const char *) &pv->id,
>> +						NULL, NULL, NULL))) {
>> +			log_error("_pv_read: Couldn't create format instance "
>> +				  "for PV %s", pv_name);
>> +			goto bad;
>> +		}
>> +	}
>> +
> 
> The code above is certainly confusing. A comment is needed, explaining
> what is going on. Please explain that non-NULL "fid" means that this PV
> belongs to a VG, and the fid variable points to that VG's fid.
> 

It's because this _pv_read could be part of a vg_read (e.g. _vg_read_orphans).
So creating a standalone PV fid that would be destroyed immediately and
replaced by orphan VG fid would be useless, so it's better to pass the existing
fid in. So if it's defined already, we just merge PVs mdas into the fid and if
not, we create the new PV-based fid.

> Also, why mdas are added to the VG fid, but the (orphan) PV fid is left
> empty? Should the code read
> 
> if (!fid) {
>     if (!(fid = pv->fid = ...
> }
> 
> fid_add_mdas(fid, ...)
> 

The fid_add_mdas is part of the create_instance fn, so you would call that
code twice... (but this is related to the next patch also and I've seen the
comment briefly, so I'll reply there :) )

> ?
> 
> If, as I suspect, it's because create_instance adds the MDA's itself,
> please add a comment to that effect. (Also, is it necessary that
> create_instance does this? I am not sure it is entirely intuitive...)
> 

...

Peter



^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH 04/17] Add format_instance support for pv_read.
  2011-01-26 11:05     ` Peter Rajnoha
@ 2011-01-26 11:12       ` Peter Rajnoha
  0 siblings, 0 replies; 36+ messages in thread
From: Peter Rajnoha @ 2011-01-26 11:12 UTC (permalink / raw)
  To: lvm-devel

On 01/26/2011 12:05 PM +0100, Peter Rajnoha wrote:
> It's because this _pv_read could be part of a vg_read (e.g. _vg_read_orphans).

..for the other "vg_read", we call the other fn, the _read_pv (_pv_read - read_pv
nice :) ). That one already handles the fid through the "fid" parameter and
then we call add_pvl_to_vgs which does the job of referencing the pv->fid to pv->vg->fid
(the format instance is already done before that where we create the VG-based
fid). So everything is tied together nicely...

Peter



^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH 05/17] Add attach_existing_mdas parameter to create_instance fn.
  2011-01-25 14:43   ` Petr Rockai
@ 2011-01-26 13:24     ` Peter Rajnoha
  0 siblings, 0 replies; 36+ messages in thread
From: Peter Rajnoha @ 2011-01-26 13:24 UTC (permalink / raw)
  To: lvm-devel

On 01/25/2011 03:43 PM +0100, Petr Rockai wrote:
> Peter Rajnoha <prajnoha@redhat.com> writes:
> 
>> If attach_existing_mdas parameter is set, we'll attach any existing
>> metadata areas found in the cache to the format_instance. Otherwise,
>> we will only initialise the format_instance and keep the metadata
>> areas list empty (so we can fill that later if that's needed).
> 
> As hinted in previous comment, I think it would be better to never
> attach existing MDAs in create_instance and simply have a single call to
> do that when it is needed. create_instance parameter list is already a
> mess...
> 

...

>> @@ -41,7 +41,8 @@ static struct format_instance *_text_create_text_instance(const struct format_ty
>>  							  const char *pvid,
>>  							  const char *vgname,
>>  							  const char *vgid,
>> -							  void *context);
>> +							  void *context,
>> +							  int attach_existing_mdas);
>>  

Yes, I was thinking whether we should separate these somehow first - at least
pv_create_instance/vg_create_instance... Hmm. But that's a detail. As for the other
parameters - vgname/vgid is necessary and context - well I'm afraid we need that too
to handle those special cases with (current) format - the location of the mda in
filesystem (metadata backup...).

The "attach_existing_mdas" vs. calling separate function to fill the format instance
with mdas - hmm, I'll think about that and see how it fits in...

Peter



^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH 02/17] Add supporting functions for metadata areas stored in format instance.
  2011-01-26 10:38     ` Peter Rajnoha
@ 2011-01-26 13:59       ` Petr Rockai
  2011-01-26 14:06       ` Petr Rockai
  1 sibling, 0 replies; 36+ messages in thread
From: Petr Rockai @ 2011-01-26 13:59 UTC (permalink / raw)
  To: lvm-devel

Peter Rajnoha <prajnoha@redhat.com> writes:
>>> +	void *metadata_areas_index;
>> 
>> I don't currently expect that we would need as much genericity as void *
>> offers (and that we could use a little extra safety). Would an union be
>> better here, with an explicit list of types that can go in?
>> 
>
> Well, my incentive here was to keep this for any future changes so the
> format-specific code can decide and use any type of index we can imagine.
> We have this "metadata.c" layer and then the "format-specific" layer
> underneath that. So adding any new format with a brand new indexing
> scheme that is fine-tuned and suitable for that one new format would
> require breaking the abstraction layer (so defining a new type of index
> used in new format in the "metadata.c" layer above). So my incentive was
> to make the index transparent for the "metadata.c" layer.
>
> (I know, we have these "fid_{add,remove,get}_mda" functions that work
> directly with the index in "metadata.c" now, but that may eventually
> evolve into format-specific "fid" functions later. But since we have
> only one format that actually make real use of the format instance,
> I kept it in that metadata.c layer for now...)
>
> But if we expect to use the same index scheme all the time for all
> possible formats, not changing it too much, then sure, we can use a
> union there... But I'd like to avoid too much editing in the future :)

Well, I think you are deluding yourself about that. Plenty of other such
things is hard-coded all over the place and I am fairly sure adding an
union member is going to be the least of your worries at that point.

I wouldn't say anything if this came for free, but you are obviously
trading code safety and maintainability (which are fairly concrete) for
easier extendability (which is fairly hypothetical). I would opt for the
first, if faced with this kind of a tradeoff. YAGNI (You Aren't Gonna
Need It), anyway.

Yours,
   Petr

PS: If you want to make the format instance actually opaque, you should
move it out of metadata.{h,c} completely, into format_text, and only
have an opaque pointer (void * typedef) in VG/PV.



^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH 02/17] Add supporting functions for metadata areas stored in format instance.
  2011-01-26 10:38     ` Peter Rajnoha
  2011-01-26 13:59       ` Petr Rockai
@ 2011-01-26 14:06       ` Petr Rockai
  1 sibling, 0 replies; 36+ messages in thread
From: Petr Rockai @ 2011-01-26 14:06 UTC (permalink / raw)
  To: lvm-devel

Peter Rajnoha <prajnoha@redhat.com> writes:

>> parameter everywhere. I know that currently we keep the PV/VG/... IDs in
>> unterminated strings, but I am quite sure this is not a good idea. I
>> wouldn't expect it to be a *lot* of work to change things to keep a NULL
>> termination in there as well. Maybe in a followup patch?
>
> ..thing with PV id is that we store that as a "struct id" which internally
> is an array of integeres... Hmm, so you want to put another array item with
> 0 at the end?
>
> BTW, we also do this "convert_to_string" in the cache code... So yes, maybe
> it would be fine to clean this up somehow...

Well, I don't see a problem with making the array ID_LEN + 1 instead of
ID_LEN and storing a 0 element at the end. It's always used as a
character array anyway, and we can save significant amount of
boilerplate by having that 0 in there.

Yours,
   Petr



^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH 08/17] Add pv_remove_metadata_area fn to support removing metadata areas on demand.
  2011-01-24 11:03 ` [PATCH 08/17] Add pv_remove_metadata_area fn to support removing " Peter Rajnoha
@ 2011-01-28 15:31   ` Petr Rockai
  0 siblings, 0 replies; 36+ messages in thread
From: Petr Rockai @ 2011-01-28 15:31 UTC (permalink / raw)
  To: lvm-devel

Peter Rajnoha <prajnoha@redhat.com> writes:

> The same as for pv_add_metadata_area, but removing...
These look OK (although the FMT_TEXT_MAX_MDAS_PER_PV is a bit fiddly).

> Signed-off-by: Peter Rajnoha <prajnoha@redhat.com>
Reviewed-by: Petr Rockai <prockai@redhat.com>

> ---
>  lib/format_text/format-text.c |   24 ++++++++++++++++++++++++
>  lib/format_text/format-text.h |    2 ++
>  lib/metadata/metadata.h       |    7 +++++++
>  3 files changed, 33 insertions(+), 0 deletions(-)
>
> diff --git a/lib/format_text/format-text.c b/lib/format_text/format-text.c
> index cf18f25..99f691f 100644
> --- a/lib/format_text/format-text.c
> +++ b/lib/format_text/format-text.c
> @@ -2275,6 +2275,29 @@ bad:
>  	return 0;
>  }
>  
> +int remove_metadata_area_from_pv(struct physical_volume *pv,
> +				 unsigned mda_index)
> +{
> +	if (mda_index >= FMT_TEXT_MAX_MDAS_PER_PV) {
> +		log_error(INTERNAL_ERROR "can't remove metadata area with "
> +					 "index %u from PV %s. Metadata "
> +					 "layou not supported by %s format.",
> +					  mda_index, dev_name(pv->dev),
> +					  pv->fmt->name);
> +		return 0;
> +	}
> +
> +	return fid_remove_mda(pv->fid, NULL, (const char *) &pv->id,
> +			      ID_LEN, mda_index);
> +}
> +
> +static int _text_pv_remove_metadata_area(const struct format_type *fmt,
> +					 struct physical_volume *pv,
> +					 unsigned mda_index)
> +{
> +	return remove_metadata_area_from_pv(pv, mda_index);
> +}
> +
>  /* 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 char *pvid,
> @@ -2356,6 +2379,7 @@ static struct format_handler _text_handler = {
>  	.pv_read = _text_pv_read,
>  	.pv_setup = _text_pv_setup,
>  	.pv_add_metadata_area = _text_pv_add_metadata_area,
> +	.pv_remove_metadata_area = _text_pv_remove_metadata_area,
>  	.pv_write = _text_pv_write,
>  	.vg_setup = _text_vg_setup,
>  	.lv_setup = _text_lv_setup,
> diff --git a/lib/format_text/format-text.h b/lib/format_text/format-text.h
> index f65be74..694b5c1 100644
> --- a/lib/format_text/format-text.h
> +++ b/lib/format_text/format-text.h
> @@ -61,6 +61,8 @@ int add_metadata_area_to_pv(struct physical_volume *pv,
>  			    uint64_t mda_start,
>  			    uint64_t mda_size,
>  			    unsigned mda_ignored);
> +int remove_metadata_area_from_pv(struct physical_volume *pv,
> +				 unsigned mda_index);
>  int add_mda(const struct format_type *fmt, struct dm_pool *mem, struct dm_list *mdas,
>  	    struct device *dev, uint64_t start, uint64_t size, unsigned ignored);
>  void del_mdas(struct dm_list *mdas);
> diff --git a/lib/metadata/metadata.h b/lib/metadata/metadata.h
> index 0da8b3d..ed72551 100644
> --- a/lib/metadata/metadata.h
> +++ b/lib/metadata/metadata.h
> @@ -266,6 +266,13 @@ struct format_handler {
>  				     unsigned metadata_ignored);
>  
>  	/*
> +	 * Remove metadata area from a PV. Changes will take effect on pv_write.
> +	 */
> +	int (*pv_remove_metadata_area) (const struct format_type *fmt,
> +					struct physical_volume *pv,
> +					unsigned metadata_index);
> +
> +	/*
>  	 * 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
>  	 */



^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH 09/17] Add pv_initialise fn to format_handler interface.
  2011-01-24 11:04 ` [PATCH 09/17] Add pv_initialise fn to format_handler interface Peter Rajnoha
@ 2011-01-28 16:31   ` Petr Rockai
  0 siblings, 0 replies; 36+ messages in thread
From: Petr Rockai @ 2011-01-28 16:31 UTC (permalink / raw)
  To: lvm-devel

Peter Rajnoha <prajnoha@redhat.com> writes:

> This is a split-off from the original pv_setup code, a simple refactor.
> It makes the code easier to read and cleans up the interface a bit. So
> now we will call pv_initialise when we initialise a PV only, creating a
> brand new PV. It will also initialise a new format_instance to use later on.

OK, although the parameter lists are huge -- calls to these functions
are plain unreadable. Please consider doing something about it... (this
is a widespread problem in LVM, I know, but that's no excuse to keep not
fixing it).

Yours,
   Petr

> Signed-off-by: Peter Rajnoha <prajnoha@redhat.com>
Reviewed-by: Petr Rockai <prockai@redhat.com>

> ---
>  lib/format1/format1.c         |   35 ++++++++++++++------
>  lib/format_pool/format_pool.c |   14 ++++++++
>  lib/format_text/format-text.c |   71 +++++++++++++++++++++++++++++++++++++++++
>  lib/metadata/metadata.h       |   13 +++++++
>  4 files changed, 123 insertions(+), 10 deletions(-)
>
> diff --git a/lib/format1/format1.c b/lib/format1/format1.c
> index 4f66cdc..cb17ef5 100644
> --- a/lib/format1/format1.c
> +++ b/lib/format1/format1.c
> @@ -361,16 +361,15 @@ static int _format1_pv_read(const struct format_type *fmt, const char *pv_name,
>  	return r;
>  }
>  
> -static int _format1_pv_setup(const struct format_type *fmt,
> -			     uint64_t pe_start, uint32_t extent_count,
> -			     uint32_t extent_size,
> -			     unsigned long data_alignment __attribute__((unused)),
> -			     unsigned long data_alignment_offset __attribute__((unused)),
> -			     int pvmetadatacopies __attribute__((unused)),
> -			     uint64_t pvmetadatasize __attribute__((unused)),
> -			     unsigned metadataignore __attribute__((unused)),
> -			     struct dm_list *mdas __attribute__((unused)),
> -			     struct physical_volume *pv, struct volume_group *vg __attribute__((unused)))
> +static int _format1_pv_initialise(const struct format_type * fmt,
> +				  int64_t label_sector __attribute__((unused)),
> +				  uint64_t pe_start,
> +				  int pe_start_locked __attribute__((unused)),
> +				  uint32_t extent_count,
> +				  uint32_t extent_size,
> +				  unsigned long data_alignment __attribute__((unused)),
> +				  unsigned long data_alignment_offset __attribute__((unused)),
> +				  struct physical_volume * pv)
>  {
>  	if (pv->size > MAX_PV_SIZE)
>  		pv->size--;
> @@ -400,6 +399,21 @@ static int _format1_pv_setup(const struct format_type *fmt,
>  	return 1;
>  }
>  
> +static int _format1_pv_setup(const struct format_type *fmt,
> +			     uint64_t pe_start, uint32_t extent_count,
> +			     uint32_t extent_size,
> +			     unsigned long data_alignment __attribute__((unused)),
> +			     unsigned long data_alignment_offset __attribute__((unused)),
> +			     int pvmetadatacopies __attribute__((unused)),
> +			     uint64_t pvmetadatasize __attribute__((unused)),
> +			     unsigned metadataignore __attribute__((unused)),
> +			     struct dm_list *mdas __attribute__((unused)),
> +			     struct physical_volume *pv,
> +			     struct volume_group *vg __attribute__((unused)))
> +{
> +	return _format1_pv_initialise(fmt, -1, 0, 0, 0, vg->extent_size, 0, 0, pv);
> +}
> +
>  static int _format1_lv_setup(struct format_instance *fid, struct logical_volume *lv)
>  {
>  	uint64_t max_size = UINT_MAX;
> @@ -563,6 +577,7 @@ static void _format1_destroy(struct format_type *fmt)
>  
>  static struct format_handler _format1_ops = {
>  	.pv_read = _format1_pv_read,
> +	.pv_initialise = _format1_pv_initialise,
>  	.pv_setup = _format1_pv_setup,
>  	.pv_write = _format1_pv_write,
>  	.lv_setup = _format1_lv_setup,
> diff --git a/lib/format_pool/format_pool.c b/lib/format_pool/format_pool.c
> index 24ccfc2..83f474a 100644
> --- a/lib/format_pool/format_pool.c
> +++ b/lib/format_pool/format_pool.c
> @@ -188,6 +188,19 @@ out:
>  	return NULL;
>  }
>  
> +static int _pool_pv_initialise(const struct format_type *fmt __attribute__((unused)),
> +			       int64_t label_sector __attribute__((unused)),
> +			       uint64_t pe_start __attribute__((unused)),
> +			       int pe_start_locked __attribute__((unused)),
> +			       uint32_t extent_count __attribute__((unused)),
> +			       uint32_t extent_size __attribute__((unused)),
> +			       unsigned long data_alignment __attribute__((unused)),
> +			       unsigned long data_alignment_offset __attribute__((unused)),
> +			       struct physical_volume *pv __attribute__((unused)))
> +{
> +	return 1;
> +}
> +
>  static int _pool_pv_setup(const struct format_type *fmt __attribute__((unused)),
>  			  uint64_t pe_start __attribute__((unused)),
>  			  uint32_t extent_count __attribute__((unused)),
> @@ -295,6 +308,7 @@ static void _pool_destroy(struct format_type *fmt)
>  /* *INDENT-OFF* */
>  static struct format_handler _format_pool_ops = {
>  	.pv_read = _pool_pv_read,
> +	.pv_initialise = _pool_pv_initialise,
>  	.pv_setup = _pool_pv_setup,
>  	.create_instance = _pool_create_instance,
>  	.destroy_instance = _pool_destroy_instance,
> diff --git a/lib/format_text/format-text.c b/lib/format_text/format-text.c
> index 99f691f..c6adedc 100644
> --- a/lib/format_text/format-text.c
> +++ b/lib/format_text/format-text.c
> @@ -1688,6 +1688,76 @@ static int _text_pv_read(const struct format_type *fmt, const char *pv_name,
>  	return 1;
>  }
>  
> +static int _text_pv_initialise(const struct format_type *fmt,
> +			       const int64_t label_sector,
> +			       uint64_t pe_start,
> +			       int pe_start_locked,
> +			       uint32_t extent_count,
> +			       uint32_t extent_size,
> +			       unsigned long data_alignment,
> +			       unsigned long data_alignment_offset,
> +			       struct physical_volume *pv)
> +{
> +	struct text_fid_pv_context *fid_pv_tc;
> +
> +	/*
> +	 * Try to keep the value of PE start set to a firm value if requested.
> +	 * This is usefull when restoring existing PE start value (backups etc.).
> +	 */
> +	if (pe_start_locked)
> +		pv->pe_start = pe_start;
> +
> +	if (!data_alignment)
> +		data_alignment = find_config_tree_int(pv->fmt->cmd,
> +					      "devices/data_alignment",
> +					      0) * 2;
> +
> +	if (set_pe_align(pv, data_alignment) != data_alignment &&
> +	    data_alignment) {
> +		log_error("%s: invalid data alignment of "
> +			  "%lu sectors (requested %lu sectors)",
> +			  pv_dev_name(pv), pv->pe_align, data_alignment);
> +		return 0;
> +	}
> +
> +	if (set_pe_align_offset(pv, data_alignment_offset) != data_alignment_offset &&
> +	    data_alignment_offset) {
> +		log_error("%s: invalid data alignment offset of "
> +			  "%lu sectors (requested %lu sectors)",
> +			  pv_dev_name(pv), pv->pe_align_offset, data_alignment_offset);
> +		return 0;
> +	}
> +
> +	if (pv->pe_align < pv->pe_align_offset) {
> +		log_error("%s: pe_align (%lu sectors) must not be less "
> +			  "than pe_align_offset (%lu sectors)",
> +			  pv_dev_name(pv), pv->pe_align, pv->pe_align_offset);
> +		return 0;
> +	}
> +
> +	if (!pe_start_locked && pv->pe_start < pv->pe_align)
> +		pv->pe_start = pv->pe_align;
> +
> +	if (extent_size)
> +		pv->pe_size = extent_size;
> +
> +	if (extent_count)
> +		pv->pe_count = extent_count;
> +
> +	if ((pv->pe_start + pv->pe_count * pv->pe_size - 1) > (pv->size << SECTOR_SHIFT)) {
> +		log_error("Physical extents end beyond end of device %s.",
> +			   pv_dev_name(pv));
> +		return 0;
> +	}
> +
> +	if (label_sector != -1) {
> +		fid_pv_tc = (struct text_fid_pv_context *) pv->fid->private;
> +		fid_pv_tc->label_sector = label_sector;
> +	}
> +
> +	return 1;
> +}
> +
>  static void _text_destroy_instance(struct format_instance *fid __attribute__((unused)))
>  {
>  }
> @@ -2377,6 +2447,7 @@ void *create_text_context(struct cmd_context *cmd, const char *path,
>  static struct format_handler _text_handler = {
>  	.scan = _text_scan,
>  	.pv_read = _text_pv_read,
> +	.pv_initialise = _text_pv_initialise,
>  	.pv_setup = _text_pv_setup,
>  	.pv_add_metadata_area = _text_pv_add_metadata_area,
>  	.pv_remove_metadata_area = _text_pv_remove_metadata_area,
> diff --git a/lib/metadata/metadata.h b/lib/metadata/metadata.h
> index ed72551..ae8dd9a 100644
> --- a/lib/metadata/metadata.h
> +++ b/lib/metadata/metadata.h
> @@ -244,6 +244,19 @@ struct format_handler {
>  			struct physical_volume * pv, int scan_label_only);
>  
>  	/*
> +	 * Initialise a new PV.
> +	 */
> +	int (*pv_initialise) (const struct format_type * fmt,
> +			      int64_t label_sector,
> +			      uint64_t pe_start,
> +			      int pe_start_locked,
> +			      uint32_t extent_count,
> +			      uint32_t extent_size,
> +			      unsigned long data_alignment,
> +			      unsigned long data_alignment_offset,
> +			      struct physical_volume * pv);
> +
> +	/*
>  	 * Tweak an already filled out a pv ready for importing into a
>  	 * vg.  eg. pe_count is format specific.
>  	 */



^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH 10/17] Add pe_start_locked parameter to pv_create fn.
  2011-01-24 11:04 ` [PATCH 10/17] Add pe_start_locked parameter to pv_create fn Peter Rajnoha
@ 2011-01-28 16:39   ` Petr Rockai
  0 siblings, 0 replies; 36+ messages in thread
From: Petr Rockai @ 2011-01-28 16:39 UTC (permalink / raw)
  To: lvm-devel

Peter Rajnoha <prajnoha@redhat.com> writes:

> So we can define and hint the metadata area handling code that the
> pe_start is supposed to be firmly set to a certain value and it should
> not be changed during calculations.

All clear. However, it adds another parameter to an already huge
list. Please consider other options. Also, not using int as a bool would
help in lots of places, but I guess we are stuck with that. (You could
for example create a structure for the parameters, so at least at the
call site, we have know which parameter means what... having a 10-tuple
of integers is not exactly informative.)

> Signed-off-by: Peter Rajnoha <prajnoha@redhat.com>
Reviewed-by: Petr Rockai <prockai@redhat.com>

> ---
>  lib/metadata/metadata-exported.h |    1 +
>  lib/metadata/metadata.c          |    4 +++-
>  tools/vgconvert.c                |    2 +-
>  3 files changed, 5 insertions(+), 2 deletions(-)
>
> diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
> index da62764..627d098 100644
> --- a/lib/metadata/metadata-exported.h
> +++ b/lib/metadata/metadata-exported.h
> @@ -394,6 +394,7 @@ struct physical_volume *pv_create(const struct cmd_context *cmd,
>  				  unsigned long data_alignment,
>  				  unsigned long data_alignment_offset,
>  				  uint64_t pe_start,
> +				  int pe_start_locked,
>  				  uint32_t existing_extent_count,
>  				  uint32_t existing_extent_size,
>  				  int pvmetadatacopies, uint64_t pvmetadatasize,
> diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
> index 591f7b5..419dcfc 100644
> --- a/lib/metadata/metadata.c
> +++ b/lib/metadata/metadata.c
> @@ -1486,7 +1486,8 @@ struct physical_volume * pvcreate_single(struct cmd_context *cmd,
>  	dm_list_init(&mdas);
>  	if (!(pv = pv_create(cmd, dev, pp->idp, pp->size,
>  			     pp->data_alignment, pp->data_alignment_offset,
> -			     pp->pe_start, pp->extent_count, pp->extent_size,
> +			     pp->pe_start, pp->pe_start ? 1 : 0,
> +			     pp->extent_count, pp->extent_size,
>  			     pp->pvmetadatacopies, pp->pvmetadatasize,
>  			     pp->metadataignore, &mdas))) {
>  		log_error("Failed to setup physical volume \"%s\"", pv_name);
> @@ -1591,6 +1592,7 @@ struct physical_volume *pv_create(const struct cmd_context *cmd,
>  				  unsigned long data_alignment,
>  				  unsigned long data_alignment_offset,
>  				  uint64_t pe_start,
> +				  int pe_start_locked,
>  				  uint32_t existing_extent_count,
>  				  uint32_t existing_extent_size,
>  				  int pvmetadatacopies, uint64_t pvmetadatasize,
> diff --git a/tools/vgconvert.c b/tools/vgconvert.c
> index acae0fc..81ff616 100644
> --- a/tools/vgconvert.c
> +++ b/tools/vgconvert.c
> @@ -125,7 +125,7 @@ static int vgconvert_single(struct cmd_context *cmd, const char *vg_name,
>  		dm_list_init(&mdas);
>  		if (!(pv = pv_create(cmd, pv_dev(existing_pv),
>  				     &existing_pv->id, size, 0, 0,
> -				     pe_start, pv_pe_count(existing_pv),
> +				     pe_start, 1, pv_pe_count(existing_pv),
>  				     pv_pe_size(existing_pv), pvmetadatacopies,
>  				     pvmetadatasize, 0, &mdas))) {
>  			log_error("Failed to setup physical volume \"%s\"",



^ permalink raw reply	[flat|nested] 36+ messages in thread

end of thread, other threads:[~2011-01-28 16:39 UTC | newest]

Thread overview: 36+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-01-24 11:03 [PATCH 00/17] Add interface to support adding and removing metadata areas on demand (v2) Peter Rajnoha
2011-01-24 11:03 ` [PATCH 01/17] Add pvid parameter to create_instance function Peter Rajnoha
2011-01-25 12:54   ` Petr Rockai
2011-01-24 11:03 ` [PATCH 02/17] Add supporting functions for metadata areas stored in format instance Peter Rajnoha
2011-01-25 13:16   ` Petr Rockai
2011-01-26 10:38     ` Peter Rajnoha
2011-01-26 13:59       ` Petr Rockai
2011-01-26 14:06       ` Petr Rockai
2011-01-24 11:03 ` [PATCH 03/17] Add struct format_instance *fid field to struct physical_volume Peter Rajnoha
2011-01-25 13:03   ` Petr Rockai
2011-01-24 11:03 ` [PATCH 04/17] Add format_instance support for pv_read Peter Rajnoha
2011-01-25 13:30   ` Petr Rockai
2011-01-26 11:05     ` Peter Rajnoha
2011-01-26 11:12       ` Peter Rajnoha
2011-01-24 11:03 ` [PATCH 05/17] Add attach_existing_mdas parameter to create_instance fn Peter Rajnoha
2011-01-25 14:43   ` Petr Rockai
2011-01-26 13:24     ` Peter Rajnoha
2011-01-24 11:03 ` [PATCH 06/17] Remove useless mdas parameter from PV read functions Peter Rajnoha
2011-01-25 14:44   ` Petr Rockai
2011-01-24 11:03 ` [PATCH 07/17] Add pv_add_metadata_area fn to support adding metadata areas on demand Peter Rajnoha
2011-01-25 14:48   ` Petr Rockai
2011-01-24 11:03 ` [PATCH 08/17] Add pv_remove_metadata_area fn to support removing " Peter Rajnoha
2011-01-28 15:31   ` Petr Rockai
2011-01-24 11:04 ` [PATCH 09/17] Add pv_initialise fn to format_handler interface Peter Rajnoha
2011-01-28 16:31   ` Petr Rockai
2011-01-24 11:04 ` [PATCH 10/17] Add pe_start_locked parameter to pv_create fn Peter Rajnoha
2011-01-28 16:39   ` Petr Rockai
2011-01-24 11:04 ` [PATCH 11/17] Refactor pv_setup to not include the PV initialisation code Peter Rajnoha
2011-01-24 11:04 ` [PATCH 12/17] Remove unused _mda_setup code Peter Rajnoha
2011-01-24 11:04 ` [PATCH 13/17] Cleanup pv_write code to use recent changes in metadata handling interface Peter Rajnoha
2011-01-24 11:04 ` [PATCH 14/17] Use new metadata handling interface to provide better support for PV resize Peter Rajnoha
2011-01-24 11:04 ` [PATCH 15/17] Change vg_convert code to actually work with recent changes in metadata handling interface Peter Rajnoha
2011-01-24 11:04 ` [PATCH 16/17] Fix pvchange -u to " Peter Rajnoha
2011-01-24 16:04   ` Peter Rajnoha
2011-01-24 11:04 ` [PATCH 17/17] Fix pvchange --metadataignore " Peter Rajnoha
2011-01-24 11:12 ` [PATCH 00/17] Add interface to support adding and removing metadata areas on demand (v2) Peter Rajnoha

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.