summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/format1/format1.c3
-rw-r--r--lib/format_text/format-text.c156
-rw-r--r--lib/metadata/metadata-exported.h3
-rw-r--r--lib/metadata/metadata.c11
-rw-r--r--lib/metadata/metadata.h3
-rw-r--r--tools/pvchange.c4
-rw-r--r--tools/pvresize.c2
-rw-r--r--tools/vgconvert.c4
-rw-r--r--tools/vgreduce.c2
9 files changed, 75 insertions, 113 deletions
diff --git a/lib/format1/format1.c b/lib/format1/format1.c
index b9d4e17b..c49226f8 100644
--- a/lib/format1/format1.c
+++ b/lib/format1/format1.c
@@ -426,8 +426,7 @@ static int _format1_lv_setup(struct format_instance *fid, struct logical_volume
return 1;
}
-static int _format1_pv_write(const struct format_type *fmt, struct physical_volume *pv,
- struct dm_list *mdas __attribute__((unused)), int64_t sector __attribute__((unused)))
+static int _format1_pv_write(const struct format_type *fmt, struct physical_volume *pv)
{
struct dm_pool *mem;
struct disk_list *dl;
diff --git a/lib/format_text/format-text.c b/lib/format_text/format-text.c
index a59d11f4..e72a9363 100644
--- a/lib/format_text/format-text.c
+++ b/lib/format_text/format-text.c
@@ -1256,60 +1256,81 @@ static int _text_scan(const struct format_type *fmt, const char *vgname)
}
/* Only for orphans */
-/* Set label_sector to -1 if rewriting existing label into same sector */
-/* If mdas is supplied it overwrites existing mdas e.g. used with pvcreate */
-static int _text_pv_write(const struct format_type *fmt, struct physical_volume *pv,
- struct dm_list *mdas, int64_t label_sector)
+static int _text_pv_write(const struct format_type *fmt, struct physical_volume *pv)
{
+ struct text_fid_pv_context *fid_pv_tc;
+ struct format_instance *fid = pv->fid;
struct label *label;
+ int64_t label_sector;
struct lvmcache_info *info;
struct mda_context *mdac;
struct metadata_area *mda;
+ unsigned mda_index;
char buf[MDA_HEADER_SIZE] __attribute__((aligned(8)));
struct mda_header *mdah = (struct mda_header *) buf;
- uint64_t adjustment;
struct data_area_list *da;
- /* FIXME Test mode don't update cache? */
-
- if (!(info = lvmcache_add(fmt->labeller, (char *) &pv->id, pv->dev,
- FMT_TEXT_ORPHAN_VG_NAME, NULL, 0)))
+ /* Add a new cache entry with PV info or update existing one. */
+ if (!(info = lvmcache_add(fmt->labeller, (const char *) &pv->id,
+ pv->dev, FMT_TEXT_ORPHAN_VG_NAME, NULL, 0)))
return_0;
+
label = info->label;
- if (label_sector != -1)
+ /*
+ * We can change the label sector for a
+ * plain PV that is not part of a VG only!
+ */
+ if (fid && (!fid->type & FMT_INSTANCE_VG) &&
+ (fid_pv_tc = (struct text_fid_pv_context *) pv->fid->private) &&
+ ((label_sector = fid_pv_tc->label_sector) != -1))
label->sector = label_sector;
info->device_size = pv->size << SECTOR_SHIFT;
info->fmt = fmt;
- /* If mdas supplied, use them regardless of existing ones, */
- /* otherwise retain existing ones */
- if (mdas) {
- if (info->mdas.n)
- del_mdas(&info->mdas);
- else
- dm_list_init(&info->mdas);
- dm_list_iterate_items(mda, mdas) {
- mdac = mda->metadata_locn;
- log_debug("Creating metadata area on %s at sector %"
- PRIu64 " size %" PRIu64 " sectors",
- dev_name(mdac->area.dev),
- mdac->area.start >> SECTOR_SHIFT,
- mdac->area.size >> SECTOR_SHIFT);
- add_mda(fmt, NULL, &info->mdas, mdac->area.dev,
- mdac->area.start, mdac->area.size, mda_is_ignored(mda));
- }
- /* FIXME Temporary until mda creation supported by tools */
- } else if (!info->mdas.n) {
+ /* Flush all cached metadata areas, we will reenter new/modified ones. */
+ if (info->mdas.n)
+ del_mdas(&info->mdas);
+ else
dm_list_init(&info->mdas);
+
+ /*
+ * Add all new or modified metadata areas for this PV stored in
+ * its format instance. If this PV is not part of a VG yet,
+ * pv->fid will be used. Otherwise pv->vg->fid will be used.
+ * The fid_get_mda_indexed fn can handle that transparently,
+ * just pass the right format_instance in.
+ */
+ for (mda_index = 0; mda_index < FMT_TEXT_MAX_MDAS_PER_PV; mda_index++) {
+ if (!(mda = fid_get_mda_indexed(fid, (const char *) &pv->id,
+ ID_LEN, mda_index)))
+ continue;
+
+ mdac = (struct mda_context *) mda->metadata_locn;
+ log_debug("Creating metadata area on %s at sector %"
+ PRIu64 " size %" PRIu64 " sectors",
+ dev_name(mdac->area.dev),
+ mdac->area.start >> SECTOR_SHIFT,
+ mdac->area.size >> SECTOR_SHIFT);
+ add_mda(fmt, NULL, &info->mdas, mdac->area.dev,
+ mdac->area.start, mdac->area.size, mda_is_ignored(mda));
}
/*
- * If no pe_start supplied but PV already exists,
- * get existing value; use-cases include:
- * - pvcreate on PV without prior pvremove
- * - vgremove on VG with PV(s) that have pe_start=0 (hacked cfg)
+ * FIXME: Allow writing zero offset/size data area to disk.
+ * This requires defining a special value since we can't
+ * write offset/size that is 0/0 - this is already reserved
+ * as a delimiter in data/metadata area area list in PV header
+ * (needs exploring compatibility with older lvm2).
+ */
+
+ /*
+ * We can't actually write pe_start = 0 (a data area offset)
+ * in PV header now. We need to replace this value here. This can
+ * happen with vgcfgrestore with redefined pe_start or
+ * pvcreate --restorefile. However, we can can have this value in
+ * metadata which will override the value in the PV header.
*/
if (info->das.n) {
if (!pv->pe_start)
@@ -1319,66 +1340,7 @@ static int _text_pv_write(const struct format_type *fmt, struct physical_volume
} else
dm_list_init(&info->das);
-#if 0
- /*
- * FIXME: ideally a pre-existing pe_start seen in .pv_write
- * would always be preserved BUT 'pvcreate on PV without prior pvremove'
- * could easily cause the pe_start to overlap with the first mda!
- */
- if (pv->pe_start) {
- log_very_verbose("%s: preserving pe_start=%lu",
- pv_dev_name(pv), pv->pe_start);
- goto preserve_pe_start;
- }
-#endif
-
- /*
- * If pe_start is still unset, set it to first aligned
- * sector after any metadata areas that begin before pe_start.
- */
- if (!pv->pe_start) {
- pv->pe_start = pv->pe_align;
- if (pv->pe_align_offset)
- pv->pe_start += pv->pe_align_offset;
- }
- dm_list_iterate_items(mda, &info->mdas) {
- mdac = (struct mda_context *) mda->metadata_locn;
- if (pv->dev == mdac->area.dev &&
- ((mdac->area.start <= (pv->pe_start << SECTOR_SHIFT)) ||
- (mdac->area.start <= lvm_getpagesize() &&
- pv->pe_start < (lvm_getpagesize() >> SECTOR_SHIFT))) &&
- (mdac->area.start + mdac->area.size >
- (pv->pe_start << SECTOR_SHIFT))) {
- pv->pe_start = (mdac->area.start + mdac->area.size)
- >> SECTOR_SHIFT;
- /* Adjust pe_start to: (N * pe_align) + pe_align_offset */
- if (pv->pe_align) {
- adjustment =
- (pv->pe_start - pv->pe_align_offset) % pv->pe_align;
- if (adjustment)
- pv->pe_start += (pv->pe_align - adjustment);
-
- log_very_verbose("%s: setting pe_start=%" PRIu64
- " (orig_pe_start=%" PRIu64 ", "
- "pe_align=%lu, pe_align_offset=%lu, "
- "adjustment=%" PRIu64 ")",
- pv_dev_name(pv), pv->pe_start,
- (adjustment ?
- pv->pe_start - (pv->pe_align - adjustment) :
- pv->pe_start),
- pv->pe_align, pv->pe_align_offset, adjustment);
- }
- }
- }
- if (pv->pe_start >= pv->size) {
- log_error("Data area is beyond end of device %s!",
- pv_dev_name(pv));
- return 0;
- }
-
- /* FIXME: preserve_pe_start: */
- if (!add_da
- (NULL, &info->das, pv->pe_start << SECTOR_SHIFT, UINT64_C(0)))
+ if (!add_da(NULL, &info->das, pv->pe_start << SECTOR_SHIFT, UINT64_C(0)))
return_0;
if (!dev_open(pv->dev))
@@ -1397,11 +1359,17 @@ static int _text_pv_write(const struct format_type *fmt, struct physical_volume
}
}
- if (!label_write(pv->dev, label)) {
+ if (!label_write(pv->dev, info->label)) {
dev_close(pv->dev);
return_0;
}
+ /*
+ * FIXME: We should probably use the format instance's metadata
+ * areas for label_write and only if it's successful,
+ * update the cache afterwards?
+ */
+
if (!dev_close(pv->dev))
return_0;
diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index b57f6ff4..6cc02bd5 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -384,8 +384,7 @@ struct dm_list *get_vgnames(struct cmd_context *cmd, int include_internal);
struct dm_list *get_vgids(struct cmd_context *cmd, int include_internal);
int scan_vgs_for_pvs(struct cmd_context *cmd, int warnings);
-int pv_write(struct cmd_context *cmd, struct physical_volume *pv,
- struct dm_list *mdas, int64_t label_sector);
+int pv_write(struct cmd_context *cmd, struct physical_volume *pv);
int move_pv(struct volume_group *vg_from, struct volume_group *vg_to,
const char *pv_name);
int move_pvs_used_by_lv(struct volume_group *vg_from,
diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
index e1cf0e50..68e4b070 100644
--- a/lib/metadata/metadata.c
+++ b/lib/metadata/metadata.c
@@ -586,7 +586,7 @@ int vg_remove(struct volume_group *vg)
}
/* FIXME Write to same sector label was read from */
- if (!pv_write(vg->cmd, pv, NULL, INT64_C(-1))) {
+ if (!pv_write(vg->cmd, pv)) {
log_error("Failed to remove physical volume \"%s\""
" from volume group \"%s\"",
pv_dev_name(pv), vg->name);
@@ -1511,7 +1511,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;
}
@@ -3536,8 +3536,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");
@@ -3550,7 +3549,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;
@@ -3569,7 +3568,7 @@ int pv_write_orphan(struct cmd_context *cmd, struct physical_volume *pv)
return 0;
}
- if (!pv_write(cmd, pv, NULL, INT64_C(-1))) {
+ if (!pv_write(cmd, pv)) {
log_error("Failed to clear metadata from physical "
"volume \"%s\" after removal from \"%s\"",
pv_dev_name(pv), old_vg_name);
diff --git a/lib/metadata/metadata.h b/lib/metadata/metadata.h
index 18b53542..6acb30b8 100644
--- a/lib/metadata/metadata.h
+++ b/lib/metadata/metadata.h
@@ -297,8 +297,7 @@ struct format_handler {
* pv->vg_name must be a valid orphan VG name
*/
int (*pv_write) (const struct format_type * fmt,
- struct physical_volume * pv, struct dm_list * mdas,
- int64_t label_sector);
+ struct physical_volume * pv);
/*
* Tweak an already filled out a lv eg, check there
diff --git a/tools/pvchange.c b/tools/pvchange.c
index 6e0fc2d3..0ffe7df4 100644
--- a/tools/pvchange.c
+++ b/tools/pvchange.c
@@ -139,7 +139,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);
return 0;
@@ -161,7 +161,7 @@ static int _pvchange_single(struct cmd_context *cmd, struct volume_group *vg,
return 0;
}
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);
return 0;
diff --git a/tools/pvresize.c b/tools/pvresize.c
index f347d9d3..f1870c6c 100644
--- a/tools/pvresize.c
+++ b/tools/pvresize.c
@@ -150,7 +150,7 @@ static int _pv_resize_single(struct cmd_context *cmd,
goto out;
}
backup(vg);
- } else if (!(pv_write(cmd, pv, NULL, INT64_C(-1)))) {
+ } else if (!(pv_write(cmd, pv))) {
log_error("Failed to store physical volume \"%s\"",
pv_name);
goto out;
diff --git a/tools/vgconvert.c b/tools/vgconvert.c
index e19fa480..3c9ff653 100644
--- a/tools/vgconvert.c
+++ b/tools/vgconvert.c
@@ -154,9 +154,7 @@ static int vgconvert_single(struct cmd_context *cmd, const char *vg_name,
log_very_verbose("Writing physical volume data to disk \"%s\"",
pv_dev_name(pv));
- if (!(pv_write(cmd, pv, &mdas,
- arg_int64_value(cmd, labelsector_ARG,
- DEFAULT_LABELSECTOR)))) {
+ if (!(pv_write(cmd, pv))) {
log_error("Failed to write physical volume \"%s\"",
pv_dev_name(pv));
log_error("Use pvcreate and vgcfgrestore to repair "
diff --git a/tools/vgreduce.c b/tools/vgreduce.c
index 5e61cf83..8d3cb1cd 100644
--- a/tools/vgreduce.c
+++ b/tools/vgreduce.c
@@ -438,7 +438,7 @@ static int _vgreduce_single(struct cmd_context *cmd, struct volume_group *vg,
goto bad;
}
- if (!pv_write(cmd, pv, NULL, INT64_C(-1))) {
+ if (!pv_write(cmd, pv)) {
log_error("Failed to clear metadata from physical "
"volume \"%s\" "
"after removal from \"%s\"", name, vg->name);