]> sourceware.org Git - lvm2.git/commitdiff
Add --dataalignmentoffset to pvcreate to shift start of aligned data area
authorsnitzer <snitzer>
Thu, 30 Jul 2009 17:45:28 +0000 (17:45 +0000)
committersnitzer <snitzer>
Thu, 30 Jul 2009 17:45:28 +0000 (17:45 +0000)
Adds pe_align_offset to 'struct physical_volume'; is initialized with
set_pe_align_offset().  After pe_start is established pe_align_offset is
added to it.

Signed-off-by: Mike Snitzer <snitzer@redhat.com>
13 files changed:
WHATS_NEW
lib/format1/format1.c
lib/format_pool/format_pool.c
lib/format_text/archiver.c
lib/format_text/format-text.c
lib/metadata/metadata-exported.h
lib/metadata/metadata.c
lib/metadata/metadata.h
man/pvcreate.8.in
tools/args.h
tools/commands.h
tools/pvcreate.c
tools/vgconvert.c

index b98cc0b5475c0c6783cb0a8fc7b60ec949d35559..659f986133cbd2464c1d2348b637f290f7fca98a 100644 (file)
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
 Version 2.02.51 - 
 ================================
+  Add --dataalignmentoffset to pvcreate to shift start of aligned data area.
   Preserve pe_start in .pv_setup and .pv_write if pe_start was supplied.
   Fix _mda_setup() to not check first mda's size before pe_align rounding.
   Formalize pe_start policy as split between .pv_setup and .pv_write.
index aa1483af1356660c338a34a39492ef00288bfc25..887906cf03dd4abfd43f96c417cd734e65693748 100644 (file)
@@ -297,6 +297,7 @@ static int _format1_pv_setup(const struct format_type *fmt,
                     uint64_t pe_start, uint32_t extent_count,
                     uint32_t extent_size,
                     unsigned long data_alignment __attribute((unused)),
+                    unsigned long data_alignment_offset __attribute((unused)),
                     int pvmetadatacopies __attribute((unused)),
                     uint64_t pvmetadatasize __attribute((unused)), struct dm_list *mdas __attribute((unused)),
                     struct physical_volume *pv, struct volume_group *vg __attribute((unused)))
