[Fai-commit] r6420 - in trunk: lib/setup-storage man

Michael Tautschnig mt at alioth.debian.org
Fri Apr 15 17:24:31 UTC 2011


Author: mt
Date: 2011-04-15 17:24:29 +0000 (Fri, 15 Apr 2011)
New Revision: 6420

Modified:
   trunk/lib/setup-storage/Parser.pm
   trunk/lib/setup-storage/Sizes.pm
   trunk/man/setup-storage.8
Log:
setup-storage: Added align-at option for user-defined alignment

Thanks: Patrick Cervicek for suggesting the user-specified alignment and Julien Blache for further work on this.
Thanks: Frank Doepper
Thanks: Mathieu Alorent

* setup-storage/{Parser.pm,Sizes.pm}: Align partition sizes to sectors or
  user-requested alignment on all disk labels, unless on DOS and preserving
  some partitions (stay with cylinder-alignment in those cases). Thanks
  Patrick Cervicek for suggesting the user-specified alignment. Thanks Julien
  Blache for further work on this.
* setup-storage.8: Document new align-at option.
* setup-storage/Sizes.pm: Take alignment into account for partition size
  computation (thanks Frank Doepper for bringing up this problem). Size of
  extended (partition) boot record is 2 sectors.
* setup-storage/Sizes.pm: Do not rely on bios_sectors_per_track information
  for computing the start location of first partition, always use 63 sectors
  gap. Thanks Mathieu Alorent for extensive testing.
* setup-storage/Sizes.pm: Removed redundant min_req_total_space tracking
  variable.


Modified: trunk/lib/setup-storage/Parser.pm
===================================================================
--- trunk/lib/setup-storage/Parser.pm	2011-04-15 15:37:03 UTC (rev 6419)
+++ trunk/lib/setup-storage/Parser.pm	2011-04-15 17:24:29 UTC (rev 6420)
@@ -573,6 +573,10 @@
             }
           }
         }
+        | /^align-at:(\d+[kKMGTPiB]*)/
+        {
+          $FAI::configs{$FAI::device}{align_at} = &FAI::convert_unit($1) * 1024.0 * 1024.0;
+        }
 
 
     option: /^preserve_always:((\d+(,\d+)*)|all)/

Modified: trunk/lib/setup-storage/Sizes.pm
===================================================================
--- trunk/lib/setup-storage/Sizes.pm	2011-04-15 15:37:03 UTC (rev 6419)
+++ trunk/lib/setup-storage/Sizes.pm	2011-04-15 17:24:29 UTC (rev 6420)
@@ -295,15 +295,14 @@
 # @param $config Disk config
 # @param $current_disk Current config of this disk
 # @param $next_start Start of the next partition
-# @param $min_req_total_space Minimum space required on disk
 # @param $max_avail The maximum size of a partition on this disk
 #
-# @return Updated values of ($next_start, $min_req_total_space)
+# @return Updated value of $next_start
 #
 ################################################################################
 sub do_partition_preserve {
 
-  my ($part_id, $config, $disk, $next_start, $min_req_total_space, $max_avail) = @_;
+  my ($part_id, $config, $disk, $next_start, $max_avail) = @_;
   # reference to the current disk config
   my $current_disk = $FAI::current_config{$disk};
 
@@ -335,9 +334,6 @@
   $part->{start_byte} = $curr_part->{begin_byte};
   $part->{end_byte} = $curr_part->{end_byte};
 
-  # and add it to the total disk space required by this config
-  $min_req_total_space += $part->{size}->{eff_size};
-
   # set the next start
   $next_start = $part->{end_byte} + 1;
 
@@ -354,10 +350,6 @@
           $current_disk->{bios_heads})) or 
       warn "Preserved partition $part_dev_name does not end at a cylinder boundary, parted may fail to restore the partition!\n";
 
-    # add one head of disk usage if this is a logical partition
-    $min_req_total_space += $current_disk->{bios_sectors_per_track} *
-      $current_disk->{sector_size} if ($part_id > 4);
-
     # make sure we don't change extended partitions to ordinary ones and
     # vice-versa
     ($part->{size}->{extended} == $curr_part->{is_extended})
@@ -376,7 +368,7 @@
       or die "Preserved partition $part_dev_name does not end at a sector boundary\n";
   }
 
-  return ($next_start, $min_req_total_space);
+  return $next_start;
 }
 
 ################################################################################
@@ -402,9 +394,6 @@
   ($part_id <= 4) or
     &FAI::internal_error("Extended partition wouldn't be a primary one");
 
-  my $epbr_size = $current_disk->{bios_sectors_per_track} *
-    $current_disk->{sector_size};
-
   # initialise the size and the start byte
   $part->{size}->{eff_size} = 0;
   $part->{start_byte} = -1;
