]> sourceware.org Git - lvm2.git/commitdiff
Add devices/data_alignment_offset_detection to lvm.conf.
authorMike Snitzer <snitzer@redhat.com>
Sat, 1 Aug 2009 17:07:36 +0000 (17:07 +0000)
committerMike Snitzer <snitzer@redhat.com>
Sat, 1 Aug 2009 17:07:36 +0000 (17:07 +0000)
If the pvcreate --dataalignmentoffset option is not specified the start
of a PV's aligned data area will be shifted by 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
doc/example.conf
lib/config/defaults.h
lib/device/device.c
lib/device/device.h
lib/format_text/format-text.c
lib/metadata/metadata.c
man/lvm.conf.5.in

index 35d69fc488c6f9f7effb3753c77e3dd647d0ef55..b9883347911f651a3a1ed366f08fe90ded4acd86 100644 (file)
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -4,6 +4,7 @@ Version 2.02.51 -
   Added configure --enable-udev_rules --enable-udev_sync.
   Added configure --with-udev-prefix --with-udevdir.
   Added udev dir to hold udev rules.
+  Add devices/data_alignment_offset_detection to lvm.conf.
   Add --dataalignmentoffset to pvcreate to shift start of aligned data area.
   Fix _mda_setup() to not check first mda's size before pe_align rounding.
   Document -I option of clvmd in the man page.
index 9791b167118be36b3679e458f0ccabfe91c2bd9b..f8528fdc74eb5b18de10b34b2d7e39dac215d135 100644 (file)
@@ -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 the PV's aligned data area will be shifted by
+    # 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 17e2b0e6a322dda08e2d374be9d08e5ba3f25c3c..227ec345c23ec64b17ceb3456fece17262a8ad1e 100644 (file)
@@ -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 3248dd65559e59413c39fc6a61855df1e27e1ca4..ebd81410f70bf6600cf95c5bbdc05d48e4834f77 100644 (file)
@@ -282,3 +282,74 @@ int _get_partition_type(struct dev_mgr *dm, struct device *d)
        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, (int)MAJOR(dev->dev), (int)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 b01682346b2e2435e79a4d28a3aa3f4e43edabff..32aee41524a3f6b2999b5606a5b2d79624ff2bd7 100644 (file)
@@ -100,4 +100,7 @@ unsigned long dev_md_stripe_width(const char *sysfs_dir, struct device *dev);
 
 int is_partitioned_dev(struct device *dev);
 
+unsigned long dev_alignment_offset(const char *sysfs_dir,
+                                  struct device *dev);
+
 #endif
index e581f5bcc63f36cb6ba98e312271c3cc3807f962..4ed8fe8cd773f454e18cb8899f03a3dd3bed8d43 100644 (file)
@@ -1772,7 +1772,11 @@ static int _text_pv_setup(const struct format_type *fmt,
                                 "%lu sectors (requested %lu sectors)",
                                 pv_dev_name(pv), pv->pe_align, data_alignment);
 
-               set_pe_align_offset(pv, data_alignment_offset);
+               if (set_pe_align_offset(pv, data_alignment_offset) != data_alignment_offset &&
+                   data_alignment_offset)
+                       log_warn("WARNING: %s: Overriding data alignment offset to "
+                                "%lu sectors (requested %lu sectors)",
+                                pv_dev_name(pv), pv->pe_align_offset, data_alignment_offset);
 
                if (pv->pe_align < pv->pe_align_offset) {
                        log_error("%s: pe_align (%lu sectors) must not be less "
index 327c08939ce27f46c6abdf719c3b85c9347cb764..d050b6c06736a41456718d476bf9e500f1992846 100644 (file)
@@ -105,6 +105,14 @@ unsigned long set_pe_align_offset(struct physical_volume *pv,
        if (!pv->dev)
                goto out;
 
+       if (find_config_tree_bool(pv->fmt->cmd,
+                                 "devices/data_alignment_offset_detection",
+                                 DEFAULT_DATA_ALIGNMENT_OFFSET_DETECTION))
+               pv->pe_align_offset =
+                       MAX(pv->pe_align_offset,
+                           dev_alignment_offset(pv->fmt->cmd->sysfs_dir,
+                                                pv->dev));
+
        log_very_verbose("%s: Setting PE alignment offset to %lu sectors.",
                         dev_name(pv->dev), pv->pe_align_offset);
 
index 3fbb162773c9984ee17065bcd51955c594e16a62..7b3ee2289bc4a79a3bef9195dc8c8b3f48e99f02 100644 (file)
@@ -142,10 +142,17 @@ 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.
+.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 shifted
+by 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
This page took 0.041688 seconds and 5 git commands to generate.