index 6f7e4b4326b09612fec12571ecd1e5fea5d267b9..0d3f9184b4a285b800fad9d479a5b646e48cf2fe 100644 (file)
@@ -193,6 +193,7 @@ static int _pool_pv_setup(const struct format_type *fmt __attribute((unused)),
                          uint32_t extent_count __attribute((unused)),
                          uint32_t extent_size __attribute((unused)),
                          unsigned long data_alignment __attribute((unused)),
+                         unsigned long data_alignment_offset __attribute((unused)),
                          int pvmetadatacopies __attribute((unused)),
                          uint64_t pvmetadatasize __attribute((unused)),
                          struct dm_list *mdas __attribute((unused)),
index 6d744ed61da666c4e5d87205b8a298ed780d128e..a3fd4bd187afd9bec07e21a1ac411bcada2efc63 100644 (file)
@@ -320,7 +320,7 @@ int backup_restore_vg(struct cmd_context *cmd, struct volume_group *vg)
                        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 73132c80ba7b3cb43aeeb98f0da8557ebef77856..629e3ea90fda15211e719e2891d19167dc2be90b 100644 (file)
@@ -1180,7 +1180,7 @@ static int _mda_setup(const struct format_type *fmt,
                      struct physical_volume *pv,
                      struct volume_group *vg __attribute((unused)))
 {
-       uint64_t mda_adjustment, disk_size, alignment;
+       uint64_t mda_adjustment, disk_size, alignment, alignment_offset;
        uint64_t start1, mda_size1;     /* First area - start of disk */
        uint64_t start2, mda_size2;     /* Second area - end of disk */
        uint64_t wipe_size = 8 << SECTOR_SHIFT;
@@ -1190,6 +1190,7 @@ static int _mda_setup(const struct format_type *fmt,
                return 1;
 
        alignment = pv->pe_align << SECTOR_SHIFT;
+       alignment_offset = pv->pe_align_offset << SECTOR_SHIFT;
        disk_size = pv->size << SECTOR_SHIFT;
        pe_start <<= SECTOR_SHIFT;
        pe_end <<= SECTOR_SHIFT;
@@ -1223,6 +1224,15 @@ static int _mda_setup(const struct format_type *fmt,
                        mda_size1 -= (alignment - mda_adjustment);
        }
 
+       /* Add pe_align_offset if on pe_align boundary */
+       if (alignment_offset &&
+           (((start1 + mda_size1) % alignment) == 0)) {
+               mda_size1 += alignment_offset;
+               /* Revert if it's now too large */
+               if (start1 + mda_size1 > disk_size)
+                       mda_size1 -= alignment_offset;
+       }
+
        /* Ensure it's not going to be bigger than the disk! */
        if (start1 + mda_size1 > disk_size) {
                log_warn("WARNING: metadata area fills disk leaving no "
@@ -1379,6 +1389,8 @@ static int _text_pv_write(const struct format_type *fmt, struct physical_volume
         * sector after any metadata areas that begin before pe_start.
         */
        pv->pe_start = pv->pe_align;
+       if (pv->pe_align_offset)
+               pv->pe_start += pv->pe_align_offset;
        dm_list_iterate_items(mda, &info->mdas) {
                mdac = (struct mda_context *) mda->metadata_locn;
                if (pv->dev == mdac->area.dev &&
@@ -1389,11 +1401,26 @@ static int _text_pv_write(const struct format_type *fmt, struct physical_volume
                     (pv->pe_start << SECTOR_SHIFT))) {
                        pv->pe_start = (mdac->area.start + mdac->area.size)
                            >> SECTOR_SHIFT;
-                       adjustment = pv->pe_start % pv->pe_align;
+                       /* Adjust pe_start to: (N * pe_align) + pe_align_offset */
+                       adjustment =
+                               (pv->pe_start - pv->pe_align_offset) % pv->pe_align;
                        if (adjustment)
                                pv->pe_start += pv->pe_align - adjustment;
+                       log_very_verbose("%s: setting pe_start=%lu (orig_pe_start=%lu, "
+                                        "pe_align=%lu, pe_align_offset=%lu, "
+                                        "adjustment=%" PRIu64 ")",
+                                        pv_dev_name(pv), pv->pe_start,
+                                        (adjustment ?
+                                         pv->pe_start -= pv->pe_align - adjustment :
+                                         pv->pe_start),
+                                        pv->pe_align, pv->pe_align_offset, adjustment);
                }
        }
+       if (pv->pe_start >= pv->size) {
+               log_error("Data area is beyond end of device %s!",
+                         pv_dev_name(pv));
+               return 0;
+       }
 
  preserve_pe_start:
        if (!add_da
@@ -1617,6 +1644,7 @@ static struct metadata_area_ops _metadata_text_raw_ops = {
 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)
@@ -1723,6 +1751,15 @@ 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 (pv->pe_align < pv->pe_align_offset) {
+                       log_error("%s: pe_align (%lu sectors) must not be less "
+                                 "than pe_align_offset (%lu sectors)",
+                                 pv_dev_name(pv), pv->pe_align, pv->pe_align_offset);
+                       return 0;
+               }
+
        preserve_pe_start:
                if (extent_count)
                        pe_end = pe_start + extent_count * extent_size - 1;
index 74786ed240f76561ae67dfe04f536a1f02181559..d8d1a936c319423712ff65bd451beb15992d58f6 100644 (file)
@@ -183,6 +183,7 @@ struct physical_volume {
        uint32_t pe_count;
        uint32_t pe_alloc_count;
        unsigned long pe_align;
+       unsigned long pe_align_offset;
 
        struct dm_list segments;        /* Ordered pv_segments covering complete PV */
        struct dm_list tags;
@@ -346,6 +347,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;
@@ -424,6 +426,7 @@ struct physical_volume *pv_create(const struct cmd_context *cmd,
                      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 76af7668096d77c99726fd1fc2d82dbf0b5c6dc7..327c08939ce27f46c6abdf719c3b85c9347cb764 100644 (file)
@@ -93,6 +93,25 @@ out:
        return pv->pe_align;
 }
 
+unsigned long set_pe_align_offset(struct physical_volume *pv,
+                                 unsigned long data_alignment_offset)
+{
+       if (pv->pe_align_offset)
+               goto out;
+
+       if (data_alignment_offset)
+               pv->pe_align_offset = data_alignment_offset;
+
+       if (!pv->dev)
+               goto out;
+
+       log_very_verbose("%s: Setting PE alignment offset to %lu sectors.",
+                        dev_name(pv->dev), pv->pe_align_offset);
+
+out:
+       return pv->pe_align_offset;
+}
+
 /**
  * add_pv_to_vg - Add a physical volume to a volume group
  * @vg - volume group to add to
@@ -154,7 +173,7 @@ int add_pv_to_vg(struct volume_group *vg, const char *pv_name,
        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);
@@ -1191,6 +1210,7 @@ static void fill_default_pvcreate_params(struct pvcreate_params *pp)
        pp->zero = 0;
        pp->size = 0;
        pp->data_alignment = UINT64_C(0);
+       pp->data_alignment_offset = UINT64_C(0);
        pp->pvmetadatacopies = DEFAULT_PVMETADATACOPIES;
        pp->pvmetadatasize = DEFAULT_PVMETADATASIZE;
        pp->labelsector = DEFAULT_LABELSECTOR;
@@ -1249,8 +1269,8 @@ struct physical_volume * pvcreate_single(struct cmd_context *cmd, const char *pv
 
        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);
@@ -1319,6 +1339,7 @@ static struct physical_volume *_alloc_pv(struct dm_pool *mem, struct device *dev
        pv->pe_count = 0;
        pv->pe_alloc_count = 0;
        pv->pe_align = 0;
+       pv->pe_align_offset = 0;
        pv->fmt = NULL;
        pv->dev = dev;
 
@@ -1337,6 +1358,7 @@ static struct physical_volume *_alloc_pv(struct dm_pool *mem, struct device *dev
  * @dev: PV device to initialize
  * @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
@@ -1355,6 +1377,7 @@ struct physical_volume *pv_create(const struct cmd_context *cmd,
                                  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,
@@ -1407,6 +1430,7 @@ struct physical_volume *pv_create(const struct cmd_context *cmd,
 
        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 b9cdfeba25f8126a24e23561b4cf13805466e001..b04e7e21e133ef26050d30563d72b205fc1d88b0 100644 (file)
@@ -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);
@@ -267,6 +268,8 @@ struct format_handler {
  * Utility functions
  */
 unsigned long set_pe_align(struct physical_volume *pv, unsigned long data_alignment);
+unsigned long set_pe_align_offset(struct physical_volume *pv,
+                                 unsigned long data_alignment_offset);
 int vg_validate(struct volume_group *vg);
 
 int pv_write_orphan(struct cmd_context *cmd, struct physical_volume *pv);
index 4d488058d2d0ddd2efcf1f53c6575d793d7b70d0..2f214e337a1c1fedea06ab24a796fb9b46e06b35 100644 (file)
@@ -14,6 +14,7 @@ pvcreate \- initialize a disk or partition for use by LVM
 .RB [ \-\-metadatacopies #copies ]
 .RB [ \-\-metadatasize size ]
 .RB [ \-\-dataalignment alignment ]
+.RB [ \-\-dataalignmentoffset alignment_offset ]
 .RB [ \-\-restorefile file ]
 .RB [ \-\-setphysicalvolumesize size ]
 .RB [ \-u | \-\-uuid uuid ]
@@ -91,13 +92,18 @@ The approximate amount of space to be set aside for each metadata area.
 (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 shifted 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"
+Shift the start of the data area by 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 846b6c2efe49be8ac03813e0242f0c5e6916b2ef..f5db50e060ced0ffab0c7b429ce9a8704d7a596b 100644 (file)
@@ -59,6 +59,7 @@ arg(nameprefixes_ARG, '\0', "nameprefixes", NULL, 0)
 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 8559799dcfc77c6c7c4454ad2129ed9c0e7c4c8b..7f9feee41b1a67bce250798b444a5610b648a9c1 100644 (file)
@@ -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 8595339b3df6bf319410eeb9ab96ff8166f8816a..a22190d769923ae9e7d5040d38fe50b6524cf3a4 100644 (file)
@@ -96,7 +96,8 @@ static int pvcreate_validate_params(struct cmd_context *cmd,
        if (!(cmd->fmt->features & FMT_MDAS) &&
            (arg_count(cmd, metadatacopies_ARG) ||
             arg_count(cmd, metadatasize_ARG)   ||
-            arg_count(cmd, dataalignment_ARG))) {
+            arg_count(cmd, dataalignment_ARG)  ||
+            arg_count(cmd, dataalignmentoffset_ARG))) {
                log_error("Metadata and data alignment parameters only "
                          "apply to text format.");
                return 0;
@@ -140,6 +141,24 @@ static int pvcreate_validate_params(struct cmd_context *cmd,
                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 0996d95427649f59e87d26a3bf79b8f2373a17b1..a8b064d94e786e7d080f061df484e5b432dac78c 100644 (file)
@@ -123,7 +123,7 @@ static int vgconvert_single(struct cmd_context *cmd, const char *vg_name,
 
                dm_list_init(&mdas);
                if (!(pv = pv_create(cmd, pv_dev(existing_pv),
-                                    &existing_pv->id, size, 0,
+                                    &existing_pv->id, size, 0, 0,
                                     pe_start, pv_pe_count(existing_pv),
                                     pv_pe_size(existing_pv), pvmetadatacopies,
                                     pvmetadatasize, &mdas))) {
This page took 0.059659 seconds and 5 git commands to generate.