@@ -413,10 +402,11 @@
     next if ($p < 5);
 
     $part->{start_byte} = $FAI::configs{$config}{partitions}{$p}{start_byte} -
-      $epbr_size if (-1 == $part->{start_byte});
+      (2 * $current_disk->{sector_size}) if (-1 == $part->{start_byte});
 
-    $part->{size}->{eff_size} += $FAI::configs{$config}{partitions}{$p}{size}{eff_size} +
-      $epbr_size;
+    $part->{size}->{eff_size} +=
+      $FAI::configs{$config}{partitions}{$p}{size}{eff_size} + (2 *
+        $current_disk->{sector_size});
 
     $part->{end_byte} = $FAI::configs{$config}{partitions}{$p}{end_byte};
   }
@@ -431,24 +421,45 @@
 #
 # @param $part_id Partition id within $config
 # @param $config Disk config
-# @param $current_disk Current config of this disk
+# @param $disk This disk
 # @param $next_start Start of the next partition
-# @param $min_req_total_space Minimum space required on disk
+# @param $block_size Requested alignment
 # @param $max_avail The maximum size of a partition on this disk
 # @param $worklist Reference to the remaining partitions
 #
-# @return Updated values of ($next_start, $min_req_total_space)
+# @return Updated value of $next_start and possibly updated value of $max_avail
 #
 ################################################################################
 sub do_partition_real {
 
-  my ($part_id, $config, $disk, $next_start, $min_req_total_space, $max_avail, $worklist) = @_;
+  my ($part_id, $config, $disk, $next_start, $block_size, $max_avail, $worklist) = @_;
   # reference to the current disk config
   my $current_disk = $FAI::current_config{$disk};
 
   # reference to the current partition
   my $part = (\%FAI::configs)->{$config}->{partitions}->{$part_id};
 
+  # compute the effective start location on the disk
+  # msdos specific offset for logical partitions
+  $next_start += 2 * $current_disk->{sector_size}
+    if (($FAI::configs{$config}{disklabel} eq "msdos") && ($part_id > 4));
+
+  # partition starts at where we currently are + requested alignment, or remains
+  # fixed in case of resized ntfs
+  if ($FAI::configs{$config}{partitions}{$part_id}{size}{resize} &&
+    ($current_disk->{partitions}->{$part_id}->{filesystem} eq "ntfs")) {
+    ($next_start <= $current_disk->{partitions}->{$part_id}->{begin_byte})
+      or die "Cannot preserve start byte of ntfs volume on partition $part_id, space before it is too small\n";
+    $next_start = $current_disk->{partitions}->{$part_id}->{begin_byte};
+  }
+
+  $FAI::configs{$config}{partitions}{$part_id}{start_byte} =
+    $next_start;
+
+  if (1 == $part_id) {
+    $max_avail = $current_disk->{size} - $next_start;
+    $max_avail = "${max_avail}B";
+  }
   my ($start, $end) = &FAI::make_range($part->{size}->{range}, $max_avail);
 
   # check, whether the size is fixed
@@ -478,11 +489,8 @@
 
         # logical partitions require the space for the EPBR to be left
         # out
-        if (($FAI::configs{$config}{disklabel} eq "msdos")
-          && ($p > 4)) {
-          $end_of_range -= $current_disk->{bios_sectors_per_track} *
-            $current_disk->{sector_size};
-        }
+        $end_of_range -= 2 * $current_disk->{sector_size}
+          if (($FAI::configs{$config}{disklabel} eq "msdos") && ($p > 4));
         last;
       } elsif ($FAI::configs{$config}{partitions}{$p}{size}{extended}) {
         next;
@@ -491,13 +499,11 @@
           $FAI::configs{$config}{partitions}{$p}{size}{range}, $max_avail);
 
         # logical partitions require the space for the EPBR to be left
-        # out
+        # out; in fact, even alignment constraints would have to be considered
         if (($FAI::configs{$config}{disklabel} eq "msdos")
-          && ($p > 4)) {
-          $min_size += $current_disk->{bios_sectors_per_track} *
-            $current_disk->{sector_size};
-          $max_size += $current_disk->{bios_sectors_per_track} *
-            $current_disk->{sector_size};
+          && ($p != $part_id) && ($p > 4)) {
+          $min_size += 2 * $current_disk->{sector_size};
+          $max_size += 2 * $current_disk->{sector_size};
         }
 
         $min_req_space += $min_size;
@@ -529,49 +535,10 @@
     $end   = $start;
   }
 
