Skip to contentSkip to conversation

Add interface to support adding and removing metadata areas on demand (v2)

PATCH New Peter Rajnoha 2 participants 36 messages Jan 24, 2011 – Jan 28, 2011

lore
Share & tools
lore
#0 lore raw

cover Add interface to support adding and removing metadata areas on demand (v2)

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(-)
Signature · 1 line
1.7.3.4
#1 lore raw

PATCH 1/17 Add pvid parameter to create_instance function.

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.

---
 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(-)
lib/cache/lvmcache.c +1 -1
index 0e9cae1..476b176 100644
@@ -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;
 
lib/format1/format1.c +1 -0
index fc14444..13b757d 100644
@@ -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)))
lib/format_pool/format_pool.c +1 -0
index 730da87..814d80c 100644
@@ -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)))
lib/format_text/archive.c +1 -1
index 43425dc..760153c 100644
@@ -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;
 	}
lib/format_text/archiver.c +4 -4
index e0212a2..b7dcad9 100644
@@ -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;
 	}
lib/format_text/format-text.c +11 -9
index c186757..fda8255 100644
@@ -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;
lib/metadata/metadata.c +5 -5
index 771cdb0..fd1948a 100644
@@ -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;
 		}
lib/metadata/metadata.h +3 -2
index c0f9148..ab7cff0 100644
@@ -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);
 
Signature · 1 line
1.7.3.4
#2 lore raw

PATCH 1/17 Add pvid parameter to create_instance function.

Quoted 19 lines · Peter Rajnoha

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,

Quoted 7 lines

- 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.

Quoted 1 line
Quoted 196 lines
---
 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(-)
lib/cache/lvmcache.c +1 -1
index 0e9cae1..476b176 100644
@@ -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;
 
lib/format1/format1.c +1 -0
index fc14444..13b757d 100644
@@ -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)))
lib/format_pool/format_pool.c +1 -0
index 730da87..814d80c 100644
@@ -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)))
lib/format_text/archive.c +1 -1
index 43425dc..760153c 100644
@@ -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;
 	}
lib/format_text/archiver.c +4 -4
index e0212a2..b7dcad9 100644
@@ -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;
 	}
lib/format_text/format-text.c +11 -9
index c186757..fda8255 100644
@@ -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;
lib/metadata/metadata.c +5 -5
index 771cdb0..fd1948a 100644
@@ -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;
 		}
lib/metadata/metadata.h +3 -2
index c0f9148..ab7cff0 100644
@@ -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);
#3 lore raw

PATCH 2/17 Add supporting functions for metadata areas stored in format instance.

In reply to Peter Rajnoha

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...

---
 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(-)
lib/format1/format1.c +1 -0
index 13b757d..ff5b0f5 100644
@@ -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);
 
lib/format_text/format-text.c +101 -36

206 lines not on this page · raw message

lib/format_text/format-text.h +1 -0
index 79365ea..f3cf4f5 100644
@@ -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
lib/metadata/metadata-exported.h +3 -0
index a9709d6..d8247dd 100644
@@ -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;
 };
 
lib/metadata/metadata.c +99 -4

128 lines not on this page · raw message

lib/metadata/metadata.h +8 -2
index ab7cff0..0fbc954 100644
@@ -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
Signature · 1 line
1.7.3.4
#4 lore raw

PATCH 2/17 Add supporting functions for metadata areas stored in format instance.

Quoted 42 lines · Peter Rajnoha

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.

Quoted 8 lines

...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...

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.)

Yours,
Petr

Quoted 63 lines
---
 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(-)
lib/format1/format1.c +1 -0
index 13b757d..ff5b0f5 100644
@@ -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);
 
lib/format_text/format-text.c +21 -6
index fda8255..c8c56f7 100644
@@ -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 *

lib/format_text/format-text.c static int _text_pv_setup(const struct format_type *fmt, · line 1945

Quoted 10 lines
lib/format_text/format-text.c +10 -0
+						   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

Quoted 149 lines
lib/format_text/format-text.c +61 -30
+
+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);
+

