master - config: fix config node lookup inside empty sections to not return the section itself
by Peter Rajnoha
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=6c81cd26ccb03f...
Commit: 6c81cd26ccb03f3452fedca651c876f2709ff0b8
Parent: a9d0e25627f751026b2c486cec97c61ecf2af309
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Wed Feb 27 13:47:57 2013 +0100
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Wed Feb 27 13:47:57 2013 +0100
config: fix config node lookup inside empty sections to not return the section itself
When a section was empty in a configuration tree (no children - this is
allowed) and we were looking for a config node inside that section, the
_find_config_node function incorrectly returned the section itself if
the node inside that section was not found.
For example the configuration below:
The config:
abc {
}
And a function call to get the "def" node inside "abc" section:
_find_config_node(..., "abc/def")
...returned the "abc" node instead of NULL ("def" not found).
This in turn caused segfaults in the code using lookups in such
a configuration tree as we (correctly) expected that the node
returned was always the one we were looking for or NULL if not
found. But if incorrect node was returned instead, we processed
that as if this was the node we were looking for and so we
processed its value as well. But sections don't have values => segfault.
---
WHATS_NEW_DM | 1 +
libdm/libdm-config.c | 4 ++--
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/WHATS_NEW_DM b/WHATS_NEW_DM
index 0052e5a..9d9c53d 100644
--- a/WHATS_NEW_DM
+++ b/WHATS_NEW_DM
@@ -1,5 +1,6 @@
Version 1.02.78 -
===================================
+ Fix config node lookup inside empty sections to not return the section itself.
Extend support for status info of thin pool target.
Fix segfault for truncated string token in config file after the first '"'.
Close open dmeventd FIFO file descriptors on exec (FD_CLOEXEC).
diff --git a/libdm/libdm-config.c b/libdm/libdm-config.c
index cc726ae..bd29d32 100644
--- a/libdm/libdm-config.c
+++ b/libdm/libdm-config.c
@@ -752,12 +752,12 @@ static const struct dm_config_node *_find_config_node(const void *start,
if (cn_found && *e)
cn = cn_found->child;
else
- break; /* don't move into the last node */
+ return cn_found;
path = e;
}
- return cn_found;
+ return NULL;
}
static const struct dm_config_node *_find_first_config_node(const void *start, const char *path)
11 years, 1 month
master - cleanup: remove struct pv_header_extension reference from struct pv_header
by Peter Rajnoha
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=a9d0e25627f751...
Commit: a9d0e25627f751026b2c486cec97c61ecf2af309
Parent: 9d5a3c16dd4f5ea64ba3d89ead049a116f728d64
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Wed Feb 27 10:47:24 2013 +0100
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Wed Feb 27 10:47:24 2013 +0100
cleanup: remove struct pv_header_extension reference from struct pv_header
Just to prevent accidental and improper use when reading the layout
from disk because of the already existing disk_areas_xl[0] lists
that are variable in size. We can read pv_header_extension only
after we know exactly where the lists end...
---
lib/format_text/layout.h | 3 ---
1 files changed, 0 insertions(+), 3 deletions(-)
diff --git a/lib/format_text/layout.h b/lib/format_text/layout.h
index 92dc582..14f9930 100644
--- a/lib/format_text/layout.h
+++ b/lib/format_text/layout.h
@@ -43,9 +43,6 @@ struct pv_header {
/* NULL-terminated list of data areas followed by */
/* NULL-terminated list of metadata area headers */
struct disk_locn disk_areas_xl[0]; /* Two lists */
-
- /* PV header extension */
- struct pv_header_extension ext;
} __attribute__ ((packed));
/*
11 years, 1 month
master - lvmetad: fix to properly process embedding area
by Peter Rajnoha
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=9d5a3c16dd4f5e...
Commit: 9d5a3c16dd4f5ea64ba3d89ead049a116f728d64
Parent: b3776468fa07a0bc173dd01152a4f6010c4d174d
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Wed Feb 27 10:36:49 2013 +0100
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Wed Feb 27 10:36:49 2013 +0100
lvmetad: fix to properly process embedding area
---
lib/cache/lvmetad.c | 12 ++++++++----
1 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/lib/cache/lvmetad.c b/lib/cache/lvmetad.c
index 2f9ffea..3cde71e 100644
--- a/lib/cache/lvmetad.c
+++ b/lib/cache/lvmetad.c
@@ -306,9 +306,12 @@ static struct lvmcache_info *_pv_populate_lvmcache(
do {
sprintf(da_id, "ea%d", i);
da = dm_config_find_node(cn->child, da_id);
- if (!dm_config_get_uint64(da->child, "offset", &offset)) return_0;
- if (!dm_config_get_uint64(da->child, "size", &size)) return_0;
- lvmcache_add_ea(info, offset, size);
+ if (da) {
+ if (!dm_config_get_uint64(da->child, "offset", &offset)) return_0;
+ if (!dm_config_get_uint64(da->child, "size", &size)) return_0;
+ lvmcache_add_ea(info, offset, size);
+ }
+ ++i;
} while (da);
return info;
@@ -675,7 +678,7 @@ static int _extract_disk_location(const char *name, struct disk_locn *dl, void *
if (!dl)
return 1;
- (void) dm_snprintf(id, 32, "name%d", b->i);
+ (void) dm_snprintf(id, 32, "%s%d", name, b->i);
if (!(cn = make_config_node(b->cft, id, b->cft->root, b->pre_sib)))
return 0;
if (!config_make_nodes(b->cft, cn, NULL,
@@ -710,6 +713,7 @@ static int _extract_mdas(struct lvmcache_info *info, struct dm_config_tree *cft,
baton.i = 0;
if (!lvmcache_foreach_da(info, &_extract_da, &baton))
return 0;
+ baton.i = 0;
if (!lvmcache_foreach_ea(info, &_extract_ea, &baton))
return 0;
11 years, 1 month
master - WHATS_NEW: add lines for embedding area support
by Peter Rajnoha
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=b3776468fa07a0...
Commit: b3776468fa07a0bc173dd01152a4f6010c4d174d
Parent: 28a5f6bc3833ad2f84e6d00745fc103d508708a6
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Tue Feb 26 15:50:43 2013 +0100
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Tue Feb 26 15:50:43 2013 +0100
WHATS_NEW: add lines for embedding area support
---
WHATS_NEW | 3 +++
1 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/WHATS_NEW b/WHATS_NEW
index dc4fc8f..3a837aa 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,8 @@
Version 2.02.99 -
===================================
+ Add pvs -o ea_start,ea_size to report embedding area start and size.
+ Add --embeddingareasize to pvcreate and vgconvert to create an embedding area.
+ Add PV header extension: extension version, flags and embedding areas.
Initial support for lvconvert of thin external origin.
Add _lv_remove_segs_using_this_lv() for removal of dependent lvs.
Improve activation code for better support of stacked devices.
11 years, 2 months
master - man: update pvcreate/pvs/vgconvert man page to cover embedding area support
by Peter Rajnoha
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=28a5f6bc3833ad...
Commit: 28a5f6bc3833ad2f84e6d00745fc103d508708a6
Parent: ea69cda4b089f96b89c178bcef3ed44df86cf825
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Tue Feb 26 14:10:11 2013 +0100
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Tue Feb 26 14:46:42 2013 +0100
man: update pvcreate/pvs/vgconvert man page to cover embedding area support
---
man/pvcreate.8.in | 13 +++++++++++++
man/pvs.8.in | 6 +++---
man/vgconvert.8.in | 2 ++
3 files changed, 18 insertions(+), 3 deletions(-)
diff --git a/man/pvcreate.8.in b/man/pvcreate.8.in
index 3fec8dc..1fda0ad 100644
--- a/man/pvcreate.8.in
+++ b/man/pvcreate.8.in
@@ -12,6 +12,8 @@ pvcreate \- initialize a disk or partition for use by LVM
.RB [ \-\-force ]]
.RB [ \-y | \-\-yes ]
.RB [ \-\-labelsector ]
+.RB [ \-\-embeddingareasize
+.IR size ]
.RB [ \-M | \-\-metadatatype
.IR type ]
.RB [ \-\- [ pv ] metadatacopies
@@ -163,6 +165,17 @@ sector (sector 1). This lets you use a different sector near the
start of the disk (between 0 and 3 inclusive - see LABEL_SCAN_SECTORS
in the source). Use with care.
.TP
+.B \-\-embeddingareasize \fIsize
+Create a separate embedding area of specified size besides PV's data
+area. The embedding area is an area of reserved space on the PV from
+which LVM2 will not allocate any extents and it's kept untouched for
+use with external tools to embed their own data or metadata. The start
+of the embedding area is always aligned, see also \fB--dataalignment\fP
+and \fB--dataalignmentoffset\fP. The embedding area size may eventually
+end up increased due to the alignment, but it's never less than the
+size that is requested. To see the embedding area start and size of
+an existing Physical Volume use \fBpvs -o +ea_start,ea_size\fP.
+.TP
.B \-\-setphysicalvolumesize \fIsize
Overrides the automatically-detected size of the PV. Use with care.
.SH Examples
diff --git a/man/pvs.8.in b/man/pvs.8.in
index 4bdfa12..7fff4fd 100644
--- a/man/pvs.8.in
+++ b/man/pvs.8.in
@@ -63,9 +63,9 @@ and \fB-o pvseg_all\fP to select all Physical Volume segment columns.
Use \fB-o help\fP to view the full list of columns available.
.IP
Column names include: pv_fmt, pv_uuid, dev_size, pv_name, pv_mda_free,
-pv_mda_size, pe_start, pv_size, pv_free, pv_used, pv_attr, pv_pe_count,
-pv_pe_alloc_count, pv_tags, pv_mda_count, pv_mda_used_count,
-pvseg_start, and pvseg_size.
+pv_mda_size, ea_start, ea_size, pe_start, pv_size, pv_free, pv_used,
+pv_attr, pv_pe_count, pv_pe_alloc_count, pv_tags, pv_mda_count,
+pv_mda_used_count, pvseg_start, and pvseg_size
.IP
With \fB\-\-segments\fP, any "pvseg_" prefixes are optional; otherwise any
"pv_" prefixes are optional. Columns mentioned in \fBvgs\fP(8) can also
diff --git a/man/vgconvert.8.in b/man/vgconvert.8.in
index 95ea41c..6567a9e 100644
--- a/man/vgconvert.8.in
+++ b/man/vgconvert.8.in
@@ -8,6 +8,8 @@ vgconvert \- convert volume group metadata format
.RB [ \-t | \-\-test ]
.RB [ \-v | \-\-verbose ]
.RB [ \-\-labelsector ]
+.RB [ \-\-embeddingareasize
+.IR size ]
.RB [ \-M | \-\-metadatatype
.IR type ]
.RB [ \-\-pvmetadatacopies
11 years, 2 months
master - report: add reporting fields for Embedding Area start and size
by Peter Rajnoha
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=ea69cda4b089f9...
Commit: ea69cda4b089f96b89c178bcef3ed44df86cf825
Parent: 86f65a3f2bf994a23aed7b29aae9bbab833d485a
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Sat Feb 16 15:10:47 2013 +0100
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Tue Feb 26 14:46:42 2013 +0100
report: add reporting fields for Embedding Area start and size
There are new reporting fields for Embedding Area: ea_start and ea_size.
An example of 1m Embedding Area and relevant reporting fields:
raw/~ # pvs -o pv_name,pe_start,ea_start,ea_size
PV 1st PE EA start EA size
/dev/sda 2.00m 1.00m 1.00m
---
lib/report/columns.h | 2 ++
lib/report/properties.c | 4 ++++
2 files changed, 6 insertions(+), 0 deletions(-)
diff --git a/lib/report/columns.h b/lib/report/columns.h
index 87b22ae..23d3e11 100644
--- a/lib/report/columns.h
+++ b/lib/report/columns.h
@@ -108,6 +108,8 @@ FIELD(PVS, pv, NUM, "Alloc", pe_alloc_count, 5, uint32, pv_pe_alloc_count, "Tota
FIELD(PVS, pv, STR, "PV Tags", tags, 7, tags, pv_tags, "Tags, if any.", 0)
FIELD(PVS, pv, NUM, "#PMda", id, 5, pvmdas, pv_mda_count, "Number of metadata areas on this device.", 0)
FIELD(PVS, pv, NUM, "#PMdaUse", id, 8, pvmdasused, pv_mda_used_count, "Number of metadata areas in use on this device.", 0)
+FIELD(PVS, pv, NUM, "EA start", ea_start, 8, size64, ea_start, "Offset to the start of Embedding Area on the underlying device.", 0)
+FIELD(PVS, pv, NUM, "EA size", ea_size, 7, size64, ea_size, "Size of Embedding Area in current units.", 0)
FIELD(VGS, vg, STR, "Fmt", cmd, 3, vgfmt, vg_fmt, "Type of metadata.", 0)
FIELD(VGS, vg, STR, "VG UUID", id, 38, uuid, vg_uuid, "Unique identifier.", 0)
diff --git a/lib/report/properties.c b/lib/report/properties.c
index 6a4d960..08443d4 100644
--- a/lib/report/properties.c
+++ b/lib/report/properties.c
@@ -155,6 +155,10 @@ GET_PV_NUM_PROPERTY_FN(pv_mda_count, pv_mda_count(pv))
#define _pv_mda_count_set _not_implemented_set
GET_PV_NUM_PROPERTY_FN(pv_mda_used_count, pv_mda_used_count(pv))
#define _pv_mda_used_count_set _not_implemented_set
+GET_PV_NUM_PROPERTY_FN(ea_start, SECTOR_SIZE * pv->ea_start)
+#define _ea_start_set _not_implemented_set
+GET_PV_NUM_PROPERTY_FN(ea_size, SECTOR_SIZE * pv->ea_size)
+#define _ea_size_set _not_implemented_set
/* LV */
GET_LV_STR_PROPERTY_FN(lv_uuid, lv_uuid_dup(lv))
11 years, 2 months
master - tools: add embeddingareasize arg to pvcreate and vgconvert
by Peter Rajnoha
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=86f65a3f2bf994...
Commit: 86f65a3f2bf994a23aed7b29aae9bbab833d485a
Parent: b778653f03702a967df11d51d842abb9a9b86068
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Fri Feb 15 11:14:26 2013 +0100
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Tue Feb 26 14:46:41 2013 +0100
tools: add embeddingareasize arg to pvcreate and vgconvert
To create an Embedding Area during PV creation (pvcreate or as part of
the vgconvert operation), we need to define the Embedding Area size.
The Embedding Area start will be calculated automatically by the tools.
This patch adds --embeddingareasize argument to pvcreate and vgconvert.
---
tools/args.h | 1 +
tools/commands.h | 15 +++++++++------
tools/toollib.c | 14 ++++++++++++++
tools/vgconvert.c | 15 +++++++++++++++
4 files changed, 39 insertions(+), 6 deletions(-)
diff --git a/tools/args.h b/tools/args.h
index b140cdb..08ace69 100644
--- a/tools/args.h
+++ b/tools/args.h
@@ -26,6 +26,7 @@ arg(vgmetadatacopies_ARG, '\0', "vgmetadatacopies", metadatacopies_arg, 0)
arg(metadatacopies_ARG, '\0', "metadatacopies", metadatacopies_arg, 0)
arg(metadatasize_ARG, '\0', "metadatasize", size_mb_arg, 0)
arg(metadataignore_ARG, '\0', "metadataignore", yes_no_arg, 0)
+arg(embeddingareasize_ARG, '\0', "embeddingareasize", size_mb_arg, 0)
arg(norestorefile_ARG, '\0', "norestorefile", NULL, 0)
arg(restorefile_ARG, '\0', "restorefile", string_arg, 0)
arg(labelsector_ARG, '\0', "labelsector", int_arg, 0)
diff --git a/tools/commands.h b/tools/commands.h
index 32d3c96..dedba54 100644
--- a/tools/commands.h
+++ b/tools/commands.h
@@ -540,6 +540,7 @@ xx(pvcreate,
"\t[-M|--metadatatype 1|2]" "\n"
"\t[--pvmetadatacopies #copies]" "\n"
"\t[--metadatasize MetadataSize[bBsSkKmMgGtTpPeE]]" "\n"
+ "\t[--embeddingareasize EmbeddingAreaSize[bBsSkKmMgGtTpPeE]]" "\n"
"\t[--dataalignment Alignment[bBsSkKmMgGtTpPeE]]" "\n"
"\t[--dataalignmentoffset AlignmentOffset[bBsSkKmMgGtTpPeE]]" "\n"
"\t[--setphysicalvolumesize PhysicalVolumeSize[bBsSkKmMgGtTpPeE]" "\n"
@@ -551,10 +552,10 @@ xx(pvcreate,
"\t[--version] " "\n"
"\tPhysicalVolume [PhysicalVolume...]\n",
- dataalignment_ARG, dataalignmentoffset_ARG, force_ARG, test_ARG,
- labelsector_ARG, metadatatype_ARG, metadatacopies_ARG,
- metadatasize_ARG, metadataignore_ARG, norestorefile_ARG,
- physicalvolumesize_ARG, pvmetadatacopies_ARG,
+ dataalignment_ARG, dataalignmentoffset_ARG, embeddingareasize_ARG,
+ force_ARG, test_ARG, labelsector_ARG, metadatatype_ARG,
+ metadatacopies_ARG, metadatasize_ARG, metadataignore_ARG,
+ norestorefile_ARG, physicalvolumesize_ARG, pvmetadatacopies_ARG,
restorefile_ARG, uuidstr_ARG, yes_ARG, zero_ARG)
xx(pvdata,
@@ -797,13 +798,15 @@ xx(vgconvert,
"\t[-M|--metadatatype 1|2]" "\n"
"\t[--pvmetadatacopies #copies]" "\n"
"\t[--metadatasize MetadataSize[bBsSkKmMgGtTpPeE]]" "\n"
+ "\t[--embeddingareasize EmbeddingAreaSize[bBsSkKmMgGtTpPeE]]" "\n"
"\t[-t|--test] " "\n"
"\t[-v|--verbose] " "\n"
"\t[--version] " "\n"
"\tVolumeGroupName [VolumeGroupName...]\n",
- force_ARG, test_ARG, labelsector_ARG, metadatatype_ARG, metadatacopies_ARG,
- pvmetadatacopies_ARG, metadatasize_ARG )
+ force_ARG, test_ARG, labelsector_ARG, embeddingareasize_ARG,
+ metadatatype_ARG, metadatacopies_ARG, pvmetadatacopies_ARG,
+ metadatasize_ARG )
xx(vgcreate,
"Create a volume group",
diff --git a/tools/toollib.c b/tools/toollib.c
index 3717bde..7043ea4 100644
--- a/tools/toollib.c
+++ b/tools/toollib.c
@@ -1413,6 +1413,13 @@ int pvcreate_params_validate(struct cmd_context *cmd,
return 0;
}
+ if (!(cmd->fmt->features & FMT_EAS) &&
+ arg_count(cmd, embeddingareasize_ARG)) {
+ log_error("Embedding area parameters only "
+ "apply to text format.");
+ return 0;
+ }
+
if (arg_count(cmd, pvmetadatacopies_ARG) &&
arg_int_value(cmd, pvmetadatacopies_ARG, -1) > 2) {
log_error("Metadatacopies may only be 0, 1 or 2");
@@ -1482,6 +1489,11 @@ int pvcreate_params_validate(struct cmd_context *cmd,
return 0;
}
+ if (arg_sign_value(cmd, embeddingareasize_ARG, SIGN_NONE) == SIGN_MINUS) {
+ log_error("Embedding area size may not be negative");
+ return 0;
+ }
+
pp->pvmetadatasize = arg_uint64_value(cmd, metadatasize_ARG, UINT64_C(0));
if (!pp->pvmetadatasize)
pp->pvmetadatasize = find_config_tree_int(cmd,
@@ -1494,6 +1506,8 @@ int pvcreate_params_validate(struct cmd_context *cmd,
"metadata/pvmetadatacopies",
DEFAULT_PVMETADATACOPIES);
+ pp->rp.ea_size = arg_uint64_value(cmd, embeddingareasize_ARG, pp->rp.ea_size);
+
return 1;
}
diff --git a/tools/vgconvert.c b/tools/vgconvert.c
index 85f68f2..3671767 100644
--- a/tools/vgconvert.c
+++ b/tools/vgconvert.c
@@ -63,6 +63,15 @@ static int vgconvert_single(struct cmd_context *cmd, const char *vg_name,
DEFAULT_PVMETADATACOPIES);
}
+ if (cmd->fmt->features & FMT_EAS) {
+ if (arg_sign_value(cmd, embeddingareasize_ARG, SIGN_NONE) == SIGN_MINUS) {
+ log_error("Embedding area size may not be negative");
+ return EINVALID_CMD_LINE;
+ }
+
+ rp.ea_size = arg_uint64_value(cmd, embeddingareasize_ARG, UINT64_C(0));
+ }
+
if (!archive(vg)) {
log_error("Archive of \"%s\" metadata failed.", vg_name);
return ECMD_FAILED;
@@ -227,6 +236,12 @@ int vgconvert(struct cmd_context *cmd, int argc, char **argv)
return EINVALID_CMD_LINE;
}
+ if (!(cmd->fmt->features & FMT_EAS) &&
+ arg_count(cmd, embeddingareasize_ARG)) {
+ log_error("Embedding area parameters only apply to text format");
+ return EINVALID_CMD_LINE;
+ }
+
return process_each_vg(cmd, argc, argv, READ_FOR_UPDATE, NULL,
&vgconvert_single);
}
11 years, 2 months
master - pv_header_extension: add support for writing PV header extension (flags & Embedding Area)
by Peter Rajnoha
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=b778653f03702a...
Commit: b778653f03702a967df11d51d842abb9a9b86068
Parent: 9dbe25709e3805fbbc8024f0be68de2aae815747
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Fri Feb 15 11:02:53 2013 +0100
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Tue Feb 26 11:28:00 2013 +0100
pv_header_extension: add support for writing PV header extension (flags & Embedding Area)
The PV header extension information (PV header extension version, flags
and list of Embedding Area locations) is stored just beyond the PV header base.
When calculating the Embedding Area start value (ea_start), the same logic is
used as when calculating the pe_start value for Data Area - the value must
follow exactly the same alignment restrictions for its start value
(the alignment detected automatically or provided via command line using
the --dataalignment and --dataalignmentoffset arguments).
The Embedding Area is placed at the very start of the PV, starting at
ea_start. The Data Area starting at pe_start is placed next. The pe_start is
still properly aligned. Due to the pe_start alignment, it's possible that the
resulting Embedding Area size (ea_size) ends up bigger in size than requested
(but never less than requested).
---
lib/format1/format1.c | 2 +
lib/format_text/export.c | 5 ++
lib/format_text/format-text.c | 108 ++++++++++++++++++++++++++++++-------
lib/format_text/text_label.c | 73 ++++++++++++++++++-------
lib/metadata/metadata-exported.h | 2 +
lib/metadata/metadata.c | 2 +
tools/pvcreate.c | 2 +
7 files changed, 153 insertions(+), 41 deletions(-)
diff --git a/lib/format1/format1.c b/lib/format1/format1.c
index c90c266..f3945bc 100644
--- a/lib/format1/format1.c
+++ b/lib/format1/format1.c
@@ -379,6 +379,8 @@ static int _format1_pv_setup(const struct format_type *fmt,
struct pvcreate_restorable_params rp = {.restorefile = NULL,
.id = {{0}},
.idp = NULL,
+ .ea_start = 0,
+ .ea_size = 0,
.pe_start = 0,
.extent_count = 0,
.extent_size = vg->extent_size};
diff --git a/lib/format_text/export.c b/lib/format_text/export.c
index d68daf5..6d83106 100644
--- a/lib/format_text/export.c
+++ b/lib/format_text/export.c
@@ -490,6 +490,11 @@ static int _print_pvs(struct formatter *f, struct volume_group *vg)
outsize(f, vg->extent_size * (uint64_t) pv->pe_count,
"pe_count = %u", pv->pe_count);
+ if (pv->ea_start && pv->ea_size) {
+ outf(f, "ea_start = %" PRIu64, pv->ea_start);
+ outsize(f, pv->ea_size, "ea_size = %" PRIu64, pv->ea_size);
+ }
+
_dec_indent(f);
outf(f, "}");
}
diff --git a/lib/format_text/format-text.c b/lib/format_text/format-text.c
index e1fbf99..774f6ce 100644
--- a/lib/format_text/format-text.c
+++ b/lib/format_text/format-text.c
@@ -1331,6 +1331,9 @@ static int _text_pv_write(const struct format_type *fmt, struct physical_volume
mdac->area.start, mdac->area.size, mda_is_ignored(mda));
}
+ if (!lvmcache_update_eas(info, pv))
+ return_0;
+
/*
* FIXME: Allow writing zero offset/size data area to disk.
* This requires defining a special value since we can't
@@ -1471,12 +1474,7 @@ static int _text_pv_initialise(const struct format_type *fmt,
struct pvcreate_restorable_params *rp,
struct physical_volume *pv)
{
- /*
- * 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 (rp->pe_start != PV_PE_START_CALC)
- pv->pe_start = rp->pe_start;
+ unsigned long adjustment, final_alignment = 0;
if (!data_alignment)
data_alignment = find_config_tree_int(pv->fmt->cmd,
@@ -1506,14 +1504,65 @@ static int _text_pv_initialise(const struct format_type *fmt,
return 0;
}
- if (pv->size < pv->pe_align + pv->pe_align_offset) {
+ final_alignment = pv->pe_align + pv->pe_align_offset;
+
+ if (pv->size < final_alignment) {
log_error("%s: Data alignment must not exceed device size.",
pv_dev_name(pv));
return 0;
}
- if (rp->pe_start == PV_PE_START_CALC)
- pv->pe_start = pv->pe_align + pv->pe_align_offset;
+ if (pv->size < final_alignment + rp->ea_size) {
+ log_error("%s: Embedding area with data-aligned start must "
+ "not exceed device size.", pv_dev_name(pv));
+ return 0;
+ }
+
+ if (rp->pe_start == PV_PE_START_CALC) {
+ /*
+ * Calculate new PE start and embedding area start value.
+ * Make sure both are properly aligned!
+ * If PE start can't be aligned because EA is taking
+ * the whole space, make PE start equal to the PV size
+ * which effectively disables DA - it will have zero size.
+ * This needs to be done as we can't have a PV without any DA.
+ * But we still want to support a PV with EA only!
+ */
+ if (rp->ea_size) {
+ pv->ea_start = final_alignment;
+ pv->ea_size = rp->ea_size;
+ if ((adjustment = rp->ea_size % pv->pe_align))
+ pv->ea_size += pv->pe_align - adjustment;
+ if (pv->size < pv->ea_start + pv->ea_size)
+ pv->ea_size = pv->size - pv->ea_start;
+ pv->pe_start = pv->ea_start + pv->ea_size;
+ } else
+ pv->pe_start = final_alignment;
+ } else {
+ /*
+ * Try to keep the value of PE start set to a firm value if
+ * requested. This is useful when restoring existing PE start
+ * value (e.g. backups). Also, if creating an EA, try to place
+ * it in between the final alignment and existing PE start
+ * if possible.
+ * TODO: Support restoring existing EA from MDA instead like
+ * we do for PE start? This would require adding EA info
+ * in MDA then!
+ */
+ pv->pe_start = rp->pe_start;
+ if (rp->ea_size) {
+ if ((rp->ea_start && rp->ea_start + rp->ea_size > rp->pe_start) ||
+ (rp->pe_start <= final_alignment) ||
+ (rp->pe_start - final_alignment < rp->ea_size)) {
+ log_error("%s: Embedding area would overlap "
+ "data area.", pv_dev_name(pv));
+ return 0;
+ } else {
+ pv->ea_start = rp->ea_start ? : final_alignment;
+ pv->ea_size = rp->ea_size;
+ }
+ }
+ }
if (rp->extent_size)
pv->pe_size = rp->extent_size;
@@ -1938,7 +1987,7 @@ static int _text_pv_add_metadata_area(const struct format_type *fmt,
{
struct format_instance *fid = pv->fid;
const char *pvid = (const char *) (*pv->old_id.uuid ? &pv->old_id : &pv->id);
- uint64_t pe_start, pe_end;
+ uint64_t ea_size, pe_start, pe_end;
uint64_t alignment, alignment_offset;
uint64_t disk_size;
uint64_t mda_start;
@@ -1959,6 +2008,7 @@ static int _text_pv_add_metadata_area(const struct format_type *fmt,
}
pe_start = pv->pe_start << SECTOR_SHIFT;
+ ea_size = pv->ea_size << SECTOR_SHIFT;
alignment = pv->pe_align << SECTOR_SHIFT;
alignment_offset = pv->pe_align_offset << SECTOR_SHIFT;
disk_size = pv->size << SECTOR_SHIFT;
@@ -1994,6 +2044,12 @@ static int _text_pv_add_metadata_area(const struct format_type *fmt,
limit_name = "disk size";
}
+ /* Adjust limits for embedding area if present. */
+ if (ea_size) {
+ limit -= ea_size;
+ limit_name = "ea_start";
+ }
+
if (limit > disk_size)
goto bad;
@@ -2053,8 +2109,11 @@ static int _text_pv_add_metadata_area(const struct format_type *fmt,
* 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;
+ if (ea_size) {
+ pv->ea_start = (mda_start + mda_size) >> SECTOR_SHIFT;
+ pv->pe_start = pv->ea_start + pv->ea_size;
+ } else
+ pv->pe_start = (mda_start + mda_size) >> SECTOR_SHIFT;
}
}
/* Second metadata area at the end of the device. */
@@ -2072,15 +2131,22 @@ static int _text_pv_add_metadata_area(const struct format_type *fmt,
if (pe_start || pe_start_locked) {
limit = pe_end ? pe_end : pe_start;
limit_name = pe_end ? "pe_end" : "pe_start";
- }
- else if ((mda = fid_get_mda_indexed(fid, pvid, ID_LEN, 0)) &&
- (mdac = mda->metadata_locn)) {
- limit = mdac->area.start + mdac->area.size;
- limit_name = "MDA0 end";
- }
- else {
- limit = LABEL_SCAN_SIZE;
- limit_name = "label scan size";
+ } else {
+ if ((mda = fid_get_mda_indexed(fid, pvid, ID_LEN, 0)) &&
+ (mdac = mda->metadata_locn)) {
+ limit = mdac->area.start + mdac->area.size;
+ limit_name = "MDA0 end";
+ }
+ else {
+ limit = LABEL_SCAN_SIZE;
+ limit_name = "label scan size";
+ }
+
+ /* Adjust limits for embedding area if present. */
+ if (ea_size) {
+ limit += ea_size;
+ limit_name = "ea_end";
+ }
}
if (limit > disk_size)
diff --git a/lib/format_text/text_label.c b/lib/format_text/text_label.c
index 7ee9022..32f3347 100644
--- a/lib/format_text/text_label.c
+++ b/lib/format_text/text_label.c
@@ -35,23 +35,28 @@ static int _text_can_handle(struct labeller *l __attribute__((unused)),
return 0;
}
-struct _da_setup_baton {
+struct _dl_setup_baton {
struct disk_locn *pvh_dlocn_xl;
struct device *dev;
};
static int _da_setup(struct disk_locn *da, void *baton)
{
- struct _da_setup_baton *p = baton;
+ struct _dl_setup_baton *p = baton;
p->pvh_dlocn_xl->offset = xlate64(da->offset);
p->pvh_dlocn_xl->size = xlate64(da->size);
p->pvh_dlocn_xl++;
return 1;
}
+static int _ea_setup(struct disk_locn *ea, void *baton)
+{
+ return _da_setup(ea, baton);
+}
+
static int _mda_setup(struct metadata_area *mda, void *baton)
{
- struct _da_setup_baton *p = baton;
+ struct _dl_setup_baton *p = baton;
struct mda_context *mdac = (struct mda_context *) mda->metadata_locn;
if (mdac->area.dev != p->dev)
@@ -64,15 +69,30 @@ static int _mda_setup(struct metadata_area *mda, void *baton)
return 1;
}
+static int _dl_null_termination(void *baton)
+{
+ struct _dl_setup_baton *p = baton;
+
+ p->pvh_dlocn_xl->offset = xlate64(UINT64_C(0));
+ p->pvh_dlocn_xl->size = xlate64(UINT64_C(0));
+ p->pvh_dlocn_xl++;
+
+ return 1;
+}
+
static int _text_write(struct label *label, void *buf)
{
struct label_header *lh = (struct label_header *) buf;
struct pv_header *pvhdr;
+ struct pv_header_extension *pvhdr_ext;
struct lvmcache_info *info;
- struct _da_setup_baton baton;
+ struct _dl_setup_baton baton;
char buffer[64] __attribute__((aligned(8)));
- int da1, mda1, mda2;
+ int ea1, da1, mda1, mda2;
+ /*
+ * PV header base
+ */
/* FIXME Move to where label is created */
strncpy(label->type, LVM2_LABEL, sizeof(label->type));
@@ -89,29 +109,34 @@ static int _text_write(struct label *label, void *buf)
}
baton.dev = lvmcache_device(info);
+ baton.pvh_dlocn_xl = &pvhdr->disk_areas_xl[0];
/* List of data areas (holding PEs) */
- baton.pvh_dlocn_xl = &pvhdr->disk_areas_xl[0];
lvmcache_foreach_da(info, _da_setup, &baton);
-
- /* NULL-termination */
- baton.pvh_dlocn_xl->offset = xlate64(UINT64_C(0));
- baton.pvh_dlocn_xl->size = xlate64(UINT64_C(0));
- baton.pvh_dlocn_xl++;
+ _dl_null_termination(&baton);
/* List of metadata area header locations */
lvmcache_foreach_mda(info, _mda_setup, &baton);
+ _dl_null_termination(&baton);
- /* NULL-termination */
- baton.pvh_dlocn_xl->offset = xlate64(UINT64_C(0));
- baton.pvh_dlocn_xl->size = xlate64(UINT64_C(0));
+ /*
+ * PV header extension
+ */
+ pvhdr_ext = (struct pv_header_extension *) ((char *) baton.pvh_dlocn_xl);
+ pvhdr_ext->version = xlate32(PV_HEADER_EXTENSION_VSN);
+ pvhdr_ext->flags = 0; /* no flags yet */
+
+ /* List of embedding area locations */
+ baton.pvh_dlocn_xl = &pvhdr_ext->embedding_areas_xl[0];
+ lvmcache_foreach_ea(info, _ea_setup, &baton);
+ _dl_null_termination(&baton);
- /* Create debug message with da and mda locations */
- if (xlate64(pvhdr->disk_areas_xl[0].offset) ||
- xlate64(pvhdr->disk_areas_xl[0].size))
- da1 = 0;
- else
- da1 = -1;
+ /* Create debug message with ea, da and mda locations */
+ ea1 = (xlate64(pvhdr_ext->embedding_areas_xl[0].offset) ||
+ xlate64(pvhdr_ext->embedding_areas_xl[0].size)) ? 0 : -1;
+
+ da1 = (xlate64(pvhdr->disk_areas_xl[0].offset) ||
+ xlate64(pvhdr->disk_areas_xl[0].size)) ? 0 : -1;
mda1 = da1 + 2;
mda2 = mda1 + 1;
@@ -126,8 +151,16 @@ static int _text_write(struct label *label, void *buf)
log_debug_metadata("%s: Preparing PV label header %s size %" PRIu64 " with"
"%s%.*" PRIu64 "%s%.*" PRIu64 "%s"
"%s%.*" PRIu64 "%s%.*" PRIu64 "%s"
+ "%s%.*" PRIu64 "%s%.*" PRIu64 "%s"
"%s%.*" PRIu64 "%s%.*" PRIu64 "%s",
dev_name(lvmcache_device(info)), buffer, lvmcache_device_size(info),
+ (ea1 > -1) ? " ea1 (" : "",
+ (ea1 > -1) ? 1 : 0,
+ (ea1 > -1) ? xlate64(pvhdr_ext->embedding_areas_xl[ea1].offset) >> SECTOR_SHIFT : 0,
+ (ea1 > -1) ? "s, " : "",
+ (ea1 > -1) ? 1 : 0,
+ (ea1 > -1) ? xlate64(pvhdr_ext->embedding_areas_xl[ea1].size) >> SECTOR_SHIFT : 0,
+ (ea1 > -1) ? "s)" : "",
(da1 > -1) ? " da1 (" : "",
(da1 > -1) ? 1 : 0,
(da1 > -1) ? xlate64(pvhdr->disk_areas_xl[da1].offset) >> SECTOR_SHIFT : 0,
diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index 6624a40..0ce5ad5 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -398,6 +398,8 @@ struct pvcreate_restorable_params {
const char *restorefile; /* 0 if no --restorefile option */
struct id id; /* FIXME: redundant */
struct id *idp; /* 0 if no --uuid option */
+ uint64_t ea_start;
+ uint64_t ea_size;
uint64_t pe_start;
uint32_t extent_count;
uint32_t extent_size;
diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
index 2c071b0..0996184 100644
--- a/lib/metadata/metadata.c
+++ b/lib/metadata/metadata.c
@@ -1430,6 +1430,8 @@ void pvcreate_params_set_defaults(struct pvcreate_params *pp)
pp->metadataignore = DEFAULT_PVMETADATAIGNORE;
pp->rp.restorefile = 0;
pp->rp.idp = 0;
+ pp->rp.ea_start = 0;
+ pp->rp.ea_size = 0;
pp->rp.pe_start = PV_PE_START_CALC;
pp->rp.extent_count = 0;
pp->rp.extent_size = 0;
diff --git a/tools/pvcreate.c b/tools/pvcreate.c
index eb2fb5e..5b83a18 100644
--- a/tools/pvcreate.c
+++ b/tools/pvcreate.c
@@ -73,6 +73,8 @@ static int pvcreate_restore_params_validate(struct cmd_context *cmd,
uuid, pp->rp.restorefile);
return 0;
}
+ pp->rp.ea_start = pv_ea_start(existing_pvl->pv);
+ pp->rp.ea_size = pv_ea_size(existing_pvl->pv);
pp->rp.pe_start = pv_pe_start(existing_pvl->pv);
pp->rp.extent_size = pv_pe_size(existing_pvl->pv);
pp->rp.extent_count = pv_pe_count(existing_pvl->pv);
11 years, 2 months
master - pv_header_extension: add support for reading PV header extension (flags & Embedding Area)
by Peter Rajnoha
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=9dbe25709e3805...
Commit: 9dbe25709e3805fbbc8024f0be68de2aae815747
Parent: 60c5d4c42f904fb018b51364f1b81aa73cac1969
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Thu Feb 14 16:04:35 2013 +0100
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Tue Feb 26 11:27:23 2013 +0100
pv_header_extension: add support for reading PV header extension (flags & Embedding Area)
New tools with PV header extension support will read the extension
if it exists and it's not an error if it does not exist (so old PVs
will still work seamlessly with new tools).
Old tools without PV header extension support will just ignore any
extension.
As for the Embedding Area location information (its start and size),
there are actually two places where this is stored:
- PV header extension
- VG metadata
The VG metadata contains a copy of what's written in the PV header
extension about the Embedding Area location (NULL value is not copied):
physical_volumes {
pv0 {
id = "AkSSRf-difg-fCCZ-NjAN-qP49-1zzg-S0Fd4T"
device = "/dev/sda" # Hint only
status = ["ALLOCATABLE"]
flags = []
dev_size = 262144 # 128 Megabytes
pe_start = 67584
pe_count = 23 # 92 Megabytes
ea_start = 2048
ea_size = 65536 # 32 Megabytes
}
}
The new metadata fields are "ea_start" and "ea_size".
This is mostly useful when restoring the PV by using existing
metadata backups (e.g. pvcreate --restorefile ...).
New tools does not require these two fields to exist in VG metadata,
they're not compulsory. Therefore, reading old VG metadata which doesn't
contain any Embedding Area information will not end up with any kind
of error but only a debug message that the ea_start and ea_size values
were not found.
Old tools just ignore these extra fields in VG metadata.
---
lib/cache/lvmcache.c | 13 +++++++++++++
lib/cache/lvmetad.c | 40 +++++++++++++++++++++++++++++++---------
lib/format1/format1.c | 1 +
lib/format_text/import_vsn1.c | 17 ++++++++++++++++-
lib/format_text/layout.h | 2 +-
lib/format_text/text_label.c | 26 ++++++++++++++++++++++++++
lib/metadata/pv.c | 10 ++++++++++
lib/metadata/pv.h | 2 ++
tools/pvcreate.c | 1 +
9 files changed, 101 insertions(+), 11 deletions(-)
diff --git a/lib/cache/lvmcache.c b/lib/cache/lvmcache.c
index 4da8fe4..13a722f 100644
--- a/lib/cache/lvmcache.c
+++ b/lib/cache/lvmcache.c
@@ -1479,6 +1479,7 @@ struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
lvmcache_del_mdas(info);
lvmcache_del_das(info);
+ lvmcache_del_eas(info);
} else {
if (existing->dev != dev) {
/* Is the existing entry a duplicate pvid e.g. md ? */
@@ -1723,9 +1724,21 @@ int lvmcache_populate_pv_fields(struct lvmcache_info *info,
return 0;
}
+ /* Currently only support one embedding area at most */
+ if (dm_list_size(&info->eas) > 1) {
+ log_error("Must be at most one embedding area (found %d) on PV %s",
+ dm_list_size(&info->eas), dev_name(info->dev));
+ return 0;
+ }
+
dm_list_iterate_items(da, &info->das)
pv->pe_start = da->disk_locn.offset >> SECTOR_SHIFT;
+ dm_list_iterate_items(da, &info->eas) {
+ pv->ea_start = da->disk_locn.offset >> SECTOR_SHIFT;
+ pv->ea_size = da->disk_locn.size >> SECTOR_SHIFT;
+ }
+
return 1;
}
diff --git a/lib/cache/lvmetad.c b/lib/cache/lvmetad.c
index 886f163..2f9ffea 100644
--- a/lib/cache/lvmetad.c
+++ b/lib/cache/lvmetad.c
@@ -280,6 +280,7 @@ static struct lvmcache_info *_pv_populate_lvmcache(
lvmcache_set_device_size(info, devsize);
lvmcache_del_das(info);
lvmcache_del_mdas(info);
+ lvmcache_del_eas(info);
do {
sprintf(mda_id, "mda%d", i);
@@ -301,6 +302,15 @@ static struct lvmcache_info *_pv_populate_lvmcache(
++i;
} while (da);
+ i = 0;
+ do {
+ sprintf(da_id, "ea%d", i);
+ da = dm_config_find_node(cn->child, da_id);
+ if (!dm_config_get_uint64(da->child, "offset", &offset)) return_0;
+ if (!dm_config_get_uint64(da->child, "size", &size)) return_0;
+ lvmcache_add_ea(info, offset, size);
+ } while (da);
+
return info;
}
@@ -629,7 +639,7 @@ int lvmetad_vg_list_to_lvmcache(struct cmd_context *cmd)
return 1;
}
-struct _extract_mda_baton {
+struct _extract_dl_baton {
int i;
struct dm_config_tree *cft;
struct dm_config_node *pre_sib;
@@ -637,7 +647,7 @@ struct _extract_mda_baton {
static int _extract_mda(struct metadata_area *mda, void *baton)
{
- struct _extract_mda_baton *b = baton;
+ struct _extract_dl_baton *b = baton;
struct dm_config_node *cn;
char id[32];
@@ -656,21 +666,21 @@ static int _extract_mda(struct metadata_area *mda, void *baton)
return 1;
}
-static int _extract_da(struct disk_locn *da, void *baton)
+static int _extract_disk_location(const char *name, struct disk_locn *dl, void *baton)
{
- struct _extract_mda_baton *b = baton;
+ struct _extract_dl_baton *b = baton;
struct dm_config_node *cn;
char id[32];
- if (!da)
+ if (!dl)
return 1;
- (void) dm_snprintf(id, 32, "da%d", b->i);
+ (void) dm_snprintf(id, 32, "name%d", b->i);
if (!(cn = make_config_node(b->cft, id, b->cft->root, b->pre_sib)))
return 0;
if (!config_make_nodes(b->cft, cn, NULL,
- "offset = %"PRId64, (int64_t) da->offset,
- "size = %"PRId64, (int64_t) da->size,
+ "offset = %"PRId64, (int64_t) dl->offset,
+ "size = %"PRId64, (int64_t) dl->size,
NULL))
return 0;
@@ -680,16 +690,28 @@ static int _extract_da(struct disk_locn *da, void *baton)
return 1;
}
+static int _extract_da(struct disk_locn *da, void *baton)
+{
+ return _extract_disk_location("da", da, baton);
+}
+
+static int _extract_ea(struct disk_locn *ea, void *baton)
+{
+ return _extract_disk_location("ea", ea, baton);
+}
+
static int _extract_mdas(struct lvmcache_info *info, struct dm_config_tree *cft,
struct dm_config_node *pre_sib)
{
- struct _extract_mda_baton baton = { .i = 0, .cft = cft, .pre_sib = NULL };
+ struct _extract_dl_baton baton = { .i = 0, .cft = cft, .pre_sib = NULL };
if (!lvmcache_foreach_mda(info, &_extract_mda, &baton))
return 0;
baton.i = 0;
if (!lvmcache_foreach_da(info, &_extract_da, &baton))
return 0;
+ if (!lvmcache_foreach_ea(info, &_extract_ea, &baton))
+ return 0;
return 1;
}
diff --git a/lib/format1/format1.c b/lib/format1/format1.c
index 335a7e2..c90c266 100644
--- a/lib/format1/format1.c
+++ b/lib/format1/format1.c
@@ -423,6 +423,7 @@ static int _format1_pv_write(const struct format_type *fmt, struct physical_volu
lvmcache_update_pv(info, pv, fmt);
lvmcache_del_mdas(info);
lvmcache_del_das(info);
+ lvmcache_del_eas(info);
dm_list_init(&pvs);
diff --git a/lib/format_text/import_vsn1.c b/lib/format_text/import_vsn1.c
index 33ad37d..d5b5a73 100644
--- a/lib/format_text/import_vsn1.c
+++ b/lib/format_text/import_vsn1.c
@@ -165,7 +165,7 @@ static int _read_pv(struct format_instance *fid,
struct physical_volume *pv;
struct pv_list *pvl;
const struct dm_config_value *cv;
- uint64_t size;
+ uint64_t size, ea_start;
if (!(pvl = dm_pool_zalloc(mem, sizeof(*pvl))) ||
!(pvl->pv = dm_pool_zalloc(mem, sizeof(*pvl->pv))))
@@ -246,6 +246,21 @@ static int _read_pv(struct format_instance *fid,
return 0;
}
+ /* Embedding area is not compulsory - just log_debug if not found. */
+ ea_start = size = 0;
+ if (!_read_uint64(pvn, "ea_start", &ea_start))
+ log_debug("PV Embedding Area start value (ea_start) not found.");
+ if (!_read_uint64(pvn, "ea_size", &size))
+ log_debug("PV Embedding Area size (ea_size) not found.");
+ if ((!ea_start && size) || (ea_start && !size)) {
+ log_error("Incomplete embedding area specification for "
+ "physical volume.");
+ return 0;
+ } else {
+ pv->ea_start = ea_start;
+ pv->ea_size = size;
+ }
+
dm_list_init(&pv->tags);
dm_list_init(&pv->segments);
diff --git a/lib/format_text/layout.h b/lib/format_text/layout.h
index 6bd3fe4..92dc582 100644
--- a/lib/format_text/layout.h
+++ b/lib/format_text/layout.h
@@ -29,7 +29,7 @@ struct pv_header_extension {
uint32_t version;
uint32_t flags;
/* NULL-terminated list of embedding areas */
- struct disk_locn embedding_area_xl[0];
+ struct disk_locn embedding_areas_xl[0];
} __attribute__ ((packed));
/* Fields with the suffix _xl should be xlate'd wherever they appear */
diff --git a/lib/format_text/text_label.c b/lib/format_text/text_label.c
index be28f11..7ee9022 100644
--- a/lib/format_text/text_label.c
+++ b/lib/format_text/text_label.c
@@ -336,11 +336,16 @@ static int _text_read(struct labeller *l, struct device *dev, void *buf,
{
struct label_header *lh = (struct label_header *) buf;
struct pv_header *pvhdr;
+ struct pv_header_extension *pvhdr_ext;
struct lvmcache_info *info;
struct disk_locn *dlocn_xl;
uint64_t offset;
+ uint32_t ext_version;
struct _update_mda_baton baton;
+ /*
+ * PV header base
+ */
pvhdr = (struct pv_header *) ((char *) buf + xlate32(lh->offset_xl));
if (!(info = lvmcache_add(l, (char *)pvhdr->pv_uuid, dev,
@@ -354,6 +359,7 @@ static int _text_read(struct labeller *l, struct device *dev, void *buf,
lvmcache_del_das(info);
lvmcache_del_mdas(info);
+ lvmcache_del_eas(info);
/* Data areas holding the PEs */
dlocn_xl = pvhdr->disk_areas_xl;
@@ -369,6 +375,25 @@ static int _text_read(struct labeller *l, struct device *dev, void *buf,
dlocn_xl++;
}
+ dlocn_xl++;
+
+ /*
+ * PV header extension
+ */
+ pvhdr_ext = (struct pv_header_extension *) ((char *) dlocn_xl);
+ if (!(ext_version = xlate32(pvhdr_ext->version)))
+ goto out;
+
+ log_debug("%s: PV header extension version %" PRIu32 " found",
+ dev_name(dev), ext_version);
+
+ /* Embedding areas */
+ dlocn_xl = pvhdr_ext->embedding_areas_xl;
+ while ((offset = xlate64(dlocn_xl->offset))) {
+ lvmcache_add_ea(info, offset, xlate64(dlocn_xl->size));
+ dlocn_xl++;
+ }
+out:
baton.info = info;
baton.label = *label;
@@ -385,6 +410,7 @@ static void _text_destroy_label(struct labeller *l __attribute__((unused)),
lvmcache_del_mdas(info);
lvmcache_del_das(info);
+ lvmcache_del_eas(info);
}
static void _fmt_text_destroy(struct labeller *l)
diff --git a/lib/metadata/pv.c b/lib/metadata/pv.c
index 3cd06aa..6c165a8 100644
--- a/lib/metadata/pv.c
+++ b/lib/metadata/pv.c
@@ -124,6 +124,16 @@ uint32_t pv_pe_size(const struct physical_volume *pv)
return pv_field(pv, pe_size);
}
+uint64_t pv_ea_start(const struct physical_volume *pv)
+{
+ return pv_field(pv, ea_start);
+}
+
+uint64_t pv_ea_size(const struct physical_volume *pv)
+{
+ return pv_field(pv, ea_size);
+}
+
uint64_t pv_pe_start(const struct physical_volume *pv)
{
return pv_field(pv, pe_start);
diff --git a/lib/metadata/pv.h b/lib/metadata/pv.h
index 69d4868..6db9d87 100644
--- a/lib/metadata/pv.h
+++ b/lib/metadata/pv.h
@@ -80,6 +80,8 @@ uint64_t pv_free(const struct physical_volume *pv);
uint64_t pv_status(const struct physical_volume *pv);
uint32_t pv_pe_size(const struct physical_volume *pv);
uint64_t pv_pe_start(const struct physical_volume *pv);
+uint64_t pv_ea_start(const struct physical_volume *pv);
+uint64_t pv_ea_size(const struct physical_volume *pv);
uint32_t pv_pe_count(const struct physical_volume *pv);
uint32_t pv_pe_alloc_count(const struct physical_volume *pv);
uint64_t pv_mda_size(const struct physical_volume *pv);
diff --git a/tools/pvcreate.c b/tools/pvcreate.c
index d7e7e52..eb2fb5e 100644
--- a/tools/pvcreate.c
+++ b/tools/pvcreate.c
@@ -76,6 +76,7 @@ static int pvcreate_restore_params_validate(struct cmd_context *cmd,
pp->rp.pe_start = pv_pe_start(existing_pvl->pv);
pp->rp.extent_size = pv_pe_size(existing_pvl->pv);
pp->rp.extent_count = pv_pe_count(existing_pvl->pv);
+
release_vg(vg);
}
11 years, 2 months
master - pv_header_extension: add supporting infrastructure for PV header extension (flags & Embedding Area)
by Peter Rajnoha
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=60c5d4c42f904f...
Commit: 60c5d4c42f904fb018b51364f1b81aa73cac1969
Parent: 6d8de3638c3e715a1c0273e3fed9daf71a871685
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Thu Feb 14 15:35:57 2013 +0100
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Tue Feb 26 11:25:16 2013 +0100
pv_header_extension: add supporting infrastructure for PV header extension (flags & Embedding Area)
PV header extension comes just beyond the existing PV header base:
PV header base (existing):
- uuid
- device size
- null-terminated list of Data Areas
- null-terminater list of MetaData Areas
PV header extension:
- extension version
- flags
- null-terminated list of Embedding Areas
This patch also adds "eas" (Embedding Areas) list to lvmcache (lvmcache_info)
and it also adds support for common operations on the list (just like for
already existing "das" - Data Areas list):
- lvmcache_add_ea
- lvmcache_update_eas
- lvmcache_foreach_ea
- lvmcache_del_eas
Also, add ea_start and ea_size to struct physical_volume for processing
PV Embedding Area location throughout the code (currently only one
Embedding Area is supported, though the definition on disk allows for
more if needed in the future...).
Also, define FMT_EAS format flag to mark that the format actually
supports Embedding Areas (currently format-text only).
---
lib/cache/lvmcache.c | 44 ++++++++++++++++++++++++++++++++++++++
lib/cache/lvmcache.h | 7 ++++++
lib/format_text/format-text.c | 2 +-
lib/format_text/format-text.h | 3 ++
lib/format_text/layout.h | 12 ++++++++++
lib/format_text/text_label.c | 11 +++++++++
lib/metadata/metadata-exported.h | 1 +
lib/metadata/pv.h | 4 +++
8 files changed, 83 insertions(+), 1 deletions(-)
diff --git a/lib/cache/lvmcache.c b/lib/cache/lvmcache.c
index acdd1c8..4da8fe4 100644
--- a/lib/cache/lvmcache.c
+++ b/lib/cache/lvmcache.c
@@ -38,6 +38,7 @@ struct lvmcache_info {
struct dm_list list; /* Join VG members together */
struct dm_list mdas; /* list head for metadata areas */
struct dm_list das; /* list head for data areas */
+ struct dm_list eas; /* list head for embedding areas */
struct lvmcache_vginfo *vginfo; /* NULL == unknown */
struct label *label;
const struct format_type *fmt;
@@ -1752,6 +1753,13 @@ void lvmcache_del_das(struct lvmcache_info *info)
dm_list_init(&info->das);
}
+void lvmcache_del_eas(struct lvmcache_info *info)
+{
+ if (info->eas.n)
+ del_eas(&info->eas);
+ dm_list_init(&info->eas);
+}
+
int lvmcache_add_mda(struct lvmcache_info *info, struct device *dev,
uint64_t start, uint64_t size, unsigned ignored)
{
@@ -1763,6 +1771,10 @@ int lvmcache_add_da(struct lvmcache_info *info, uint64_t start, uint64_t size)
return add_da(NULL, &info->das, start, size);
}
+int lvmcache_add_ea(struct lvmcache_info *info, uint64_t start, uint64_t size)
+{
+ return add_ea(NULL, &info->eas, start, size);
+}
void lvmcache_update_pv(struct lvmcache_info *info, struct physical_volume *pv,
const struct format_type *fmt)
@@ -1788,6 +1800,25 @@ int lvmcache_update_das(struct lvmcache_info *info, struct physical_volume *pv)
return 1;
}
+int lvmcache_update_eas(struct lvmcache_info *info, struct physical_volume *pv)
+{
+ struct data_area_list *ea;
+ if (info->eas.n) {
+ if (!pv->ea_start && !pv->ea_size)
+ dm_list_iterate_items(ea, &info->eas) {
+ pv->ea_start = ea->disk_locn.offset >> SECTOR_SHIFT;
+ pv->ea_size = ea->disk_locn.size >> SECTOR_SHIFT;
+ }
+ del_das(&info->eas);
+ } else
+ dm_list_init(&info->eas);
+
+ if (!add_ea(NULL, &info->eas, pv->ea_start << SECTOR_SHIFT, pv->ea_size << SECTOR_SHIFT))
+ return_0;
+
+ return 1;
+}
+
int lvmcache_foreach_pv(struct lvmcache_vginfo *vginfo,
int (*fun)(struct lvmcache_info *, void *),
void *baton)
@@ -1832,6 +1863,19 @@ int lvmcache_foreach_da(struct lvmcache_info *info,
return 1;
}
+int lvmcache_foreach_ea(struct lvmcache_info *info,
+ int (*fun)(struct disk_locn *, void *),
+ void *baton)
+{
+ struct data_area_list *ea;
+ dm_list_iterate_items(ea, &info->eas) {
+ if (!fun(&ea->disk_locn, baton))
+ return_0;
+ }
+
+ return 1;
+}
+
/*
* The lifetime of the label returned is tied to the lifetime of the
* lvmcache_info which is the same as lvmcache itself.
diff --git a/lib/cache/lvmcache.h b/lib/cache/lvmcache.h
index 768cd4c..9ceec19 100644
--- a/lib/cache/lvmcache.h
+++ b/lib/cache/lvmcache.h
@@ -118,9 +118,11 @@ int lvmcache_populate_pv_fields(struct lvmcache_info *info,
int lvmcache_check_format(struct lvmcache_info *info, const struct format_type *fmt);
void lvmcache_del_mdas(struct lvmcache_info *info);
void lvmcache_del_das(struct lvmcache_info *info);
+void lvmcache_del_eas(struct lvmcache_info *info);
int lvmcache_add_mda(struct lvmcache_info *info, struct device *dev,
uint64_t start, uint64_t size, unsigned ignored);
int lvmcache_add_da(struct lvmcache_info *info, uint64_t start, uint64_t size);
+int lvmcache_add_ea(struct lvmcache_info *info, uint64_t start, uint64_t size);
const struct format_type *lvmcache_fmt(struct lvmcache_info *info);
struct label *lvmcache_get_label(struct lvmcache_info *info);
@@ -128,6 +130,7 @@ struct label *lvmcache_get_label(struct lvmcache_info *info);
void lvmcache_update_pv(struct lvmcache_info *info, struct physical_volume *pv,
const struct format_type *fmt);
int lvmcache_update_das(struct lvmcache_info *info, struct physical_volume *pv);
+int lvmcache_update_eas(struct lvmcache_info *info, struct physical_volume *pv);
int lvmcache_foreach_mda(struct lvmcache_info *info,
int (*fun)(struct metadata_area *, void *),
void *baton);
@@ -136,6 +139,10 @@ int lvmcache_foreach_da(struct lvmcache_info *info,
int (*fun)(struct disk_locn *, void *),
void *baton);
+int lvmcache_foreach_ea(struct lvmcache_info *info,
+ int (*fun)(struct disk_locn *, void *),
+ void *baton);
+
int lvmcache_foreach_pv(struct lvmcache_vginfo *vg,
int (*fun)(struct lvmcache_info *, void *), void * baton);
diff --git a/lib/format_text/format-text.c b/lib/format_text/format-text.c
index a769daf..e1fbf99 100644
--- a/lib/format_text/format-text.c
+++ b/lib/format_text/format-text.c
@@ -2349,7 +2349,7 @@ struct format_type *create_text_format(struct cmd_context *cmd)
fmt->orphan_vg_name = ORPHAN_VG_NAME(FMT_TEXT_NAME);
fmt->features = FMT_SEGMENTS | FMT_MDAS | FMT_TAGS | FMT_PRECOMMIT |
FMT_UNLIMITED_VOLS | FMT_RESIZE_PV |
- FMT_UNLIMITED_STRIPESIZE;
+ FMT_UNLIMITED_STRIPESIZE | FMT_EAS;
if (!(mda_lists = dm_malloc(sizeof(struct mda_lists)))) {
log_error("Failed to allocate dir_list");
diff --git a/lib/format_text/format-text.h b/lib/format_text/format-text.h
index d8ec255..4706313 100644
--- a/lib/format_text/format-text.h
+++ b/lib/format_text/format-text.h
@@ -58,6 +58,9 @@ int pvhdr_read(struct device *dev, char *buf);
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_ea(struct dm_pool *mem, struct dm_list *eas,
+ uint64_t start, uint64_t size);
+void del_eas(struct dm_list *eas);
int add_mda(const struct format_type *fmt, struct dm_pool *mem, struct dm_list *mdas,
struct device *dev, uint64_t start, uint64_t size, unsigned ignored);
void del_mdas(struct dm_list *mdas);
diff --git a/lib/format_text/layout.h b/lib/format_text/layout.h
index 1a9856d..6bd3fe4 100644
--- a/lib/format_text/layout.h
+++ b/lib/format_text/layout.h
@@ -23,6 +23,15 @@
/* disk_locn and data_area_list are defined in format-text.h */
+#define PV_HEADER_EXTENSION_VSN 1
+
+struct pv_header_extension {
+ uint32_t version;
+ uint32_t flags;
+ /* NULL-terminated list of embedding areas */
+ struct disk_locn embedding_area_xl[0];
+} __attribute__ ((packed));
+
/* Fields with the suffix _xl should be xlate'd wherever they appear */
/* On disk */
struct pv_header {
@@ -34,6 +43,9 @@ struct pv_header {
/* NULL-terminated list of data areas followed by */
/* NULL-terminated list of metadata area headers */
struct disk_locn disk_areas_xl[0]; /* Two lists */
+
+ /* PV header extension */
+ struct pv_header_extension ext;
} __attribute__ ((packed));
/*
diff --git a/lib/format_text/text_label.c b/lib/format_text/text_label.c
index 9d50334..be28f11 100644
--- a/lib/format_text/text_label.c
+++ b/lib/format_text/text_label.c
@@ -196,6 +196,17 @@ void del_das(struct dm_list *das)
}
}
+int add_ea(struct dm_pool *mem, struct dm_list *eas,
+ uint64_t start, uint64_t size)
+{
+ return add_da(mem, eas, start, size);
+}
+
+void del_eas(struct dm_list *eas)
+{
+ del_das(eas);
+}
+
/* FIXME: refactor this function with other mda constructor code */
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)
diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index 5c8a6df..6624a40 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -107,6 +107,7 @@
#define FMT_RESIZE_PV 0x00000080U /* Supports pvresize? */
#define FMT_UNLIMITED_STRIPESIZE 0x00000100U /* Unlimited stripe size? */
#define FMT_RESTRICTED_READAHEAD 0x00000200U /* Readahead restricted to 2-120? */
+#define FMT_EAS 0x000000400U /* Supports embedding areas? */
/* Mirror conversion type flags */
#define MIRROR_BY_SEG 0x00000001U /* segment-by-segment mirror */
diff --git a/lib/metadata/pv.h b/lib/metadata/pv.h
index b80472a..69d4868 100644
--- a/lib/metadata/pv.h
+++ b/lib/metadata/pv.h
@@ -43,6 +43,10 @@ struct physical_volume {
uint64_t status;
uint64_t size;
+ /* embedding area */
+ uint64_t ea_start;
+ uint64_t ea_size;
+
/* physical extents */
uint32_t pe_size;
uint64_t pe_start;
11 years, 2 months