-  # now we compute the effective locations on the disk
-  # msdos specific offset for logical partitions
-  if (($FAI::configs{$config}{disklabel} eq "msdos")
-    && ($part_id > 4)) {
-
-    # add one head of disk usage if this is a logical partition
-    $min_req_total_space += $current_disk->{bios_sectors_per_track} *
-      $current_disk->{sector_size};
-
-    # move the start byte as well
-    $next_start += $current_disk->{bios_sectors_per_track} *
-      $current_disk->{sector_size};
-  }
-
-  # partition starts at where we currently are, or remains fixed in case of
-  # resized ntfs
-  if ($FAI::configs{$config}{partitions}{$part_id}{size}{resize} &&
-    ($current_disk->{partitions}->{$part_id}->{filesystem} eq "ntfs")) {
-    ($next_start <= $current_disk->{partitions}->{$part_id}->{begin_byte}) 
-      or die "Cannot preserve start byte of ntfs volume on partition $part_id, space before it is too small\n";
-    $next_start = $current_disk->{partitions}->{$part_id}->{begin_byte};
-  }
-  $FAI::configs{$config}{partitions}{$part_id}{start_byte} =
-    $next_start;
-
-  # the end may need some alignment, depending on the disk label
+  # partitions must end at the requested alignment
   my $end_byte = $next_start + $start - 1;
+  $end_byte -= ($end_byte + 1) % $block_size;
 
-  # on msdos, ensure that the partition ends at a cylinder boundary
-  if ($FAI::configs{$config}{disklabel} eq "msdos") {
-    $end_byte -=
-      ($end_byte + 1) % ($current_disk->{sector_size} *
-        $current_disk->{bios_sectors_per_track} *
-        $current_disk->{bios_heads});
-  }
-
-  # on gpt, ensure that the partition ends at a sector boundary
-  if ($FAI::configs{$config}{disklabel} eq "gpt" ||
-    $FAI::configs{$config}{disklabel} eq "gpt-bios") {
-    $end_byte -=
-      ($end_byte + 1) % $current_disk->{sector_size};
-  }
-
   # set $start and $end to the effective values
   $start = $end_byte - $next_start + 1;
   $end   = $start;
@@ -585,13 +552,10 @@
   # write the end byte to the configuration
   $part->{end_byte} = $end_byte;
 
-  # and add it to the total disk space required by this config
-  $min_req_total_space += $part->{size}->{eff_size};
-
   # set the next start
   $next_start = $part->{end_byte} + 1;
 
-  return ($next_start, $min_req_total_space);
+  return ($next_start, $max_avail);
 }
 
 ################################################################################
@@ -619,6 +583,23 @@
     # reference to the current disk config
     my $current_disk = $FAI::current_config{$disk};
 
+    # align to sector boundary by default
+    my $block_size = $current_disk->{sector_size};
+    # align to cylinder boundary for msdos disklabels if at least one of the
+    # partitions has to be preserved, for backward compatibility
+    if ($FAI::configs{$config}{disklabel} eq "msdos" &&
+      $FAI::configs{$config}{preserveparts} == 1) {
+      $block_size = $current_disk->{sector_size} *
+        $current_disk->{bios_sectors_per_track} *
+        $current_disk->{bios_heads};
+    }
+    # but user-specified alignment wins no matter what
+    defined ($FAI::configs{$config}{align_at}) and
+      $block_size = $FAI::configs{$config}{align_at};
+
+    (0 == $block_size % $current_disk->{sector_size}) or
+      die "Alignment must be set to a multiple of the underlying disk sector size\n";
+
     # at various points the following code highly depends on the desired disk label!
     # initialise variables
     # the id of the extended partition to be created, if required
@@ -636,22 +617,14 @@
       }
     }
 