lib/format_text/format-text.c static struct format_instance *_text_create_text_instance(const struct format_ty · line 2077

Quoted 10 lines
lib/format_text/format-text.c +9 -0
+	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.

Quoted 19 lines
lib/format_text/format-text.c +0 -0
 void *create_text_context(struct cmd_context *cmd, const char *path,
lib/format_text/format-text.h +1 -0
index 79365ea..f3cf4f5 100644
@@ -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
lib/metadata/metadata-exported.h +0 -0
index a9709d6..d8247dd 100644

lib/metadata/metadata-exported.h struct pv_segment { · line 176

Quoted 4 lines
lib/metadata/metadata-exported.h +1 -0
@@ -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.

lib/metadata/metadata-exported.h struct format_instance { · line 186

Quoted 9 lines
lib/metadata/metadata-exported.h +2 -0
+
 	/*
 	 * 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?

Quoted 23 lines
lib/metadata/metadata-exported.h +0 -0
 	void *private;
 };
 
lib/metadata/metadata.c +3 -2
index fd1948a..c3accaf 100644
@@ -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,

lib/metadata/metadata.c uint32_t vg_lock_newname(struct cmd_context *cmd, const char *vgname) · line 3926

Quoted 10 lines
lib/metadata/metadata.c +9 -0
+				  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?

Quoted 11 lines
lib/metadata/metadata.c +9 -0
+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 */

lib/metadata/metadata.c uint32_t vg_lock_newname(struct cmd_context *cmd, const char *vgname) · line 3948

Quoted 10 lines
lib/metadata/metadata.c +10 -0
+	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?

Quoted 32 lines
lib/metadata/metadata.c +20 -2
+	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;

lib/metadata/metadata.c uint32_t vg_lock_newname(struct cmd_context *cmd, const char *vgname) · line 3988

Quoted 10 lines
lib/metadata/metadata.c +10 -0
+
+	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).

Quoted 23 lines
lib/metadata/metadata.c +23 -0
+	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;
+

lib/metadata/metadata.c uint32_t vg_lock_newname(struct cmd_context *cmd, const char *vgname) · line 4021

Quoted 10 lines
lib/metadata/metadata.c +10 -0
+		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.

Quoted 28 lines
lib/metadata/metadata.c +4 -0
+	}
+
+	dm_list_del(&mda->list);
+
 	return 1;
 }
 
lib/metadata/metadata.h +8 -2
index ab7cff0..0fbc954 100644
@@ -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
#5 lore raw

PATCH 2/17 Add supporting functions for metadata areas stored in format instance.

Quoted 8 lines · Petr Rockai

lib/metadata/metadata-exported.h struct pv_segment { · line 176

Quoted 3 lines

struct format_instance {

lib/metadata/metadata-exported.h +1 -0
 	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...

Quoted 5 lines
Quoted 5 lines
lib/metadata/metadata-exported.h +1 -0
+
 	/*
 	 * 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 {
Quoted 9 lines

lib/metadata/metadata-exported.h struct format_instance { · line 186

Quoted 4 lines
lib/metadata/metadata-exported.h +1 -0
 	 */
 	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 :)

Quoted 6 lines
Quoted 6 lines
lib/metadata/metadata.c +5 -0
+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;
Quoted 8 lines

lib/metadata/metadata.c uint32_t vg_lock_newname(struct cmd_context *cmd, const char *vgname) · line 3926

Quoted 5 lines
lib/metadata/metadata.c +5 -0
+	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).

Quoted 4 lines

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...

Quoted 20 lines
Quoted 20 lines
lib/metadata/metadata.c +17 -0
+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. */
Quoted 9 lines

lib/metadata/metadata.c uint32_t vg_lock_newname(struct cmd_context *cmd, const char *vgname) · line 3948

Quoted 2 lines
lib/metadata/metadata.c +2 -0
+	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...

Quoted 10 lines
Quoted 10 lines
lib/metadata/metadata.c +10 -0
+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;
Quoted 9 lines

lib/metadata/metadata.c uint32_t vg_lock_newname(struct cmd_context *cmd, const char *vgname) · line 3988

Quoted 6 lines
lib/metadata/metadata.c +6 -0
+
+	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...

Quoted 24 lines
Quoted 24 lines
lib/metadata/metadata.c +24 -0
+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;
+
Quoted 9 lines

lib/metadata/metadata.c uint32_t vg_lock_newname(struct cmd_context *cmd, const char *vgname) · line 4021

Quoted 6 lines
lib/metadata/metadata.c +6 -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

#6 lore raw

PATCH 2/17 Add supporting functions for metadata areas stored in format instance.

Quoted 22 lines · Peter Rajnoha
Quoted 6 lines

lib/metadata/metadata-exported.h struct format_instance { · line 186

Quoted 1 line
lib/metadata/metadata-exported.h +1 -0
+	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...)

Quoted 3 lines

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.

#7 lore raw

PATCH 2/17 Add supporting functions for metadata areas stored in format instance.

In reply to Peter Rajnoha
Quoted 11 lines · Peter Rajnoha
Quoted 4 lines

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

#8 lore raw

PATCH 3/17 Add struct format_instance *fid field to struct physical_volume.

In reply to Peter Rajnoha

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.

---
 lib/metadata/metadata.c |    7 +++++++
 lib/metadata/pv.h       |    1 +
 2 files changed, 8 insertions(+), 0 deletions(-)
lib/metadata/metadata.c +7 -0
index c3accaf..ed2084d 100644
@@ -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;
 
lib/metadata/pv.h +1 -0
index a02f6f8..a9efcfe 100644
@@ -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.
Signature · 1 line
1.7.3.4
#9 lore raw

PATCH 3/17 Add struct format_instance *fid field to struct physical_volume.

Quoted 3 lines · Peter Rajnoha

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.

Quoted 1 line
Quoted 42 lines
---
 lib/metadata/metadata.c |    7 +++++++
 lib/metadata/pv.h       |    1 +
 2 files changed, 8 insertions(+), 0 deletions(-)
lib/metadata/metadata.c +7 -0
index c3accaf..ed2084d 100644
@@ -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;
 
lib/metadata/pv.h +1 -0
index a02f6f8..a9efcfe 100644
@@ -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.
#10 lore raw

PATCH 4/17 Add format_instance support for pv_read.

In reply to Peter Rajnoha

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).

