* [PATCHi v2 1/5] Update 'md_chunk_alignment' to use stripe-width to align PV data
2009-07-06 2:39 [PATCH v4 0/5] LVM2 topology support Mike Snitzer
@ 2009-07-06 2:39 ` Mike Snitzer
2009-07-06 10:47 ` Alasdair G Kergon
2009-07-06 2:39 ` [PATCH v4 2/5] cmdline: support for bytes and sectors Mike Snitzer
` (3 subsequent siblings)
4 siblings, 1 reply; 9+ messages in thread
From: Mike Snitzer @ 2009-07-06 2:39 UTC (permalink / raw)
To: lvm-devel
Use the MD device's stripe-width, instead of chunk_size, to align the
data blocks of a Physical Volume that is placed directly upon an MD
device.
Signed-off-by: Mike Snitzer <snitzer@redhat.com>
---
WHATS_NEW | 1
doc/example.conf | 2
lib/device/dev-md.c | 161 ++++++++++++++++++++++++++++++++++++++++--------
lib/device/device.h | 2
lib/metadata/metadata.c | 6 -
man/lvm.conf.5.in | 4 -
6 files changed, 145 insertions(+), 31 deletions(-)
Index: LVM2/lib/device/dev-md.c
===================================================================
--- LVM2.orig/lib/device/dev-md.c
+++ LVM2/lib/device/dev-md.c
@@ -125,62 +125,175 @@ out:
return ret;
}
-/*
- * Retrieve chunk size from md device using sysfs.
- */
-unsigned long dev_md_chunk_size(const char *sysfs_dir, struct device *dev)
+static FILE *md_sysfs_fopen(const char *sysfs_dir, struct device *dev,
+ const char *attribute)
{
- char path[PATH_MAX+1], buffer[64];
+ char path[PATH_MAX+1];
FILE *fp;
struct stat info;
- unsigned long chunk_size_bytes = 0UL;
if (MAJOR(dev->dev) != md_major())
- return 0;
+ return NULL;
if (!sysfs_dir || !*sysfs_dir)
- return_0;
+ return NULL;
- if (dm_snprintf(path, PATH_MAX, "%s/dev/block/%d:%d/md/chunk_size",
- sysfs_dir, MAJOR(dev->dev), MINOR(dev->dev)) < 0) {
- log_error("dm_snprintf md chunk_size failed");
- return 0;
+ if (dm_snprintf(path, PATH_MAX, "%s/dev/block/%d:%d/md/%s",
+ sysfs_dir, MAJOR(dev->dev), MINOR(dev->dev), attribute) < 0) {
+ log_error("dm_snprintf md %s failed", attribute);
+ return NULL;
}
/* old sysfs structure */
if (stat(path, &info) &&
- dm_snprintf(path, PATH_MAX, "%s/block/md%d/md/chunk_size",
- sysfs_dir, MINOR(dev->dev)) < 0) {
- log_error("dm_snprintf old md chunk size failed");
- return 0;
+ dm_snprintf(path, PATH_MAX, "%s/block/md%d/md/%s",
+ sysfs_dir, MINOR(dev->dev), attribute) < 0) {
+ log_error("dm_snprintf old md %s failed", attribute);
+ return NULL;
}
if (!(fp = fopen(path, "r"))) {
log_sys_error("fopen", path);
- return 0;
+ return NULL;
}
+ return fp;
+}
+
+/*
+ * Retrieve chunk size from md device using sysfs.
+ */
+static unsigned long dev_md_chunk_size(const char *sysfs_dir,
+ struct device *dev)
+{
+ char buffer[64];
+ FILE *fp;
+ const char *attribute = "chunk_size";
+ unsigned long chunk_size_bytes = 0UL;
+
+ if (!(fp = md_sysfs_fopen(sysfs_dir, dev, attribute)))
+ return 0;
+
if (!fgets(buffer, sizeof(buffer), fp)) {
- log_sys_error("fgets", path);
+ log_sys_error("fgets", attribute);
goto out;
}
if (sscanf(buffer, "%lu", &chunk_size_bytes) != 1) {
- log_error("sysfs file %s not in expected format: %s", path,
- buffer);
+ log_error("%s sysfs attr %s not in expected format: %s",
+ dev_name(dev), attribute, buffer);
goto out;
}
- log_very_verbose("Device %s md chunk size is %lu bytes.",
+ log_very_verbose("Device %s chunk size is %lu bytes.",
dev_name(dev), chunk_size_bytes);
out:
if (fclose(fp))
- log_sys_error("fclose", path);
+ log_sys_error("fclose", attribute);
return chunk_size_bytes >> SECTOR_SHIFT;
}
+/*
+ * Retrieve level from md device using sysfs.
+ */
+static int dev_md_level(const char *sysfs_dir, struct device *dev)
+{
+ char buffer[64];
+ FILE *fp;
+ const char *attribute = "level";
+ int level = -1;
+
+ if (!(fp = md_sysfs_fopen(sysfs_dir, dev, attribute)))
+ return -1;
+
+ if (!fgets(buffer, sizeof(buffer), fp)) {
+ log_sys_error("fgets", attribute);
+ goto out;
+ }
+
+ if (sscanf(buffer, "raid%d", &level) != 1) {
+ log_error("%s sysfs attr %s not in expected format: %s",
+ dev_name(dev), attribute, buffer);
+ goto out;
+ }
+
+ log_very_verbose("Device %s raid level is %d.",
+ dev_name(dev), level);
+
+out:
+ if (fclose(fp))
+ log_sys_error("fclose", attribute);
+
+ return level;
+}
+
+/*
+ * Retrieve raid_disks from md device using sysfs.
+ */
+static int dev_md_raid_disks(const char *sysfs_dir, struct device *dev)
+{
+ char buffer[64];
+ FILE *fp;
+ const char *attribute = "raid_disks";
+ int raid_disks = 0;
+
+ if (!(fp = md_sysfs_fopen(sysfs_dir, dev, attribute)))
+ return 0;
+
+ if (!fgets(buffer, sizeof(buffer), fp)) {
+ log_sys_error("fgets", attribute);
+ goto out;
+ }
+
+ if (sscanf(buffer, "%d", &raid_disks) != 1) {
+ log_error("%s sysfs attr %s not in expected format: %s",
+ dev_name(dev), attribute, buffer);
+ goto out;
+ }
+
+ log_very_verbose("Device %s raid_disks is %d.",
+ dev_name(dev), raid_disks);
+
+out:
+ if (fclose(fp))
+ log_sys_error("fclose", attribute);
+
+ return raid_disks;
+}
+
+/*
+ * Calculate stripe width of md device using its sysfs files.
+ */
+unsigned long dev_md_stripe_width(const char *sysfs_dir, struct device *dev)
+{
+ unsigned long chunk_size_sectors = 0UL;
+ unsigned long stripe_width_sectors = 0UL;
+ int level, raid_disks, data_disks;
+
+ chunk_size_sectors = dev_md_chunk_size(sysfs_dir, dev);
+ if (!chunk_size_sectors)
+ return 0;
+
+ level = dev_md_level(sysfs_dir, dev);
+ if (level < 0)
+ return 0;
+
+ raid_disks = dev_md_raid_disks(sysfs_dir, dev);
+ if (!raid_disks)
+ return 0;
+
+ data_disks = raid_disks - (level == 0 ? 0 : (level <= 5 ? 1 : 2));
+ stripe_width_sectors = chunk_size_sectors * data_disks;
+
+ log_very_verbose("Device %s stripe-width is %lu bytes.",
+ dev_name(dev),
+ stripe_width_sectors << SECTOR_SHIFT);
+
+ return stripe_width_sectors;
+}
+
#else
int dev_is_md(struct device *dev __attribute((unused)),
@@ -189,8 +302,8 @@ int dev_is_md(struct device *dev __attri
return 0;
}
-unsigned long dev_md_chunk_size(const char *sysfs_dir __attribute((unused)),
- struct device *dev __attribute((unused)))
+unsigned long dev_md_stripe_width(const char *sysfs_dir __attribute((unused)),
+ struct device *dev __attribute((unused)))
{
return 0UL;
}
Index: LVM2/lib/device/device.h
===================================================================
--- LVM2.orig/lib/device/device.h
+++ LVM2/lib/device/device.h
@@ -96,7 +96,7 @@ const char *dev_name_confirmed(struct de
/* Does device contain md superblock? If so, where? */
int dev_is_md(struct device *dev, uint64_t *sb);
int dev_is_swap(struct device *dev, uint64_t *signature);
-unsigned long dev_md_chunk_size(const char *sysfs_dir, struct device *dev);
+unsigned long dev_md_stripe_width(const char *sysfs_dir, struct device *dev);
int is_partitioned_dev(struct device *dev);
Index: LVM2/lib/metadata/metadata.c
===================================================================
--- LVM2.orig/lib/metadata/metadata.c
+++ LVM2/lib/metadata/metadata.c
@@ -81,13 +81,13 @@ unsigned long set_pe_align(struct physic
goto out;
/*
- * Align to chunk size of underlying md device if present
+ * Align to stripe-width of underlying md device if present
*/
if (find_config_tree_bool(pv->fmt->cmd, "devices/md_chunk_alignment",
DEFAULT_MD_CHUNK_ALIGNMENT))
pv->pe_align = MAX(pv->pe_align,
- dev_md_chunk_size(pv->fmt->cmd->sysfs_dir,
- pv->dev));
+ dev_md_stripe_width(pv->fmt->cmd->sysfs_dir,
+ pv->dev));
log_very_verbose("%s: Setting PE alignment to %lu sectors.",
dev_name(pv->dev), pv->pe_align);
Index: LVM2/man/lvm.conf.5.in
===================================================================
--- LVM2.orig/man/lvm.conf.5.in
+++ LVM2/man/lvm.conf.5.in
@@ -134,8 +134,8 @@ superblocks. This doesn't always work sa
has been reused without wiping the md superblocks first.
.IP
\fBmd_chunk_alignment\fP \(em If set to 1, and a Physical Volume is placed
-directly upon an md device, LVM2 will align its data blocks with the the
-chunk_size exposed in sysfs.
+directly upon an md device, LVM2 will align its data blocks with the
+md device's stripe-width.
.IP
\fBdata_alignment\fP \(em Default alignment (in KB) of start of data area
when creating a new Physical Volume using the \fBlvm2\fP format.
Index: LVM2/WHATS_NEW
===================================================================
--- LVM2.orig/WHATS_NEW
+++ LVM2/WHATS_NEW
@@ -1,5 +1,6 @@
Version 2.02.49 -
================================
+ Update 'md_chunk_alignment' to use stripe-width to align PV data area.
Update test/t-inconsistent-metadata.sh to match new vg_read interface.
Add lvmcache_init() to polldaemon initialization.
Convert tools to use new vg_read / vg_read_for_update.
Index: LVM2/doc/example.conf
===================================================================
--- LVM2.orig/doc/example.conf
+++ LVM2/doc/example.conf
@@ -94,7 +94,7 @@ devices {
md_component_detection = 1
# By default, if a PV is placed directly upon an md device, LVM2
- # will align its data blocks with the the chunk_size exposed in sysfs.
+ # will align its data blocks with the md device's stripe-width.
# 1 enables; 0 disables.
md_chunk_alignment = 1
^ permalink raw reply [flat|nested] 9+ messages in thread* [PATCHi v2 1/5] Update 'md_chunk_alignment' to use stripe-width to align PV data
2009-07-06 2:39 ` [PATCHi v2 1/5] Update 'md_chunk_alignment' to use stripe-width to align PV data Mike Snitzer
@ 2009-07-06 10:47 ` Alasdair G Kergon
2009-07-06 17:14 ` Mike Snitzer
0 siblings, 1 reply; 9+ messages in thread
From: Alasdair G Kergon @ 2009-07-06 10:47 UTC (permalink / raw)
To: lvm-devel
On Sun, Jul 05, 2009 at 10:39:46PM -0400, Mike Snitzer wrote:
> +static unsigned long dev_md_chunk_size(const char *sysfs_dir,
> + struct device *dev)
> + if (!(fp = md_sysfs_fopen(sysfs_dir, dev, attribute)))
> + return 0;
> - log_sys_error("fgets", path);
> + log_sys_error("fgets", attribute);
Please reinstate the variable contextual information in these messages.
(sysfs_dir, dev, md are all now missing - return 'path' to the caller
of the customised fopen, or create the path in a separate fn first
and pass it in?)
> +static int dev_md_level(const char *sysfs_dir, struct device *dev)
> +static int dev_md_raid_disks(const char *sysfs_dir, struct device *dev)
> +unsigned long dev_md_stripe_width(const char *sysfs_dir, struct device *dev)
Is there more code that could be shared between these functions?
> + data_disks = raid_disks - (level == 0 ? 0 : (level <= 5 ? 1 : 2));
Add a comment before that line explaining it.
Ack
Alasdair
^ permalink raw reply [flat|nested] 9+ messages in thread* Re: [PATCHi v2 1/5] Update 'md_chunk_alignment' to use stripe-width to align PV data
2009-07-06 10:47 ` Alasdair G Kergon
@ 2009-07-06 17:14 ` Mike Snitzer
0 siblings, 0 replies; 9+ messages in thread
From: Mike Snitzer @ 2009-07-06 17:14 UTC (permalink / raw)
To: lvm-devel
On Mon, Jul 06 2009 at 6:47am -0400,
Alasdair G Kergon <agk@redhat.com> wrote:
> On Sun, Jul 05, 2009 at 10:39:46PM -0400, Mike Snitzer wrote:
> > +static unsigned long dev_md_chunk_size(const char *sysfs_dir,
> > + struct device *dev)
>
> > + if (!(fp = md_sysfs_fopen(sysfs_dir, dev, attribute)))
> > + return 0;
>
> > - log_sys_error("fgets", path);
> > + log_sys_error("fgets", attribute);
>
> Please reinstate the variable contextual information in these messages.
> (sysfs_dir, dev, md are all now missing - return 'path' to the caller
> of the customised fopen, or create the path in a separate fn first
> and pass it in?)
Done.
> > +static int dev_md_level(const char *sysfs_dir, struct device *dev)
> > +static int dev_md_raid_disks(const char *sysfs_dir, struct device *dev)
> > +unsigned long dev_md_stripe_width(const char *sysfs_dir, struct device *dev)
>
> Is there more code that could be shared between these functions?
Yes, I ended up sharing a bit more.
> > + data_disks = raid_disks - (level == 0 ? 0 : (level <= 5 ? 1 : 2));
> Add a comment before that line explaining it.
Turns out the above logic completely mishandled raid1. I reworked the
above into a proper switch statement with comments.
> Ack
Thanks for the review,
Mike
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v4 2/5] cmdline: support for bytes and sectors
2009-07-06 2:39 [PATCH v4 0/5] LVM2 topology support Mike Snitzer
2009-07-06 2:39 ` [PATCHi v2 1/5] Update 'md_chunk_alignment' to use stripe-width to align PV data Mike Snitzer
@ 2009-07-06 2:39 ` Mike Snitzer
2009-07-06 11:01 ` Alasdair G Kergon
2009-07-06 2:39 ` [PATCH v4 3/5] Add --dataalignmentoffset to pvcreate to pad aligned data area Mike Snitzer
` (2 subsequent siblings)
4 siblings, 1 reply; 9+ messages in thread
From: Mike Snitzer @ 2009-07-06 2:39 UTC (permalink / raw)
To: lvm-devel
Allow commandline sizes to be specified in terms of bytes and sectors.
Update the man pages to document size units uniformly.
Signed-off-by: Mike Snitzer <snitzer@redhat.com>
---
WHATS_NEW | 2 ++
man/lvcreate.8.in | 6 +++---
man/lvextend.8.in | 4 ++--
man/lvreduce.8.in | 4 ++--
man/lvresize.8.in | 4 ++--
man/vgchange.8.in | 4 ++--
man/vgcreate.8.in | 4 ++--
tools/commands.h | 26 +++++++++++++-------------
tools/lvmcmdline.c | 20 ++++++++++++++------
9 files changed, 42 insertions(+), 32 deletions(-)
Index: LVM2/WHATS_NEW
===================================================================
--- LVM2.orig/WHATS_NEW
+++ LVM2/WHATS_NEW
@@ -1,5 +1,7 @@
Version 2.02.49 -
================================
+ Update the man pages to document size units uniformly.
+ Allow specifying commandline sizes in terms of bytes and sectors.
Update 'md_chunk_alignment' to use stripe-width to align PV data area.
Update test/t-inconsistent-metadata.sh to match new vg_read interface.
Add lvmcache_init() to polldaemon initialization.
Index: LVM2/man/lvcreate.8.in
===================================================================
--- LVM2.orig/man/lvcreate.8.in
+++ LVM2/man/lvcreate.8.in
@@ -9,7 +9,7 @@ lvcreate \- create a logical volume in a
[\-h|\-?|\-\-help]
[\-i|\-\-stripes Stripes [\-I|\-\-stripesize StripeSize]]
{\-l|\-\-extents LogicalExtentsNumber[%{VG|PVS|FREE}] |
- \-L|\-\-size LogicalVolumeSize[kKmMgGtT]}
+ \-L|\-\-size LogicalVolumeSize[bBsSkKmMgGtTpPeE]}
[\-M|\-\-persistent y|n] [\-\-minor minor]
[\-m|\-\-mirrors Mirrors [\-\-nosync] [\-\-mirrorlog {disk|core}] [\-\-corelog]
[\-R|\-\-regionsize MirrorLogRegionSize]]
@@ -23,7 +23,7 @@ VolumeGroupName [PhysicalVolumePath...]
.br
.B lvcreate
{\-l|\-\-extents LogicalExtentsNumber[%{VG|FREE}] |
- \-L|\-\-size LogicalVolumeSize[kKmMgGtT]}
+ \-L|\-\-size LogicalVolumeSize[bBsSkKmMgGtTpPeE]}
[\-c|\-\-chunksize ChunkSize]
\-n|\-\-name SnapshotLogicalVolumeName
{{\-s|\-\-snapshot}
@@ -76,7 +76,7 @@ free space in the Volume Group with the
of the remaining free space for the specified PhysicalVolume(s)
with the suffix %PVS,
.TP
-.I \-L, \-\-size LogicalVolumeSize[kKmMgGtTpPeE]
+.I \-L, \-\-size LogicalVolumeSize[bBsSkKmMgGtTpPeE]
Gives the size to allocate for the new logical volume.
A size suffix of K for kilobytes, M for megabytes,
G for gigabytes, T for terabytes, P for petabytes
Index: LVM2/man/lvextend.8.in
===================================================================
--- LVM2.orig/man/lvextend.8.in
+++ LVM2/man/lvextend.8.in
@@ -7,7 +7,7 @@ lvextend \- extend the size of a logical
[\-A|\-\-autobackup y|n] [\-d|\-\-debug] [\-h|\-?|\-\-help]
[\-i|\-\-stripes Stripes [\-I|\-\-stripesize StripeSize]]
{\-l|\-\-extents [+]LogicalExtentsNumber[%{VG|LV|PVS|FREE}] |
-\-L|\-\-size [+]LogicalVolumeSize[kKmMgGtT]}
+\-L|\-\-size [+]LogicalVolumeSize[bBsSkKmMgGtTpPeE]}
[\-t|\-\-test]
[\-v|\-\-verbose] LogicalVolumePath [PhysicalVolumePath...]
.SH DESCRIPTION
@@ -32,7 +32,7 @@ free space for the specified PhysicalVol
or as a percentage of the remaining free space in the Volume Group
with the suffix %FREE.
.TP
-.I \-L, \-\-size [+]LogicalVolumeSize[kKmMgGtTpPeE]
+.I \-L, \-\-size [+]LogicalVolumeSize[bBsSkKmMgGtTpPeE]
Extend or set the logical volume size in units of megabytes.
A size suffix of M for megabytes,
G for gigabytes, T for terabytes, P for petabytes
Index: LVM2/man/lvreduce.8.in
===================================================================
--- LVM2.orig/man/lvreduce.8.in
+++ LVM2/man/lvreduce.8.in
@@ -6,7 +6,7 @@ lvreduce \- reduce the size of a logical
[\-A|\-\-autobackup y|n] [\-d|\-\-debug] [\-f|\-\-force]
[\-h|\-?|\-\-help]
{\-l|\-\-extents [\-]LogicalExtentsNumber[%{VG|LV|FREE}] |
-\-L|\-\-size [\-]LogicalVolumeSize[kKmMgGtT]}
+\-L|\-\-size [\-]LogicalVolumeSize[bBsSkKmMgGtTpPeE]}
[\-t|\-\-test]
[\-v|\-\-verbose] LogicalVolume[Path]
.SH DESCRIPTION
@@ -46,7 +46,7 @@ in the Volume Group with the suffix %VG
size of the Logical Volume with the suffix %LV or as a percentage of the remaining
free space in the Volume Group with the suffix %FREE.
.TP
-.I \-L, \-\-size [\-]LogicalVolumeSize[kKmMgGtTpPeE]
+.I \-L, \-\-size [\-]LogicalVolumeSize[bBsSkKmMgGtTpPeE]
Reduce or set the logical volume size in units of megabyte by default.
A size suffix of k for kilobyte, m for megabyte,
g for gigabytes, t for terabytes, p for petabytes
Index: LVM2/man/lvresize.8.in
===================================================================
--- LVM2.orig/man/lvresize.8.in
+++ LVM2/man/lvresize.8.in
@@ -7,7 +7,7 @@ lvresize \- resize a logical volume
[\-A|\-\-autobackup y|n] [\-d|\-\-debug] [\-h|\-?|\-\-help]
[\-i|\-\-stripes Stripes [\-I|\-\-stripesize StripeSize]]
{\-l|\-\-extents [+]LogicalExtentsNumber[%{VG|LV|PVS|FREE}] |
-\-L|\-\-size [+]LogicalVolumeSize[kKmMgGtT]}
+\-L|\-\-size [+]LogicalVolumeSize[bBsSkKmMgGtTpPeE]}
[\-t|\-\-test]
[\-v|\-\-verbose] LogicalVolumePath [PhysicalVolumePath...]
.SH DESCRIPTION
@@ -36,7 +36,7 @@ the remaining free space of the Physical
suffix %PVS, or as a percentage of the remaining free space in the
Volume Group with the suffix %FREE.
.TP
-.I \-L, \-\-size [+|-]LogicalVolumeSize[kKmMgGtTpPeE]
+.I \-L, \-\-size [+|-]LogicalVolumeSize[bBsSkKmMgGtTpPeE]
Change or set the logical volume size in units of megabytes.
A size suffix of M for megabytes,
G for gigabytes, T for terabytes, P for petabytes
Index: LVM2/man/vgchange.8.in
===================================================================
--- LVM2.orig/man/vgchange.8.in
+++ LVM2/man/vgchange.8.in
@@ -24,7 +24,7 @@ vgchange \- change attributes of a volum
.IR MaxPhysicalVolumes ]
.RB [ \-P | \-\-partial]
.RB [ \-s | \-\-physicalextentsize
-.IR PhysicalExtentSize [ \fBkKmMgGtT\fR ]]
+.IR PhysicalExtentSize [ \fBbBsSkKmMgGtTpPeE\fR ]]
.RB [ \-\-refresh]
.RB [ -t | \-\-test]
.RB [ \-v | \-\-verbose]
@@ -108,7 +108,7 @@ for tool performance reasons, you should
some use of \fB--metadatacopies 0\fP
as described in \fBpvcreate(8)\fP.
.TP
-.BR \-s ", " \-\-physicalextentsize " " \fIPhysicalExtentSize\fR[\fBkKmMgGtT\fR]
+.BR \-s ", " \-\-physicalextentsize " " \fIPhysicalExtentSize\fR[\fBbBsSkKmMgGtTpPeE\fR]
Changes the physical extent size on physical volumes of this volume group.
A size suffix (k for kilobytes up to t for terabytes) is optional, megabytes
is the default if no suffix is present.
Index: LVM2/man/vgcreate.8.in
===================================================================
--- LVM2.orig/man/vgcreate.8.in
+++ LVM2/man/vgcreate.8.in
@@ -17,7 +17,7 @@ vgcreate \- create a volume group
.RB [ -p | \-\-maxphysicalvolumes
.IR MaxPhysicalVolumes ]
.RB [ \-s | \-\-physicalextentsize
-.IR PhysicalExtentSize [ \fBkKmMgGtT\fR ]]
+.IR PhysicalExtentSize [ \fBbBsSkKmMgGtTpPeE\fR ]]
.RB [ \-t | \-\-test ]
.RB [ \-v | \-\-verbose ]
.RB [ \-\-version ]
@@ -66,7 +66,7 @@ for tool performance reasons, you should
some use of \fB--metadatacopies 0\fP
as described in \fBpvcreate(8)\fP.
.TP
-.BR \-s ", " \-\-physicalextentsize " " \fIPhysicalExtentSize\fR[\fBkKmMgGtT\fR]
+.BR \-s ", " \-\-physicalextentsize " " \fIPhysicalExtentSize\fR[\fBbBsSkKmMgGtTpPeE\fR]
Sets the physical extent size on physical volumes of this volume group.
A size suffix (k for kilobytes up to t for terabytes) is optional, megabytes
is the default if no suffix is present.
Index: LVM2/tools/commands.h
===================================================================
--- LVM2.orig/tools/commands.h
+++ LVM2/tools/commands.h
@@ -19,7 +19,7 @@ xx(e2fsadm,
"e2fsadm "
"[-d|--debug] " "[-h|--help] " "[-n|--nofsck]" "\n"
"\t{[-l|--extents] [+|-]LogicalExtentsNumber |" "\n"
- "\t [-L|--size] [+|-]LogicalVolumeSize[kKmMgGtTpPeE]}" "\n"
+ "\t [-L|--size] [+|-]LogicalVolumeSize[bBsSkKmMgGtTpPeE]}" "\n"
"\t[-t|--test] " "\n"
"\t[-v|--verbose] " "\n"
"\t[--version] " "\n"
@@ -133,7 +133,7 @@ xx(lvcreate,
"\t[-h|-?|--help]\n"
"\t[-i|--stripes Stripes [-I|--stripesize StripeSize]]\n"
"\t{-l|--extents LogicalExtentsNumber |\n"
- "\t -L|--size LogicalVolumeSize[kKmMgGtTpPeE]}\n"
+ "\t -L|--size LogicalVolumeSize[bBsSkKmMgGtTpPeE]}\n"
"\t[-M|--persistent {y|n}] [--major major] [--minor minor]\n"
"\t[-m|--mirrors Mirrors [--nosync] [{--mirrorlog {disk|core}|--corelog}]]\n"
"\t[-n|--name LogicalVolumeName]\n"
@@ -159,7 +159,7 @@ xx(lvcreate,
"\t[-h|-?|--help]\n"
"\t[-i|--stripes Stripes [-I|--stripesize StripeSize]]\n"
"\t{-l|--extents LogicalExtentsNumber[%{VG|LV|PVS|FREE}] |\n"
- "\t -L|--size LogicalVolumeSize[kKmMgGtTpPeE]}\n"
+ "\t -L|--size LogicalVolumeSize[bBsSkKmMgGtTpPeE]}\n"
"\t[-M|--persistent {y|n}] [--major major] [--minor minor]\n"
"\t[-n|--name LogicalVolumeName]\n"
"\t[-p|--permission {r|rw}]\n"
@@ -228,7 +228,7 @@ xx(lvextend,
"\t[-h|--help]\n"
"\t[-i|--stripes Stripes [-I|--stripesize StripeSize]]\n"
"\t{-l|--extents [+]LogicalExtentsNumber[%{VG|PVS|FREE}] |\n"
- "\t -L|--size [+]LogicalVolumeSize[kKmMgGtTpPeE]}\n"
+ "\t -L|--size [+]LogicalVolumeSize[bBsSkKmMgGtTpPeE]}\n"
"\t[-m|--mirrors Mirrors]\n"
"\t[-n|--nofsck]\n"
"\t[-r|--resizefs]\n"
@@ -298,7 +298,7 @@ xx(lvreduce,
"\t[-f|--force]\n"
"\t[-h|--help]\n"
"\t{-l|--extents [-]LogicalExtentsNumber[%{VG|LV|FREE}] |\n"
- "\t -L|--size [-]LogicalVolumeSize[kKmMgGtTpPeE]}\n"
+ "\t -L|--size [-]LogicalVolumeSize[bBsSkKmMgGtTpPeE]}\n"
"\t[-n|--nofsck]\n"
"\t[-r|--resizefs]\n"
"\t[-t|--test]\n"
@@ -351,7 +351,7 @@ xx(lvresize,
"\t[-h|--help]\n"
"\t[-i|--stripes Stripes [-I|--stripesize StripeSize]]\n"
"\t{-l|--extents [+|-]LogicalExtentsNumber[%{VG|LV|PVS|FREE}] |\n"
- "\t -L|--size [+|-]LogicalVolumeSize[kKmMgGtTpPeE]}\n"
+ "\t -L|--size [+|-]LogicalVolumeSize[bBsSkKmMgGtTpPeE]}\n"
"\t[-n|--nofsck]\n"
"\t[-r|--resizefs]\n"
"\t[-t|--test]\n"
@@ -436,7 +436,7 @@ xx(pvresize,
"pvresize " "\n"
"\t[-d|--debug]" "\n"
"\t[-h|-?|--help] " "\n"
- "\t[--setphysicalvolumesize PhysicalVolumeSize[kKmMgGtTpPeE]" "\n"
+ "\t[--setphysicalvolumesize PhysicalVolumeSize[bBsSkKmMgGtTpPeE]" "\n"
"\t[-t|--test] " "\n"
"\t[-v|--verbose] " "\n"
"\t[--version] " "\n"
@@ -468,9 +468,9 @@ xx(pvcreate,
"\t[--labelsector sector] " "\n"
"\t[-M|--metadatatype 1|2]" "\n"
"\t[--metadatacopies #copies]" "\n"
- "\t[--metadatasize MetadataSize[kKmMgGtTpPeE]]" "\n"
- "\t[--dataalignment Alignment[kKmMgGtTpPeE]]" "\n"
- "\t[--setphysicalvolumesize PhysicalVolumeSize[kKmMgGtTpPeE]" "\n"
+ "\t[--metadatasize MetadataSize[bBsSkKmMgGtTpPeE]]" "\n"
+ "\t[--dataalignment Alignment[bBsSkKmMgGtTpPeE]]" "\n"
+ "\t[--setphysicalvolumesize PhysicalVolumeSize[bBsSkKmMgGtTpPeE]" "\n"
"\t[-t|--test] " "\n"
"\t[-u|--uuid uuid] " "\n"
"\t[-v|--verbose] " "\n"
@@ -683,7 +683,7 @@ xx(vgchange,
"\t -x|--resizeable {y|n} |" "\n"
"\t -l|--logicalvolume MaxLogicalVolumes |" "\n"
"\t -p|--maxphysicalvolumes MaxPhysicalVolumes |" "\n"
- "\t -s|--physicalextentsize PhysicalExtentSize[kKmMgGtTpPeE] |" "\n"
+ "\t -s|--physicalextentsize PhysicalExtentSize[bBsSkKmMgGtTpPeE] |" "\n"
"\t --addtag Tag |\n"
"\t --deltag Tag}\n"
"\t[VolumeGroupName...]\n",
@@ -713,7 +713,7 @@ xx(vgconvert,
"\t[--labelsector sector] " "\n"
"\t[-M|--metadatatype 1|2]" "\n"
"\t[--metadatacopies #copies]" "\n"
- "\t[--metadatasize MetadataSize[kKmMgGtTpPeE]]" "\n"
+ "\t[--metadatasize MetadataSize[bBsSkKmMgGtTpPeE]]" "\n"
"\t[-t|--test] " "\n"
"\t[-v|--verbose] " "\n"
"\t[--version] " "\n"
@@ -735,7 +735,7 @@ xx(vgcreate,
"\t[-l|--maxlogicalvolumes MaxLogicalVolumes]" "\n"
"\t[-M|--metadatatype 1|2] " "\n"
"\t[-p|--maxphysicalvolumes MaxPhysicalVolumes] " "\n"
- "\t[-s|--physicalextentsize PhysicalExtentSize[kKmMgGtTpPeE]] " "\n"
+ "\t[-s|--physicalextentsize PhysicalExtentSize[bBsSkKmMgGtTpPeE]] " "\n"
"\t[-t|--test] " "\n"
"\t[-v|--verbose]" "\n"
"\t[--version] " "\n"
Index: LVM2/tools/lvmcmdline.c
===================================================================
--- LVM2.orig/tools/lvmcmdline.c
+++ LVM2/tools/lvmcmdline.c
@@ -239,7 +239,7 @@ static int _size_arg(struct cmd_context
{
char *ptr;
int i;
- static const char *suffixes = "kmgtpe";
+ static const char *suffixes = "kmgtpebs";
char *val;
double v;
@@ -274,11 +274,19 @@ static int _size_arg(struct cmd_context
if (i < 0)
return 0;
-
- while (i-- > 0)
- v *= 1024;
-
- v *= 2;
+ else if (i == 7) {
+ /* sectors */
+ v = v;
+ } else if (i == 6) {
+ /* bytes */
+ if (v < 512)
+ return 0;
+ v /= 512;
+ } else {
+ while (i-- > 0)
+ v *= 1024;
+ v *= 2;
+ }
} else
v *= factor;
^ permalink raw reply [flat|nested] 9+ messages in thread* [PATCH v4 2/5] cmdline: support for bytes and sectors
2009-07-06 2:39 ` [PATCH v4 2/5] cmdline: support for bytes and sectors Mike Snitzer
@ 2009-07-06 11:01 ` Alasdair G Kergon
0 siblings, 0 replies; 9+ messages in thread
From: Alasdair G Kergon @ 2009-07-06 11:01 UTC (permalink / raw)
To: lvm-devel
On Sun, Jul 05, 2009 at 10:39:47PM -0400, Mike Snitzer wrote:
> Allow commandline sizes to be specified in terms of bytes and sectors.
> Update the man pages to document size units uniformly.
Does the addition of 'bytes' now permit invalid sizes to be specified anywhere
leading to rounding happening without warning messages?
If rounding occurs the user should be notified.
E.g. lvcreate has: log_print("Rounding size (%d extents) up to stripe boundary "
(Whether to round up or to round down may depend on the context - see lvresize,
for example.)
> @@ -274,11 +274,19 @@ static int _size_arg(struct cmd_context
>
> if (i < 0)
> return 0;
> -
> - while (i-- > 0)
> - v *= 1024;
> -
> - v *= 2;
> + else if (i == 7) {
else superfluous?
> + /* sectors */
> + v = v;
> + } else if (i == 6) {
> + /* bytes */
Warning messages needed here, I think.
> + if (v < 512)
> + return 0;
> + v /= 512;
> + } else {
Add comment like the others to indicate which cases this now covers
> + while (i-- > 0)
> + v *= 1024;
> + v *= 2;
> + }
> } else
> v *= factor;
Alasdair
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v4 3/5] Add --dataalignmentoffset to pvcreate to pad aligned data area
2009-07-06 2:39 [PATCH v4 0/5] LVM2 topology support Mike Snitzer
2009-07-06 2:39 ` [PATCHi v2 1/5] Update 'md_chunk_alignment' to use stripe-width to align PV data Mike Snitzer
2009-07-06 2:39 ` [PATCH v4 2/5] cmdline: support for bytes and sectors Mike Snitzer
@ 2009-07-06 2:39 ` Mike Snitzer
2009-07-06 2:39 ` [PATCH v4 4/5] Add devices/data_alignment_offset_detection to lvm.conf Mike Snitzer
2009-07-06 2:39 ` [PATCH v4 5/5] Add devices/data_alignment_detection " Mike Snitzer
4 siblings, 0 replies; 9+ messages in thread
From: Mike Snitzer @ 2009-07-06 2:39 UTC (permalink / raw)
To: lvm-devel
Implement pvcreate --dataalignmentoffset to pad the start of
the aligned data area.
When setting up the first mda, format-text.c:_mda_setup now sets the
pe_start to immediately follow the first mda (which ends at a pe_align
boundry). data_alignment_offset will be added to pe_start if
--dataalignmentoffset was used.
Testing included verifying 'pvcreate --metadatacopies 2' works
(2nd mda's location on disk isn't affected by data_alignment_offset).
- Worst case scenario is the PV's pe_count may be reduced by 1 depending
upon the size of the device.
Signed-off-by: Mike Snitzer <snitzer@redhat.com>
---
WHATS_NEW | 1 +
lib/format1/format1.c | 1 +
lib/format_pool/format_pool.c | 1 +
lib/format_text/archiver.c | 2 +-
lib/format_text/format-text.c | 16 ++++++++++++++--
lib/metadata/metadata-exported.h | 1 +
lib/metadata/metadata.c | 10 ++++++++--
lib/metadata/metadata.h | 1 +
man/pvcreate.8.in | 20 +++++++++++++++++---
tools/args.h | 1 +
tools/commands.h | 7 ++++---
tools/pvcreate.c | 23 +++++++++++++++++++++--
tools/vgconvert.c | 2 +-
13 files changed, 72 insertions(+), 14 deletions(-)
Index: LVM2/WHATS_NEW
===================================================================
--- LVM2.orig/WHATS_NEW
+++ LVM2/WHATS_NEW
@@ -1,5 +1,6 @@
Version 2.02.49 -
================================
+ Add --dataalignmentoffset to pvcreate to pad aligned data area.
Update the man pages to document size units uniformly.
Allow specifying commandline sizes in terms of bytes and sectors.
Update 'md_chunk_alignment' to use stripe-width to align PV data area.
Index: LVM2/lib/format1/format1.c
===================================================================
--- LVM2.orig/lib/format1/format1.c
+++ LVM2/lib/format1/format1.c
@@ -296,6 +296,7 @@ static int _format1_pv_setup(const struc
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)), struct dm_list *mdas __attribute((unused)),
struct physical_volume *pv, struct volume_group *vg __attribute((unused)))
Index: LVM2/lib/format_pool/format_pool.c
===================================================================
--- LVM2.orig/lib/format_pool/format_pool.c
+++ LVM2/lib/format_pool/format_pool.c
@@ -192,6 +192,7 @@ static int _pool_pv_setup(const struct f
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)),
struct dm_list *mdas __attribute((unused)),
Index: LVM2/lib/format_text/archiver.c
===================================================================
--- LVM2.orig/lib/format_text/archiver.c
+++ LVM2/lib/format_text/archiver.c
@@ -316,7 +316,7 @@ int backup_restore_vg(struct cmd_context
return 0;
}
if (!vg->fid->fmt->ops->
- pv_setup(vg->fid->fmt, UINT64_C(0), 0, 0, 0, 0UL,
+ pv_setup(vg->fid->fmt, UINT64_C(0), 0, 0, 0, 0, 0UL,
UINT64_C(0), &vg->fid->metadata_areas, pv, vg)) {
log_error("Format-specific setup for %s failed",
pv_dev_name(pv));
Index: LVM2/lib/format_text/format-text.c
===================================================================
--- LVM2.orig/lib/format_text/format-text.c
+++ LVM2/lib/format_text/format-text.c
@@ -1175,6 +1175,7 @@ static int _text_scan(const struct forma
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,
+ unsigned long data_alignment_offset,
int pvmetadatacopies,
uint64_t pvmetadatasize, struct dm_list *mdas,
struct physical_volume *pv,
@@ -1251,6 +1252,16 @@ static int _mda_setup(const struct forma
return 0;
}
+ if (!pe_start && !pe_end) {
+ /*
+ * Set PV's pe_start to immediately follow the
+ * first mda (which ends at a pe_align boundry)
+ */
+ pv->pe_start = (start1 + mda_size1) >> SECTOR_SHIFT;
+ if (data_alignment_offset)
+ pv->pe_start += data_alignment_offset;
+ }
+
if (pvmetadatacopies == 1)
return 1;
} else
@@ -1598,6 +1609,7 @@ static struct metadata_area_ops _metadat
static int _text_pv_setup(const struct format_type *fmt,
uint64_t pe_start, uint32_t extent_count,
uint32_t extent_size, unsigned long data_alignment,
+ unsigned long data_alignment_offset,
int pvmetadatacopies,
uint64_t pvmetadatasize, struct dm_list *mdas,
struct physical_volume *pv, struct volume_group *vg)
@@ -1707,8 +1719,8 @@ static int _text_pv_setup(const struct f
if (extent_count)
pe_end = pe_start + extent_count * extent_size - 1;
- if (!_mda_setup(fmt, pe_start, pe_end, pvmetadatacopies,
- pvmetadatasize, mdas, pv, vg))
+ if (!_mda_setup(fmt, pe_start, pe_end, data_alignment_offset,
+ pvmetadatacopies, pvmetadatasize, mdas, pv, vg))
return_0;
}
Index: LVM2/lib/metadata/metadata-exported.h
===================================================================
--- LVM2.orig/lib/metadata/metadata-exported.h
+++ LVM2/lib/metadata/metadata-exported.h
@@ -416,6 +416,7 @@ pv_t *pv_create(const struct cmd_context
struct id *id,
uint64_t size,
unsigned long data_alignment,
+ unsigned long data_alignment_offset,
uint64_t pe_start,
uint32_t existing_extent_count,
uint32_t existing_extent_size,
Index: LVM2/lib/metadata/metadata.c
===================================================================
--- LVM2.orig/lib/metadata/metadata.c
+++ LVM2/lib/metadata/metadata.c
@@ -48,6 +48,7 @@ static struct physical_volume *_pv_creat
struct device *dev,
struct id *id, uint64_t size,
unsigned long data_alignment,
+ unsigned long data_alignment_offset,
uint64_t pe_start,
uint32_t existing_extent_count,
uint32_t existing_extent_size,
@@ -157,7 +158,7 @@ int add_pv_to_vg(struct volume_group *vg
pv->pe_alloc_count = 0;
if (!fid->fmt->ops->pv_setup(fid->fmt, UINT64_C(0), 0,
- vg->extent_size, 0, 0UL, UINT64_C(0),
+ vg->extent_size, 0, 0, 0UL, UINT64_C(0),
&fid->metadata_areas, pv, vg)) {
log_error("Format-specific setup of physical volume '%s' "
"failed.", pv_name);
@@ -787,6 +788,7 @@ int vg_split_mdas(struct cmd_context *cm
* @id: PV UUID to use for initialization
* @size: size of the PV in sectors
* @data_alignment: requested alignment of data
+ * @data_alignment_offset: requested offset to aligned data
* @pe_start: physical extent start
* @existing_extent_count
* @existing_extent_size
@@ -805,13 +807,15 @@ pv_t *pv_create(const struct cmd_context
struct device *dev,
struct id *id, uint64_t size,
unsigned long data_alignment,
+ unsigned long data_alignment_offset,
uint64_t pe_start,
uint32_t existing_extent_count,
uint32_t existing_extent_size,
int pvmetadatacopies,
uint64_t pvmetadatasize, struct dm_list *mdas)
{
- return _pv_create(cmd->fmt, dev, id, size, data_alignment, pe_start,
+ return _pv_create(cmd->fmt, dev, id, size,
+ data_alignment, data_alignment_offset, pe_start,
existing_extent_count,
existing_extent_size,
pvmetadatacopies,
@@ -856,6 +860,7 @@ static struct physical_volume *_pv_creat
struct device *dev,
struct id *id, uint64_t size,
unsigned long data_alignment,
+ unsigned long data_alignment_offset,
uint64_t pe_start,
uint32_t existing_extent_count,
uint32_t existing_extent_size,
@@ -907,6 +912,7 @@ static struct physical_volume *_pv_creat
if (!fmt->ops->pv_setup(fmt, pe_start, existing_extent_count,
existing_extent_size, data_alignment,
+ data_alignment_offset,
pvmetadatacopies, pvmetadatasize, mdas,
pv, NULL)) {
log_error("%s: Format-specific setup of physical volume "
Index: LVM2/lib/metadata/metadata.h
===================================================================
--- LVM2.orig/lib/metadata/metadata.h
+++ LVM2/lib/metadata/metadata.h
@@ -213,6 +213,7 @@ struct format_handler {
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, struct dm_list * mdas,
struct physical_volume * pv, struct volume_group * vg);
Index: LVM2/man/pvcreate.8.in
===================================================================
--- LVM2.orig/man/pvcreate.8.in
+++ LVM2/man/pvcreate.8.in
@@ -14,6 +14,7 @@ pvcreate \- initialize a disk or partiti
.RB [ \-\-metadatacopies #copies ]
.RB [ \-\-metadatasize size ]
.RB [ \-\-dataalignment alignment ]
+.RB [ \-\-dataalignmentoffset offset ]
.RB [ \-\-restorefile file ]
.RB [ \-\-setphysicalvolumesize size ]
.RB [ \-u | \-\-uuid uuid ]
@@ -91,13 +92,18 @@ The approximate amount of space to be se
(The size you specify may get rounded.)
.TP
.BR \-\-dataalignment " alignment"
-Align the offset of the start of the data to a multiple of this number.
+Align the start of the data to a multiple of this number.
You should also specify an appropriate \fBPhysicalExtentSize\fP when creating
the Volume Group with \fBvgcreate\fP.
.sp
To see the location of the first Physical Extent of an existing Physical Volume
use \fBpvs -o +pe_start\fP . It will be a multiple of the requested
-\fBdata_alignment\fP.
+\fBalignment\fP. In addition it may be padded by \fBalignment_offset\fP from
+\fBdata_alignment_offset_detection\fP (if enabled in \fBlvm.conf\fP) or
+\fB--dataalignmentoffset\fP.
+.TP
+.BR \-\-dataalignmentoffset " alignment_offset"
+Pad the start of the data with this additional \fBalignment_offset\fP.
.TP
.BR \-\-metadatacopies " copies"
The number of metadata areas to set aside on each PV. Currently
@@ -128,13 +134,21 @@ in the source). Use with care.
.TP
.BR \-\-setphysicalvolumesize " size"
Overrides the automatically-detected size of the PV. Use with care.
-.SH Example
+.SH EXAMPLES
Initialize partition #4 on the third SCSI disk and the entire fifth
SCSI disk for later use by LVM:
.sp
.B pvcreate /dev/sdc4 /dev/sde
.sp
+If the 2nd SCSI disk is a 4KB sector drive that compensates for windows
+partitioning (sector 7 is the lowest aligned logical block, the 4KB
+sectors start at LBA -1, and consequently sector 63 is aligned on a 4KB
+boundary) manually account for this when initializing for use by LVM:
+.sp
+.B pvcreate --dataalignmentoffset 7S /dev/sdb
+.sp
.SH SEE ALSO
+.BR lvm.conf (5),
.BR lvm (8),
.BR vgcreate (8),
.BR vgextend (8),
Index: LVM2/tools/args.h
===================================================================
--- LVM2.orig/tools/args.h
+++ LVM2/tools/args.h
@@ -59,6 +59,7 @@ arg(nameprefixes_ARG, '\0', "nameprefixe
arg(unquoted_ARG, '\0', "unquoted", NULL, 0)
arg(rows_ARG, '\0', "rows", NULL, 0)
arg(dataalignment_ARG, '\0', "dataalignment", size_kb_arg, 0)
+arg(dataalignmentoffset_ARG, '\0', "dataalignmentoffset", size_kb_arg, 0)
arg(virtualoriginsize_ARG, '\0', "virtualoriginsize", size_mb_arg, 0)
arg(virtualsize_ARG, '\0', "virtualsize", size_mb_arg, 0)
Index: LVM2/tools/commands.h
===================================================================
--- LVM2.orig/tools/commands.h
+++ LVM2/tools/commands.h
@@ -470,6 +470,7 @@ xx(pvcreate,
"\t[--metadatacopies #copies]" "\n"
"\t[--metadatasize MetadataSize[bBsSkKmMgGtTpPeE]]" "\n"
"\t[--dataalignment Alignment[bBsSkKmMgGtTpPeE]]" "\n"
+ "\t[--dataalignmentoffset AlignmentOffset[bBsSkKmMgGtTpPeE]]" "\n"
"\t[--setphysicalvolumesize PhysicalVolumeSize[bBsSkKmMgGtTpPeE]" "\n"
"\t[-t|--test] " "\n"
"\t[-u|--uuid uuid] " "\n"
@@ -479,9 +480,9 @@ xx(pvcreate,
"\t[--version] " "\n"
"\tPhysicalVolume [PhysicalVolume...]\n",
- dataalignment_ARG, force_ARG, test_ARG, labelsector_ARG, metadatatype_ARG,
- metadatacopies_ARG, metadatasize_ARG, physicalvolumesize_ARG,
- restorefile_ARG, uuidstr_ARG, yes_ARG, zero_ARG)
+ dataalignment_ARG, dataalignmentoffset_ARG, force_ARG, test_ARG,
+ labelsector_ARG, metadatatype_ARG, metadatacopies_ARG, metadatasize_ARG,
+ physicalvolumesize_ARG, restorefile_ARG, uuidstr_ARG, yes_ARG, zero_ARG)
xx(pvdata,
"Display the on-disk metadata for physical volume(s)",
Index: LVM2/tools/pvcreate.c
===================================================================
--- LVM2.orig/tools/pvcreate.c
+++ LVM2/tools/pvcreate.c
@@ -20,6 +20,7 @@ struct pvcreate_params {
int zero;
uint64_t size;
uint64_t data_alignment;
+ uint64_t data_alignment_offset;
int pvmetadatacopies;
uint64_t pvmetadatasize;
int64_t labelsector;
@@ -203,8 +204,8 @@ static int pvcreate_single(struct cmd_co
dm_list_init(&mdas);
if (!(pv = pv_create(cmd, dev, pp->idp, pp->size,
- pp->data_alignment, pp->pe_start,
- pp->extent_count, pp->extent_size,
+ pp->data_alignment, pp->data_alignment_offset,
+ pp->pe_start, pp->extent_count, pp->extent_size,
pp->pvmetadatacopies,
pp->pvmetadatasize,&mdas))) {
log_error("Failed to setup physical volume \"%s\"", pv_name);
@@ -377,6 +378,24 @@ static int pvcreate_validate_params(stru
pp->data_alignment = 0;
}
+ if (arg_sign_value(cmd, dataalignmentoffset_ARG, 0) == SIGN_MINUS) {
+ log_error("Physical volume data alignment offset may not be negative");
+ return 0;
+ }
+ pp->data_alignment_offset = arg_uint64_value(cmd, dataalignmentoffset_ARG, UINT64_C(0));
+
+ if (pp->data_alignment_offset > ULONG_MAX) {
+ log_error("Physical volume data alignment offset is too big.");
+ return 0;
+ }
+
+ if (pp->data_alignment_offset && pp->pe_start) {
+ log_warn("WARNING: Ignoring data alignment offset %" PRIu64
+ " incompatible with --restorefile value (%"
+ PRIu64").", pp->data_alignment_offset, pp->pe_start);
+ pp->data_alignment_offset = 0;
+ }
+
if (arg_sign_value(cmd, metadatasize_ARG, 0) == SIGN_MINUS) {
log_error("Metadata size may not be negative");
return 0;
Index: LVM2/tools/vgconvert.c
===================================================================
--- LVM2.orig/tools/vgconvert.c
+++ LVM2/tools/vgconvert.c
@@ -123,7 +123,7 @@ static int vgconvert_single(struct cmd_c
dm_list_init(&mdas);
if (!(pv = pv_create(cmd, pv_dev(existing_pv),
- &existing_pv->id, size, 0,
+ &existing_pv->id, size, 0, 0,
pe_start, pv_pe_count(existing_pv),
pv_pe_size(existing_pv), pvmetadatacopies,
pvmetadatasize, &mdas))) {
^ permalink raw reply [flat|nested] 9+ messages in thread* [PATCH v4 4/5] Add devices/data_alignment_offset_detection to lvm.conf.
2009-07-06 2:39 [PATCH v4 0/5] LVM2 topology support Mike Snitzer
` (2 preceding siblings ...)
2009-07-06 2:39 ` [PATCH v4 3/5] Add --dataalignmentoffset to pvcreate to pad aligned data area Mike Snitzer
@ 2009-07-06 2:39 ` Mike Snitzer
2009-07-06 2:39 ` [PATCH v4 5/5] Add devices/data_alignment_detection " Mike Snitzer
4 siblings, 0 replies; 9+ messages in thread
From: Mike Snitzer @ 2009-07-06 2:39 UTC (permalink / raw)
To: lvm-devel
If the pvcreate --dataalignmentoffset option is not specified the start
of a PV's aligned data area will be padded with the associated
'alignment_offset' exposed in sysfs (unless
devices/data_alignment_offset_detection is disabled in lvm.conf).
Signed-off-by: Mike Snitzer <snitzer@redhat.com>
---
WHATS_NEW | 1
doc/example.conf | 9 ++++++
lib/config/defaults.h | 1
lib/device/device.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++
lib/device/device.h | 3 ++
lib/metadata/metadata.c | 8 +++++
man/lvm.conf.5.in | 9 +++++-
7 files changed, 101 insertions(+), 1 deletion(-)
Index: LVM2/WHATS_NEW
===================================================================
--- LVM2.orig/WHATS_NEW
+++ LVM2/WHATS_NEW
@@ -1,5 +1,6 @@
Version 2.02.49 -
================================
+ Add devices/data_alignment_offset_detection to lvm.conf.
Add --dataalignmentoffset to pvcreate to pad aligned data area.
Update the man pages to document size units uniformly.
Allow specifying commandline sizes in terms of bytes and sectors.
Index: LVM2/doc/example.conf
===================================================================
--- LVM2.orig/doc/example.conf
+++ LVM2/doc/example.conf
@@ -104,6 +104,15 @@ devices {
# Set to 0 for the default alignment of 64KB or page size, if larger.
data_alignment = 0
+ # By default, the start of a PV's aligned data area will be padded with
+ # the 'alignment_offset' exposed in sysfs. This offset is often 0 but
+ # may be non-zero; e.g.: certain 4KB sector drives that compensate for
+ # windows partitioning will have an alignment_offset of 3584 bytes
+ # (sector 7 is the lowest aligned logical block, the 4KB sectors start
+ # at LBA -1, and consequently sector 63 is aligned on a 4KB boundary).
+ # 1 enables; 0 disables.
+ data_alignment_offset_detection = 1
+
# If, while scanning the system for PVs, LVM2 encounters a device-mapper
# device that has its I/O suspended, it waits for it to become accessible.
# Set this to 1 to skip such devices. This should only be needed
Index: LVM2/lib/config/defaults.h
===================================================================
--- LVM2.orig/lib/config/defaults.h
+++ LVM2/lib/config/defaults.h
@@ -34,6 +34,7 @@
#define DEFAULT_MD_COMPONENT_DETECTION 1
#define DEFAULT_MD_CHUNK_ALIGNMENT 1
#define DEFAULT_IGNORE_SUSPENDED_DEVICES 1
+#define DEFAULT_DATA_ALIGNMENT_OFFSET_DETECTION 1
#define DEFAULT_LOCK_DIR "/var/lock/lvm"
#define DEFAULT_LOCKING_LIB "liblvm2clusterlock.so"
Index: LVM2/lib/device/device.c
===================================================================
--- LVM2.orig/lib/device/device.c
+++ LVM2/lib/device/device.c
@@ -278,3 +278,74 @@ int _get_partition_type(struct dev_mgr *
return 0;
}
#endif
+
+#ifdef linux
+
+static unsigned long _dev_topology_attribute(const char *attribute,
+ const char *sysfs_dir,
+ struct device *dev)
+{
+ char path[PATH_MAX+1], buffer[64];
+ FILE *fp;
+ struct stat info;
+ unsigned long result = 0UL;
+
+ if (!attribute || !*attribute)
+ return_0;
+
+ if (!sysfs_dir || !*sysfs_dir)
+ return_0;
+
+ if (dm_snprintf(path, PATH_MAX, "%s/dev/block/%d:%d/%s",
+ sysfs_dir, MAJOR(dev->dev), MINOR(dev->dev),
+ attribute) < 0) {
+ log_error("dm_snprintf %s failed", attribute);
+ return 0;
+ }
+
+ /* check if the desired sysfs attribute exists */
+ if (stat(path, &info) < 0)
+ return 0;
+
+ if (!(fp = fopen(path, "r"))) {
+ log_sys_error("fopen", path);
+ return 0;
+ }
+
+ if (!fgets(buffer, sizeof(buffer), fp)) {
+ log_sys_error("fgets", path);
+ goto out;
+ }
+
+ if (sscanf(buffer, "%lu", &result) != 1) {
+ log_error("sysfs file %s not in expected format: %s", path,
+ buffer);
+ goto out;
+ }
+
+ log_very_verbose("Device %s %s is %lu bytes.",
+ dev_name(dev), attribute, result);
+
+out:
+ if (fclose(fp))
+ log_sys_error("fclose", path);
+
+ return result >> SECTOR_SHIFT;
+}
+
+unsigned long dev_alignment_offset(const char *sysfs_dir,
+ struct device *dev)
+{
+ return _dev_topology_attribute("alignment_offset",
+ sysfs_dir, dev);
+}
+
+#else
+
+unsigned long dev_alignment_offset(const char *sysfs_dir,
+ struct device *dev)
+{
+ return 0UL;
+}
+
+#endif
Index: LVM2/lib/device/device.h
===================================================================
--- LVM2.orig/lib/device/device.h
+++ LVM2/lib/device/device.h
@@ -100,4 +100,7 @@ unsigned long dev_md_stripe_width(const
int is_partitioned_dev(struct device *dev);
+unsigned long dev_alignment_offset(const char *sysfs_dir,
+ struct device *dev);
+
#endif
Index: LVM2/lib/metadata/metadata.c
===================================================================
--- LVM2.orig/lib/metadata/metadata.c
+++ LVM2/lib/metadata/metadata.c
@@ -910,6 +910,14 @@ static struct physical_volume *_pv_creat
pv->fmt = fmt;
pv->vg_name = fmt->orphan_vg_name;
+ if (!pe_start && !data_alignment_offset &&
+ find_config_tree_bool(pv->fmt->cmd,
+ "devices/data_alignment_offset_detection",
+ DEFAULT_DATA_ALIGNMENT_OFFSET_DETECTION)) {
+ data_alignment_offset =
+ dev_alignment_offset(pv->fmt->cmd->sysfs_dir, pv->dev);
+ }
+
if (!fmt->ops->pv_setup(fmt, pe_start, existing_extent_count,
existing_extent_size, data_alignment,
data_alignment_offset,
Index: LVM2/man/lvm.conf.5.in
===================================================================
--- LVM2.orig/man/lvm.conf.5.in
+++ LVM2/man/lvm.conf.5.in
@@ -142,10 +142,17 @@ when creating a new Physical Volume usin
If a Physical Volume is placed directly upon an md device and
\fBmd_chunk_alignment\fP is enabled this parameter is ignored.
Set to 0 to use the default alignment of 64KB or the page size, if larger.
+.IP
+\fBdata_alignment_offset_detection\fP \(em If set to 1, and your kernel
+provides topology information in sysfs for the Physical Volume, the
+start of the aligned data area of the Physical Volume will be padded
+with the alignment_offset exposed in sysfs.
.sp
To see the location of the first Physical Extent of an existing Physical Volume
use \fBpvs -o +pe_start\fP . It will be a multiple of the requested
-\fBdata_alignment\fP.
+\fBdata_alignment\fP plus the alignment_offset from
+\fBdata_alignment_offset_detection\fP (if enabled) or the pvcreate
+commandline.
.TP
\fBlog\fP \(em Default log settings
.IP
^ permalink raw reply [flat|nested] 9+ messages in thread* [PATCH v4 5/5] Add devices/data_alignment_detection to lvm.conf.
2009-07-06 2:39 [PATCH v4 0/5] LVM2 topology support Mike Snitzer
` (3 preceding siblings ...)
2009-07-06 2:39 ` [PATCH v4 4/5] Add devices/data_alignment_offset_detection to lvm.conf Mike Snitzer
@ 2009-07-06 2:39 ` Mike Snitzer
4 siblings, 0 replies; 9+ messages in thread
From: Mike Snitzer @ 2009-07-06 2:39 UTC (permalink / raw)
To: lvm-devel
Adds 'data_alignment_detection' config option to the devices section of
lvm.conf. If your kernel provides topology information in sysfs (linux
>= 2.6.31) for the Physical Volume, the start of data area will be
aligned on a multiple of the ???minimum_io_size??? or ???optimal_io_size???
exposed in sysfs.
minimum_io_size is used if optimal_io_size is undefined (0). If both
md_chunk_alignment and data_alignment_detection are enabled the result
of data_alignment_detection is used.
Signed-off-by: Mike Snitzer <snitzer@redhat.com>
---
WHATS_NEW | 1
doc/example.conf | 12 ++++++-
lib/config/defaults.h | 1
lib/device/device.c | 75 ++++++++++++++++++++++++++++++++++++++++++++----
lib/device/device.h | 6 +++
lib/metadata/metadata.c | 19 ++++++++++++
man/lvm.conf.5.in | 13 +++++++-
7 files changed, 118 insertions(+), 9 deletions(-)
Index: LVM2/WHATS_NEW
===================================================================
--- LVM2.orig/WHATS_NEW
+++ LVM2/WHATS_NEW
@@ -1,5 +1,6 @@
Version 2.02.49 -
================================
+ Add devices/data_alignment_detection to lvm.conf.
Add devices/data_alignment_offset_detection to lvm.conf.
Add --dataalignmentoffset to pvcreate to pad aligned data area.
Update the man pages to document size units uniformly.
Index: LVM2/doc/example.conf
===================================================================
--- LVM2.orig/doc/example.conf
+++ LVM2/doc/example.conf
@@ -98,9 +98,17 @@ devices {
# 1 enables; 0 disables.
md_chunk_alignment = 1
+ # By default, the start of a PV's data area will be aligned with
+ # the 'minimum_io_size' or 'optimal_io_size' exposed in sysfs.
+ # minimum_io_size is used if optimal_io_size is undefined (0).
+ # If md_chunk_alignment is enabled, that detects the optimal_io_size.
+ # This setting takes precedence over md_chunk_alignment.
+ # 1 enables; 0 disables.
+ data_alignment_detection = 1
+
# Alignment (in KB) of start of data area when creating a new PV.
- # If a PV is placed directly upon an md device and md_chunk_alignment is
- # enabled this parameter is ignored.
+ # If a PV is placed directly upon an md device and md_chunk_alignment or
+ # data_alignment_detection is enabled this parameter is ignored.
# Set to 0 for the default alignment of 64KB or page size, if larger.
data_alignment = 0
Index: LVM2/lib/config/defaults.h
===================================================================
--- LVM2.orig/lib/config/defaults.h
+++ LVM2/lib/config/defaults.h
@@ -35,6 +35,7 @@
#define DEFAULT_MD_CHUNK_ALIGNMENT 1
#define DEFAULT_IGNORE_SUSPENDED_DEVICES 1
#define DEFAULT_DATA_ALIGNMENT_OFFSET_DETECTION 1
+#define DEFAULT_DATA_ALIGNMENT_DETECTION 1
#define DEFAULT_LOCK_DIR "/var/lock/lvm"
#define DEFAULT_LOCKING_LIB "liblvm2clusterlock.so"
Index: LVM2/lib/device/device.c
===================================================================
--- LVM2.orig/lib/device/device.c
+++ LVM2/lib/device/device.c
@@ -281,13 +281,36 @@ int _get_partition_type(struct dev_mgr *
#ifdef linux
+static int _primary_dev(const char *sysfs_dir,
+ struct device *dev, dev_t *result)
+{
+ char path[PATH_MAX+1];
+ struct stat info;
+
+ /* check if dev is a partition */
+ if (dm_snprintf(path, PATH_MAX, "%s/dev/block/%d:%d/partition",
+ sysfs_dir, MAJOR(dev->dev), MINOR(dev->dev)) < 0) {
+ log_error("dm_snprintf partition failed");
+ return 0;
+ }
+
+ if (stat(path, &info) < 0)
+ return 0;
+
+ *result = dev->dev -
+ (MINOR(dev->dev) % max_partitions(MAJOR(dev->dev)));
+ return 1;
+}
+
static unsigned long _dev_topology_attribute(const char *attribute,
const char *sysfs_dir,
struct device *dev)
{
+ const char *sysfs_fmt_str = "%s/dev/block/%d:%d/%s";
char path[PATH_MAX+1], buffer[64];
FILE *fp;
struct stat info;
+ dev_t primary;
unsigned long result = 0UL;
if (!attribute || !*attribute)
@@ -296,16 +319,32 @@ static unsigned long _dev_topology_attri
if (!sysfs_dir || !*sysfs_dir)
return_0;
- if (dm_snprintf(path, PATH_MAX, "%s/dev/block/%d:%d/%s",
- sysfs_dir, MAJOR(dev->dev), MINOR(dev->dev),
+ if (dm_snprintf(path, PATH_MAX, sysfs_fmt_str, sysfs_dir,
+ MAJOR(dev->dev), MINOR(dev->dev),
attribute) < 0) {
log_error("dm_snprintf %s failed", attribute);
return 0;
}
- /* check if the desired sysfs attribute exists */
- if (stat(path, &info) < 0)
- return 0;
+ /*
+ * check if the desired sysfs attribute exists
+ * - if not: either the kernel doesn't have topology support
+ * or the device could be a partition
+ */
+ if (stat(path, &info) < 0) {
+ if (!_primary_dev(sysfs_dir, dev, &primary))
+ return 0;
+
+ /* get attribute from partition's primary device */
+ if (dm_snprintf(path, PATH_MAX, sysfs_fmt_str, sysfs_dir,
+ MAJOR(primary), MINOR(primary),
+ attribute) < 0) {
+ log_error("pri dm_snprintf %s failed", attribute);
+ return 0;
+ }
+ if (stat(path, &info) < 0)
+ return 0;
+ }
if (!(fp = fopen(path, "r"))) {
log_sys_error("fopen", path);
@@ -340,6 +379,20 @@ unsigned long dev_alignment_offset(const
sysfs_dir, dev);
}
+unsigned long dev_minimum_io_size(const char *sysfs_dir,
+ struct device *dev)
+{
+ return _dev_topology_attribute("queue/minimum_io_size",
+ sysfs_dir, dev);
+}
+
+unsigned long dev_optimal_io_size(const char *sysfs_dir,
+ struct device *dev)
+{
+ return _dev_topology_attribute("queue/optimal_io_size",
+ sysfs_dir, dev);
+}
+
#else
unsigned long dev_alignment_offset(const char *sysfs_dir,
@@ -348,4 +401,16 @@ unsigned long dev_alignment_offset(const
return 0UL;
}
+unsigned long dev_minimum_io_size(const char *sysfs_dir,
+ struct device *dev)
+{
+ return 0UL;
+}
+
+unsigned long dev_optimal_io_size(const char *sysfs_dir,
+ struct device *dev)
+{
+ return 0UL;
+}
+
#endif
Index: LVM2/lib/device/device.h
===================================================================
--- LVM2.orig/lib/device/device.h
+++ LVM2/lib/device/device.h
@@ -103,4 +103,10 @@ int is_partitioned_dev(struct device *de
unsigned long dev_alignment_offset(const char *sysfs_dir,
struct device *dev);
+unsigned long dev_minimum_io_size(const char *sysfs_dir,
+ struct device *dev);
+
+unsigned long dev_optimal_io_size(const char *sysfs_dir,
+ struct device *dev);
+
#endif
Index: LVM2/lib/metadata/metadata.c
===================================================================
--- LVM2.orig/lib/metadata/metadata.c
+++ LVM2/lib/metadata/metadata.c
@@ -90,6 +90,25 @@ unsigned long set_pe_align(struct physic
dev_md_stripe_width(pv->fmt->cmd->sysfs_dir,
pv->dev));
+ /*
+ * Align to topology's minimum_io_size or optimal_io_size if present
+ * - minimum_io_size - the smallest request the device can perform
+ * w/o incurring a read-modify-write penalty (e.g. MD's chunk size)
+ * - optimal_io_size - the device's preferred unit of receiving I/O
+ * (e.g. MD's stripe width)
+ */
+ if (find_config_tree_bool(pv->fmt->cmd,
+ "devices/data_alignment_detection",
+ DEFAULT_DATA_ALIGNMENT_DETECTION)) {
+ pv->pe_align = MAX(pv->pe_align,
+ dev_minimum_io_size(pv->fmt->cmd->sysfs_dir,
+ pv->dev));
+
+ pv->pe_align = MAX(pv->pe_align,
+ dev_optimal_io_size(pv->fmt->cmd->sysfs_dir,
+ pv->dev));
+ }
+
log_very_verbose("%s: Setting PE alignment to %lu sectors.",
dev_name(pv->dev), pv->pe_align);
Index: LVM2/man/lvm.conf.5.in
===================================================================
--- LVM2.orig/man/lvm.conf.5.in
+++ LVM2/man/lvm.conf.5.in
@@ -137,11 +137,20 @@ has been reused without wiping the md su
directly upon an md device, LVM2 will align its data blocks with the
md device's stripe-width.
.IP
+\fBdata_alignment_detection\fP \(em If set to 1, and your kernel provides
+topology information in sysfs for the Physical Volume, the start of data
+area will be aligned on a multiple of the ???minimum_io_size??? or
+???optimal_io_size??? exposed in sysfs. minimum_io_size is used if
+optimal_io_size is undefined (0). If both \fBmd_chunk_alignment\fP and
+\fBdata_alignment_detection\fP are enabled the result of
+\fBdata_alignment_detection\fP is used.
+.IP
\fBdata_alignment\fP \(em Default alignment (in KB) of start of data area
when creating a new Physical Volume using the \fBlvm2\fP format.
If a Physical Volume is placed directly upon an md device and
-\fBmd_chunk_alignment\fP is enabled this parameter is ignored.
-Set to 0 to use the default alignment of 64KB or the page size, if larger.
+\fBmd_chunk_alignment\fP or \fBdata_alignment_detection\fP is enabled
+this parameter is ignored. Set to 0 to use the default alignment of
+64KB or the page size, if larger.
.IP
\fBdata_alignment_offset_detection\fP \(em If set to 1, and your kernel
provides topology information in sysfs for the Physical Volume, the
^ permalink raw reply [flat|nested] 9+ messages in thread