resize: Add --alignment flag to allow partition alignment to be picked.
authorRichard W.M. Jones <rjones@redhat.com>
Thu, 20 Oct 2011 15:49:15 +0000 (16:49 +0100)
committerRichard W.M. Jones <rjones@redhat.com>
Thu, 20 Oct 2011 15:49:15 +0000 (16:49 +0100)
resize/resize.ml
resize/virt-resize.pod

index 295d121..aed0e43 100644 (file)
@@ -28,7 +28,7 @@ let min_extra_partition = 10L *^ 1024L *^ 1024L
 (* Command line argument parsing. *)
 let prog = Filename.basename Sys.executable_name
 
 (* Command line argument parsing. *)
 let prog = Filename.basename Sys.executable_name
 
-let infile, outfile, copy_boot_loader, debug, deletes, dryrun,
+let infile, outfile, alignment, copy_boot_loader, debug, deletes, dryrun,
   expand, expand_content, extra_partition, format, ignores,
   lv_expands, machine_readable, ntfsresize_force, output_format,
   quiet, resizes, resizes_force, shrink =
   expand, expand_content, extra_partition, format, ignores,
   lv_expands, machine_readable, ntfsresize_force, output_format,
   quiet, resizes, resizes_force, shrink =
@@ -42,6 +42,7 @@ let infile, outfile, copy_boot_loader, debug, deletes, dryrun,
 
   let add xs s = xs := s :: !xs in
 
 
   let add xs s = xs := s :: !xs in
 
+  let alignment = ref 128 in
   let copy_boot_loader = ref true in
   let debug = ref false in
   let deletes = ref [] in
   let copy_boot_loader = ref true in
   let debug = ref false in
   let deletes = ref [] in
@@ -71,6 +72,7 @@ let infile, outfile, copy_boot_loader, debug, deletes, dryrun,
   in
 
   let argspec = Arg.align [
   in
 
   let argspec = Arg.align [
+    "--alignment", Arg.Set_int alignment,   "sectors Set partition alignment (default: 128 sectors)";
     "--no-copy-boot-loader", Arg.Clear copy_boot_loader, " Don't copy boot loader";
     "-d",        Arg.Set debug,             " Enable debugging messages";
     "--debug",   Arg.Set debug,             " -\"-";
     "--no-copy-boot-loader", Arg.Clear copy_boot_loader, " Don't copy boot loader";
     "-d",        Arg.Set debug,             " Enable debugging messages";
     "--debug",   Arg.Set debug,             " -\"-";
@@ -118,6 +120,7 @@ read the man page virt-resize(1).
   );
 
   (* Dereference the rest of the args. *)
   );
 
   (* Dereference the rest of the args. *)
+  let alignment = !alignment in
   let copy_boot_loader = !copy_boot_loader in
   let deletes = List.rev !deletes in
   let dryrun = !dryrun in
   let copy_boot_loader = !copy_boot_loader in
   let deletes = List.rev !deletes in
   let dryrun = !dryrun in
@@ -135,6 +138,10 @@ read the man page virt-resize(1).
   let resizes_force = List.rev !resizes_force in
   let shrink = match !shrink with "" -> None | str -> Some str in
 
   let resizes_force = List.rev !resizes_force in
   let shrink = match !shrink with "" -> None | str -> Some str in
 