---
 lib/metadata/metadata.c |   26 +++++++++++++++++++++-----
 1 files changed, 21 insertions(+), 5 deletions(-)
lib/metadata/metadata.c +21 -5
index ed2084d..f6ea0e5 100644
@@ -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);
 }
Signature · 1 line
1.7.3.4
#11 lore raw

PATCH 4/17 Add format_instance support for pv_read.

Quoted 4 lines · Peter Rajnoha

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.

Quoted 74 lines
---
 lib/metadata/metadata.c |   26 +++++++++++++++++++++-----
 1 files changed, 21 insertions(+), 5 deletions(-)
lib/metadata/metadata.c +10 -4
index ed2084d..f6ea0e5 100644
@@ -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);

lib/metadata/metadata.c static struct physical_volume *_pv_read(struct cmd_context *cmd, · line 3425

Quoted 10 lines
lib/metadata/metadata.c +10 -0
+	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...)

lib/metadata/metadata.c struct physical_volume *pv_by_path(struct cmd_context *cmd, const char *pv_name) · line 4233

Quoted 10 lines
lib/metadata/metadata.c +1 -1
 	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

#12 lore raw

PATCH 4/17 Add format_instance support for pv_read.

Quoted 11 lines · Petr Rockai
Quoted 4 lines · Peter Rajnoha

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...

Quoted 1 line

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

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

Quoted 2 lines

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)

Quoted 1 line

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).

Quoted 3 lines

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...

Quoted 8 lines
Quoted 8 lines
lib/metadata/metadata.c +8 -0
+	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);
Quoted 9 lines