-    # the space required on the disk
-    my $min_req_total_space = 0;
-
     # the start byte for the next partition
     my $next_start = 0;
 
     if ($FAI::configs{$config}{disklabel} eq "msdos") {
-      # on msdos disk labels, the first partitions starts at head #1
-      $next_start = $current_disk->{bios_sectors_per_track} *
-        $current_disk->{sector_size};
-      $min_req_total_space += $next_start;
+      # on msdos disk labels, the first partitions starts at head #1; well,
+      # enforce a 63-sectors-per-track layout
+      $next_start = 63 * $current_disk->{sector_size};
 
-      # the MBR requires space, too
-      $min_req_total_space += $current_disk->{bios_sectors_per_track} *
-        $current_disk->{sector_size};
-
     } elsif ($FAI::configs{$config}{disklabel} eq "gpt") {
       # on GPT-EFI disk labels the first 34 and last 33 sectors must be left alone
       $next_start = 34 * $current_disk->{sector_size};
@@ -659,32 +632,24 @@
       # modify the disk to claim the space for the second partition table
       $current_disk->{end_byte} -= 33 * $current_disk->{sector_size};
 
-      # the space required by the GPTs
-      $min_req_total_space += (34 + 33) * $current_disk->{sector_size};
-
     } elsif ($FAI::configs{$config}{disklabel} eq "gpt-bios") {
-      # on BIOS-style disk labels, the first partitions starts at head #1
-      $next_start = $current_disk->{bios_sectors_per_track} *
-        $current_disk->{sector_size};
-
       # the MBR requires space, too
-      $min_req_total_space += $current_disk->{bios_sectors_per_track} *
-        $current_disk->{sector_size};
+      $next_start = $current_disk->{sector_size};
+      # not too sure whether this is needed: standard GPT partition table space
+      $next_start += 33 * $current_disk->{sector_size};
 
       # apparently parted insists in having some space left at the end too
       # modify the disk to claim the space for the second partition table
       $current_disk->{end_byte} -= 33 * $current_disk->{sector_size};
 
-      # the space required by the GPTs
-      $min_req_total_space += 33 * $current_disk->{sector_size};
-
       # on gpt-bios we'll need an additional partition to store what doesn't fit
       # in the MBR; this partition must be at the beginning, but it should be
       # created at the very end such as not to invalidate indices of other
       # partitions
       $FAI::device = $config;
       &FAI::init_part_config("primary");
-      $FAI::configs{$config}{gpt_bios_part} = $FAI::partition_pointer->{number};
+      $FAI::configs{$config}{gpt_bios_part} =
+        (&FAI::phys_dev($FAI::partition_pointer_dev_name))[2];
       my ($s, $e) = &FAI::make_range("1-1", $current_disk->{size} . "B");
       # enter the range into the hash
       $FAI::partition_pointer->{size}->{range} = "$s-$s";
@@ -692,7 +657,6 @@
       $FAI::partition_pointer->{start_byte} = $next_start;
       $FAI::partition_pointer->{end_byte} = $next_start + $s - 1;
       $next_start += $s;
-      $min_req_total_space += $s;
       # set proper defaults
       $FAI::partition_pointer->{encrypt} = 0;
       $FAI::partition_pointer->{filesystem} = "-";
@@ -700,7 +664,7 @@
     }
 
     # the size of a 100% partition (the 100% available to the user)
-    my $max_avail = $current_disk->{size} - $min_req_total_space;
+    my $max_avail = $current_disk->{size} - $next_start;
     # expressed in bytes
     $max_avail = "${max_avail}B";
 
@@ -754,14 +718,14 @@
         shift @worklist;
       # the partition $part_id must be preserved
       } elsif ($part->{size}->{preserve}) {
-        ($next_start, $min_req_total_space) = &FAI::do_partition_preserve($part_id,
-          $config, $disk, $next_start, $min_req_total_space, $max_avail);
+        $next_start = &FAI::do_partition_preserve($part_id, $config, $disk,
+          $next_start, $max_avail);
 
         # partition done
         shift @worklist;
       } else {
-        ($next_start, $min_req_total_space) = &FAI::do_partition_real($part_id, 
-          $config, $disk, $next_start, $min_req_total_space, $max_avail, \@worklist);
+        ($next_start, $max_avail) = &FAI::do_partition_real($part_id, $config,
+          $disk, $next_start, $block_size, $max_avail, \@worklist);
 
         # msdos does not support partitions larger than 2TiB
         ($part->{size}->{eff_size} > (&FAI::convert_unit("2TiB") * 1024.0 *
@@ -773,8 +737,8 @@
     }
 
     # check, whether there is sufficient space on the disk
-    ($min_req_total_space > $current_disk->{size})
-      and die "Disk $disk is too small - at least $min_req_total_space bytes are required\n";
+    ($next_start > $current_disk->{end_byte} + 1)
+      and die "Disk $disk is too small - at least $next_start bytes are required\n";
 
     # make sure, extended partitions are only created on msdos disklabels
     ($FAI::configs{$config}{disklabel} ne "msdos" && $extended > -1)

Modified: trunk/man/setup-storage.8
===================================================================
--- trunk/man/setup-storage.8	2011-04-15 15:37:03 UTC (rev 6419)
+++ trunk/man/setup-storage.8	2011-04-15 17:24:29 UTC (rev 6420)
@@ -497,6 +497,20 @@
 .br
            */
 .br
+           | align-at:([[:digit:]]+[kKMGTPiB]*)
+.br
+           /* Align partitions at multiples of the given block size (unit
+.br
+           defaults to MiB, if omitted). Such an alignment, e.g., 4K, might be
+.br
+           important for proper performance of RAID arrays which use a logical
+.br
+           block size other than the sector size of the underlying disks. It
+.br
+           must, however, always be a multiple of this sector size.
+.br
+           */
+.br
 
 
 volume ::= <type> <mountpoint> <size> <filesystem> <mount_options> <fs_options>




More information about the Fai-commit mailing list