+  if alignment < 1 then
+    error "alignment cannot be < 1";
+  let alignment = Int64.of_int alignment in
+
   (* No arguments and machine-readable mode?  Print out some facts
    * about what this binary supports.  We only need to print out new
    * things added since this option, or things which depend on features
   (* No arguments and machine-readable mode?  Print out some facts
    * about what this binary supports.  We only need to print out new
    * things added since this option, or things which depend on features
@@ -145,6 +152,7 @@ read the man page virt-resize(1).
     printf "ntfsresize-force\n";
     printf "32bitok\n";
     printf "128-sector-alignment\n";
     printf "ntfsresize-force\n";
     printf "32bitok\n";
     printf "128-sector-alignment\n";
+    printf "alignment\n";
     let g = new G.guestfs () in
     g#add_drive_opts "/dev/null";
     g#launch ();
     let g = new G.guestfs () in
     g#add_drive_opts "/dev/null";
     g#launch ();
@@ -162,7 +170,7 @@ read the man page virt-resize(1).
     | _ ->
         error "usage is: %s [--options] indisk outdisk" prog in
 
     | _ ->
         error "usage is: %s [--options] indisk outdisk" prog in
 
-  infile, outfile, copy_boot_loader, debug, deletes, dryrun,
+  infile, outfile, alignment, copy_boot_loader, debug, deletes, dryrun,
   expand, expand_content, extra_partition, format, ignores,
   lv_expands, machine_readable, ntfsresize_force, output_format,
   quiet, resizes, resizes_force, shrink
   expand, expand_content, extra_partition, format, ignores,
   lv_expands, machine_readable, ntfsresize_force, output_format,
   quiet, resizes, resizes_force, shrink
@@ -570,7 +578,7 @@ let calculate_surplus () =
   let nr_partitions = List.length partitions in
   let overhead = (Int64.of_int sectsize) *^ (
     2L *^ 64L +^                                 (* GPT start and end *)
   let nr_partitions = List.length partitions in
   let overhead = (Int64.of_int sectsize) *^ (
     2L *^ 64L +^                                 (* GPT start and end *)
-    (128L *^ (Int64.of_int (nr_partitions + 1))) (* Maximum alignment *)
+    (alignment *^ (Int64.of_int (nr_partitions + 1))) (* Maximum alignment *)
   ) +^
   (Int64.of_int (max_bootloader - 64 * 512)) in  (* Bootloader *)
 
   ) +^
   (Int64.of_int (max_bootloader - 64 * 512)) in  (* Bootloader *)
 
@@ -809,6 +817,9 @@ let () =
 let partitions =
   let sectsize = Int64.of_int sectsize in
 
 let partitions =
   let sectsize = Int64.of_int sectsize in
 
+  (* Return 'i' rounded up to the next multiple of 'a'. *)
+  let roundup64 i a = let a = a -^ 1L in (i +^ a) &^ (~^ a) in
+
   let rec loop partnum start = function
     | p :: ps ->
       (match p.p_operation with
   let rec loop partnum start = function
     | p :: ps ->
       (match p.p_operation with
@@ -819,7 +830,7 @@ let partitions =
          let size = (p.p_part.G.part_size +^ sectsize -^ 1L) /^ sectsize in
          (* Start of next partition + alignment. *)
          let end_ = start +^ size in
          let size = (p.p_part.G.part_size +^ sectsize -^ 1L) /^ sectsize in
          (* Start of next partition + alignment. *)
          let end_ = start +^ size in
-         let next = (end_ +^ 127L) &^ (~^ 127L) in
+         let next = roundup64 end_ alignment in
 
          { p with p_target_start = start; p_target_end = end_ -^ 1L;
            p_target_partnum = partnum } :: loop (partnum+1) next ps
 
          { p with p_target_start = start; p_target_end = end_ -^ 1L;
            p_target_partnum = partnum } :: loop (partnum+1) next ps
@@ -829,7 +840,7 @@ let partitions =
          let size = (newsize +^ sectsize -^ 1L) /^ sectsize in
          (* Start of next partition + alignment. *)
          let next = start +^ size in
          let size = (newsize +^ sectsize -^ 1L) /^ sectsize in
          (* Start of next partition + alignment. *)
          let next = start +^ size in
-         let next = (next +^ 127L) &^ (~^ 127L) in
+         let next = roundup64 next alignment in
 
          { p with p_target_start = start; p_target_end = next -^ 1L;
            p_target_partnum = partnum } :: loop (partnum+1) next ps
 
          { p with p_target_start = start; p_target_end = next -^ 1L;
            p_target_partnum = partnum } :: loop (partnum+1) next ps
index 622d8b9..8ae4894 100644 (file)
@@ -246,6 +246,40 @@ C<dd if=/dev/zero of=outdisk bs=1M count=..>)
 
 Display help.
 
 
 Display help.
 
+=item B<--alignment N>
+
+Set the alignment of partitions to C<N> sectors.  The default in
+virt-resize E<lt> 1.13.19 was 64 sectors, and after that is 128
+sectors.
+
+Assuming 512 byte sector size inside the guest, here are some
+suitable values for this:
+
+=over 4
+
+=item I<--alignment 1> (512 bytes)
+
+The partitions would be packed together as closely as possible, but
+would be completely unaligned.  In some cases this can cause very poor
+performance.  See L<virt-alignment-scan(1)> for further details.
+
+=item I<--alignment 8> (4K)
+
+This would be the minimum acceptable alignment for reasonable
+performance on modern hosts.
+
+=item I<--alignment 128> (64K)
+
+This alignment provides good performance when the host is using high
+end network storage.
+
+=item I<--alignment 2048> (1M)
+
+This is the standard alignment used by all newly installed guests
+since around 2008.
+
+=back
+
 =item B<-d>
 
 =item B<--debug>
 =item B<-d>
 
 =item B<--debug>
@@ -545,12 +579,12 @@ I<--machine-readable> option and will return an error.
 
 =head2 "Partition 1 does not end on cylinder boundary."
 
 
 =head2 "Partition 1 does not end on cylinder boundary."
 
-Virt-resize aligns partitions to multiples of 64 sectors.  Usually
-this means the partitions will not be aligned to the ancient CHS
-geometry.  However CHS geometry is meaningless for disks manufactured
-since the early 1990s, and doubly so for virtual hard drives.
-Alignment of partitions to cylinders is not required by any modern
-operating system.
+Virt-resize aligns partitions to multiples of 128 sectors (see the
+I<--alignment> parameter).  Usually this means the partitions will not
+be aligned to the ancient CHS geometry.  However CHS geometry is
+meaningless for disks manufactured since the early 1990s, and doubly
+so for virtual hard drives.  Alignment of partitions to cylinders is
+not required by any modern operating system.
 
 =head2 RESIZING WINDOWS VIRTUAL MACHINES
 
 
 =head2 RESIZING WINDOWS VIRTUAL MACHINES
 
@@ -630,6 +664,7 @@ L<grub(8)>,
 L<grub-install(8)>,
 L<virt-rescue(1)>,
 L<virt-sparsify(1)>,
 L<grub-install(8)>,
 L<virt-rescue(1)>,
 L<virt-sparsify(1)>,
+L<virt-alignment-scan(1)>,
 L<http://libguestfs.org/>.
 
 =head1 AUTHOR
 L<http://libguestfs.org/>.
 
 =head1 AUTHOR