lib/metadata/metadata.c static struct physical_volume *_pv_read(struct cmd_context *cmd, · line 3425

Quoted 4 lines
lib/metadata/metadata.c +4 -0
+			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.

Quoted 9 lines

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 :) )

Quoted 6 lines

?

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

#13 lore raw

PATCH 4/17 Add format_instance support for pv_read.

Quoted 1 line · Peter Rajnoha

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

#14 lore raw

PATCH 5/17 Add attach_existing_mdas parameter to create_instance fn.

In reply to Peter Rajnoha

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).

---
 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(-)
lib/cache/lvmcache.c +1 -1
index 476b176..e3ac4f2 100644
@@ -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 */
lib/format1/format1.c +2 -1
index ff5b0f5..b79bd56 100644
@@ -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;
lib/format_pool/format_pool.c +2 -1
index 814d80c..3ecbfe9 100644
@@ -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;
lib/format_text/archive.c +1 -1
index 760153c..8d55988 100644
@@ -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;
 	}
lib/format_text/archiver.c +6 -4
index b7dcad9..ec65794 100644
@@ -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;
 	}
lib/format_text/format-text.c +20 -14
index c8c56f7..a2f3d74 100644
@@ -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;
lib/metadata/metadata.c +20 -7
index f6ea0e5..dccc3af 100644
@@ -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)
 {
lib/metadata/metadata.h +3 -1
index 0fbc954..bd638b5 100644
@@ -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
Signature · 1 line
1.7.3.4
#15 lore raw

PATCH 5/17 Add attach_existing_mdas parameter to create_instance fn.

Quoted 4 lines · Peter Rajnoha

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

Quoted 317 lines
---
 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(-)
lib/cache/lvmcache.c +1 -1
index 476b176..e3ac4f2 100644
@@ -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 */
lib/format1/format1.c +2 -1
index ff5b0f5..b79bd56 100644
@@ -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;
lib/format_pool/format_pool.c +2 -1
index 814d80c..3ecbfe9 100644
@@ -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;
lib/format_text/archive.c +1 -1
index 760153c..8d55988 100644
@@ -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;
 	}
lib/format_text/archiver.c +6 -4
index b7dcad9..ec65794 100644
@@ -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;
 	}
lib/format_text/format-text.c +20 -14
index c8c56f7..a2f3d74 100644
@@ -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;
lib/metadata/metadata.c +20 -7
index f6ea0e5..dccc3af 100644
@@ -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)
 {
lib/metadata/metadata.h +3 -1
index 0fbc954..bd638b5 100644
@@ -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
#16 lore raw

PATCH 5/17 Add attach_existing_mdas parameter to create_instance fn.

Quoted 12 lines · Petr Rockai
Quoted 4 lines · Peter Rajnoha

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...

...

Quoted 8 lines

lib/format_text/format-text.c static struct format_instance *_text_create_text_instance(const struct format_ty · line 46

Quoted 8 lines
lib/format_text/format-text.c +2 -1
@@ -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

#17 lore raw

PATCH 6/17 Remove useless mdas parameter from PV read functions.

In reply to Peter Rajnoha

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

---
 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(-)
lib/format1/format1.c +1 -2
index b79bd56..4f66cdc 100644
@@ -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;
lib/format_pool/format_pool.c +0 -1
index 3ecbfe9..24ccfc2 100644
@@ -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);
lib/format_text/format-text.c +1 -14
index a2f3d74..5dfe0b8 100644
@@ -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;
 }
 
lib/metadata/metadata-exported.h +2 -2
index d8247dd..da62764 100644
@@ -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);
 
 /*
lib/metadata/metadata.c +13 -24
index dccc3af..591f7b5 100644
@@ -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);
 }
lib/metadata/metadata.h +1 -2
index bd638b5..7ebf85c 100644
@@ -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
tools/pvremove.c +4 -6
index a8717e0..ace3c1d 100644
@@ -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;
 		}
tools/pvresize.c +3 -5
index 8582ef4..4f1d610 100644
@@ -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);
 
tools/toollib.c +6 -8
index f76aacd..48f8ed5 100644
@@ -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 "
Signature · 1 line
1.7.3.4
#18 lore raw

PATCH 6/17 Remove useless mdas parameter from PV read functions.

Quoted 1 line · Peter Rajnoha

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

looks OK

Quoted 1 line
Quoted 346 lines
---
 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(-)
lib/format1/format1.c +1 -2
index b79bd56..4f66cdc 100644
@@ -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;
lib/format_pool/format_pool.c +0 -1
index 3ecbfe9..24ccfc2 100644
@@ -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);
lib/format_text/format-text.c +1 -14
index a2f3d74..5dfe0b8 100644
@@ -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;
 }
 
lib/metadata/metadata-exported.h +2 -2
index d8247dd..da62764 100644
@@ -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);
 
 /*
lib/metadata/metadata.c +13 -24
index dccc3af..591f7b5 100644
@@ -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);
 }
lib/metadata/metadata.h +1 -2
index bd638b5..7ebf85c 100644
@@ -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
tools/pvremove.c +4 -6
index a8717e0..ace3c1d 100644
@@ -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;
 		}
tools/pvresize.c +3 -5
index 8582ef4..4f1d610 100644
@@ -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);
 
tools/toollib.c +6 -8
index f76aacd..48f8ed5 100644
@@ -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 "
#19 lore raw

PATCH 7/17 Add pv_add_metadata_area fn to support adding metadata areas on demand.

In reply to Peter Rajnoha

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).

---
 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(-)
lib/format_text/format-text.c +245 -0
index 5dfe0b8..cf18f25 100644
@@ -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,
lib/format_text/format-text.h +5 -0
index f3cf4f5..f65be74 100644
@@ -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);
lib/metadata/metadata.h +10 -0
index 7ebf85c..0da8b3d 100644
@@ -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
 	 */
Signature · 1 line
1.7.3.4
#20 lore raw

PATCH 7/17 Add pv_add_metadata_area fn to support adding metadata areas on demand.

Quoted 7 lines · Peter Rajnoha

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.

Quoted 1 line

(One minor tweak below)

Quoted 243 lines
---
 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(-)
lib/format_text/format-text.c +229 -0
index 5dfe0b8..cf18f25 100644
@@ -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;
+		}

lib/format_text/format-text.c static int _create_vg_text_instance(struct format_instance *fid, · line 2272

Quoted 10 lines
lib/format_text/format-text.c +10 -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?

Quoted 53 lines
lib/format_text/format-text.c +6 -0
+	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,
lib/format_text/format-text.h +5 -0
index f3cf4f5..f65be74 100644
@@ -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);
lib/metadata/metadata.h +10 -0
index 7ebf85c..0da8b3d 100644
@@ -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
 	 */
#21 lore raw

PATCH 8/17 Add pv_remove_metadata_area fn to support removing metadata areas on demand.

In reply to Peter Rajnoha

The same as for pv_add_metadata_area, but removing...

---
 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(-)
lib/format_text/format-text.c +24 -0
index cf18f25..99f691f 100644
@@ -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,
lib/format_text/format-text.h +2 -0
index f65be74..694b5c1 100644
@@ -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);
lib/metadata/metadata.h +7 -0
index 0da8b3d..ed72551 100644
@@ -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
 	 */
Signature · 1 line
1.7.3.4
#22 lore raw

PATCH 8/17 Add pv_remove_metadata_area fn to support removing metadata areas on demand.

Quoted 1 line · Peter Rajnoha

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).

Quoted 1 line
Quoted 79 lines
---
 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(-)
lib/format_text/format-text.c +24 -0
index cf18f25..99f691f 100644
@@ -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,
lib/format_text/format-text.h +2 -0
index f65be74..694b5c1 100644
@@ -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);
lib/metadata/metadata.h +7 -0
index 0da8b3d..ed72551 100644
@@ -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
 	 */
#23 lore raw

PATCH 9/17 Add pv_initialise fn to format_handler interface.

In reply to Peter Rajnoha

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.

---
 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(-)
lib/format1/format1.c +25 -10
index 4f66cdc..cb17ef5 100644
@@ -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,
lib/format_pool/format_pool.c +14 -0
index 24ccfc2..83f474a 100644
@@ -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,
lib/format_text/format-text.c +71 -0

83 lines not on this page · raw message

lib/metadata/metadata.h +13 -0
index ed72551..ae8dd9a 100644
@@ -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.
 	 */
Signature · 1 line
1.7.3.4
#24 lore raw

PATCH 9/17 Add pv_initialise fn to format_handler interface.

Quoted 4 lines · Peter Rajnoha

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

Quoted 1 line
Quoted 212 lines
---
 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(-)
lib/format1/format1.c +25 -10
index 4f66cdc..cb17ef5 100644
@@ -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,
lib/format_pool/format_pool.c +14 -0
index 24ccfc2..83f474a 100644
@@ -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,
lib/format_text/format-text.c +71 -0
index 99f691f..c6adedc 100644
@@ -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,
lib/metadata/metadata.h +13 -0
index ed72551..ae8dd9a 100644
@@ -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.
 	 */
#25 lore raw

PATCH 10/17 Add pe_start_locked parameter to pv_create fn.

In reply to Peter Rajnoha

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.

---
 lib/metadata/metadata-exported.h |    1 +
 lib/metadata/metadata.c          |    4 +++-
 tools/vgconvert.c                |    2 +-
 3 files changed, 5 insertions(+), 2 deletions(-)
lib/metadata/metadata-exported.h +1 -0
index da62764..627d098 100644
@@ -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,
lib/metadata/metadata.c +3 -1
index 591f7b5..419dcfc 100644
@@ -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,
tools/vgconvert.c +1 -1
index acae0fc..81ff616 100644
@@ -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\"",
Signature · 1 line
1.7.3.4
#26 lore raw

PATCH 10/17 Add pe_start_locked parameter to pv_create fn.

Quoted 3 lines · Peter Rajnoha

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.)

Quoted 1 line
Quoted 53 lines
---
 lib/metadata/metadata-exported.h |    1 +
 lib/metadata/metadata.c          |    4 +++-
 tools/vgconvert.c                |    2 +-
 3 files changed, 5 insertions(+), 2 deletions(-)
lib/metadata/metadata-exported.h +1 -0
index da62764..627d098 100644
@@ -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,
lib/metadata/metadata.c +3 -1
index 591f7b5..419dcfc 100644
@@ -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,
tools/vgconvert.c +1 -1
index acae0fc..81ff616 100644
@@ -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\"",
#27 lore raw

PATCH 11/17 Refactor pv_setup to not include the PV initialisation code.

In reply to Peter Rajnoha

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...)

---
 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(-)
lib/format1/format1.c +0 -8
index cb17ef5..cbb9e76 100644
@@ -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)))
 {
lib/format_pool/format_pool.c +0 -9
index 83f474a..8b1472c 100644
@@ -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)))
 {
lib/format_text/archiver.c +1 -4
index ec65794..5b888fc 100644
@@ -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;
lib/format_text/format-text.c +51 -132

202 lines not on this page · raw message

lib/metadata/metadata-exported.h +4 -3
index 627d098..398f245 100644
@@ -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,
lib/metadata/metadata.c +23 -30

90 lines not on this page · raw message

lib/metadata/metadata.h +2 -6
index ae8dd9a..a4f1fc1 100644
@@ -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.
tools/vgconvert.c +4 -2
index 81ff616..e747b0e 100644
@@ -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)
Signature · 1 line
1.7.3.4
#28 lore raw

PATCH 12/17 Remove unused _mda_setup code.

In reply to Peter Rajnoha

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

---
 lib/format_text/format-text.c |  153 -----------------------------------------
 1 files changed, 0 insertions(+), 153 deletions(-)
lib/format_text/format-text.c +0 -153
index 2671adb..4cc6364 100644
@@ -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 */
Signature · 1 line
1.7.3.4
#29 lore raw

PATCH 13/17 Cleanup pv_write code to use recent changes in metadata handling interface.

In reply to Peter Rajnoha

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).

---
 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(-)
lib/format1/format1.c +1 -2
index cbb9e76..b3eb8f5 100644
@@ -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;
lib/format_text/format-text.c +48 -99

188 lines not on this page · raw message

lib/metadata/metadata-exported.h +1 -2
index 398f245..88dd902 100644
@@ -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,
lib/metadata/metadata.c +5 -6
index 11dc205..de9960d 100644
@@ -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);
lib/metadata/metadata.h +1 -2
index a4f1fc1..f537671 100644
@@ -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
tools/pvchange.c +2 -2
index 899a8b9..3f60f54 100644
@@ -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;
tools/pvresize.c +1 -1
index 4f1d610..dbec967 100644
@@ -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;
tools/vgconvert.c +1 -3
index e747b0e..21c4d1a 100644
@@ -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 "
tools/vgreduce.c +1 -1
index 4aa8f01..f85df13 100644
@@ -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);
Signature · 1 line
1.7.3.4
#30 lore raw

PATCH 14/17 Use new metadata handling interface to provide better support for PV resize.

In reply to Peter Rajnoha

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.

---
 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(-)
lib/format_text/format-text.c +49 -0
index 521e346..f17bdb1 100644
@@ -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,
lib/metadata/metadata-exported.h +1 -1
index 88dd902..74086a2 100644
@@ -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);
 
lib/metadata/metadata.h +8 -0
index f537671..5f35333 100644
@@ -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
 	 */
lib/metadata/pv_manip.c +54 -16

94 lines not on this page · raw message

tools/pvresize.c +2 -49

82 lines not on this page · raw message

Signature · 1 line
1.7.3.4
#31 lore raw

PATCH 15/17 Change vg_convert code to actually work with recent changes in metadata handling interface.

In reply to Peter Rajnoha

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.

---
 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(-)
lib/format_text/format-text.c +5 -4
index f17bdb1..04abf58 100644
@@ -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 */
 
lib/metadata/metadata-exported.h +3 -0
index 74086a2..5a06580 100644
@@ -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);
lib/metadata/metadata.c +103 -0

109 lines not on this page · raw message

tools/vgconvert.c +22 -71

159 lines not on this page · raw message

Signature · 1 line
1.7.3.4
#32 lore raw

PATCH 16/17 Fix pvchange -u to work with recent changes in metadata handling interface.

In reply to Peter Rajnoha

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.

---
 lib/format_text/format-text.c |   10 +++++-----
 lib/metadata/pv.h             |    1 +
 tools/pvchange.c              |    1 +
 3 files changed, 7 insertions(+), 5 deletions(-)
lib/format_text/format-text.c +5 -5
index 04abf58..c0d35f0 100644
@@ -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;
lib/metadata/pv.h +1 -0
index a9efcfe..af63610 100644
@@ -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;
tools/pvchange.c +1 -0
index 3f60f54..1e11982 100644
@@ -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);
Signature · 1 line
1.7.3.4
#33 lore raw

PATCH 16/17 Fix pvchange -u to work with recent changes in metadata handling interface.

Quoted 4 lines · Peter Rajnoha

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

#34 lore raw

PATCH 17/17 Fix pvchange --metadataignore to work with recent changes in metadata handling interface.

In reply to Peter Rajnoha

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!).

---
 lib/metadata/pv.c |   20 ++++++++++++--------
 1 files changed, 12 insertions(+), 8 deletions(-)
lib/metadata/pv.c +12 -8
index e5bb9f0..7386cb1 100644
@@ -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);
Signature · 1 line
1.7.3.4
#35 lore raw

cover Add interface to support adding and removing metadata areas on demand (v2)

In reply to Peter Rajnoha
Quoted 1 line · Peter Rajnoha

The tests seems to be passing, just one is still failing - it's lvm2 format

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

Peter