[Libguestfs] [PATCH v3 7/7] resize: add support to resize logical partitions

Hu Tao hutao at cn.fujitsu.com
Mon Sep 22 07:47:40 UTC 2014


Signed-off-by: Hu Tao <hutao at cn.fujitsu.com>
---
 resize/resize.ml | 82 +++++++++++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 72 insertions(+), 10 deletions(-)

diff --git a/resize/resize.ml b/resize/resize.ml
index 3f804a0..ea0be9e 100644
--- a/resize/resize.ml
+++ b/resize/resize.ml
@@ -596,6 +596,8 @@ read the man page virt-resize(1).
     let hash = Hashtbl.create 13 in
     List.iter (fun ({ p_name = name } as p) -> Hashtbl.add hash name p)
       partitions;
+    List.iter (fun ({ p_name = name } as p) -> Hashtbl.add hash name p)
+      logical_partitions;
     fun ~option name ->
       let name =
         if String.length name < 5 || String.sub name 0 5 <> "/dev/" then
@@ -719,8 +721,10 @@ read the man page virt-resize(1).
     (* We need some overhead for partitioning. *)
     let overhead =
       let maxl64 = List.fold_left max 0L in
+      let alignment = if alignment = 1L then 2L else alignment in
 
       let nr_partitions = List.length partitions in
+      let nr_partitions = nr_partitions + List.length logical_partitions in
 
       let gpt_start_sects = 64L in
       let gpt_end_sects = gpt_start_sects in
@@ -748,12 +752,25 @@ read the man page virt-resize(1).
     let required = List.fold_left (
       fun total p ->
         let newsize =
+          (* don't count extended partition but logical partitions below,
+           * because we may extend and resize logical partitions at
+           * the same time. *)
+          if p.p_type = ContentExtendedPartition then 0L else
+            match p.p_operation with
+            | OpCopy | OpIgnore -> p.p_part.G.part_size
+            | OpDelete -> 0L
+            | OpResize newsize -> newsize in
+        total +^ newsize
+    ) 0L partitions in
+    let required = required +^ List.fold_left (
+      fun total p ->
+        let newsize =
           match p.p_operation with
           | OpCopy | OpIgnore -> p.p_part.G.part_size
           | OpDelete -> 0L
           | OpResize newsize -> newsize in
         total +^ newsize
-    ) 0L partitions in
+    ) 0L logical_partitions in
 
     let surplus = outsize -^ (required +^ overhead) in
 
@@ -799,6 +816,28 @@ read the man page virt-resize(1).
     )
   );
 
+  (* handle resizing of logical partitions *)
+  List.iter (
+    fun p ->
+      if p.p_type = ContentExtendedPartition then (
+        let alignment = if alignment = 1L then 2L else alignment in
+        let size = roundup64 p.p_part.G.part_size sectsize in
+        let logical_sizes = List.fold_left (
+          fun total p ->
+            match p.p_operation with
+              | OpDelete -> total +^ 0L
+              | OpCopy | OpIgnore -> total +^ (roundup64 p.p_part.G.part_size (alignment *^ sectsize))
+              | OpResize newsize -> total +^ (roundup64 newsize (alignment *^ sectsize))
+          ) 0L logical_partitions in
+        (* the first logical partition is aligned *)
+        let logical_sizes = logical_sizes +^ alignment *^ sectsize in
+        if logical_sizes > size then
+          p.p_operation <- OpResize logical_sizes
+        (* don't touch the extended partition if logical sizes less
+         * then the original size *)
+      )
+  ) partitions;
+
   (* Calculate the final surplus.
    * At this point, this number must be >= 0.
    *)
@@ -857,6 +896,7 @@ read the man page virt-resize(1).
         wrap ~indent:4 (text ^ "\n\n") in
 
     List.iter print_summary partitions;
+    List.iter print_summary logical_partitions;
 
     List.iter (
       fun ({ lv_name = name } as lv) ->
@@ -1030,6 +1070,7 @@ read the man page virt-resize(1).
         | OpDelete -> calculate_target_partitions partnum start ~create_surplus ps (* skip p *)
 
         | OpIgnore | OpCopy ->          (* same size *)
+          let start = roundup64 start 2L in
           (* Size in sectors. *)
           let size = div_roundup64 p.p_part.G.part_size sectsize in
           (* Start of next partition + alignment. *)
@@ -1044,6 +1085,7 @@ read the man page virt-resize(1).
             p_target_partnum = partnum } :: calculate_target_partitions (partnum+1) next ~create_surplus ps
 
         | OpResize newsize ->           (* resized partition *)
+          let start = roundup64 start 2L in
           (* New size in sectors. *)
           let size = div_roundup64 newsize sectsize in
           (* Start of next partition + alignment. *)
@@ -1054,7 +1096,9 @@ read the man page virt-resize(1).
             eprintf "target partition %d: resize: newsize=%Ld start=%Ld end=%Ld\n%!"
               partnum newsize start (next -^ 1L);
 
-          { p with p_target_start = start; p_target_end = next -^ 1L;
+          (* there must be a at least 1-sector gap between logical
+           * partitions otherwise parted refused to add logical partition *)
+          { p with p_target_start = start; p_target_end = next -^ 2L;
             p_target_partnum = partnum } :: calculate_target_partitions (partnum+1) next ~create_surplus ps
         )
 
@@ -1096,6 +1140,16 @@ read the man page virt-resize(1).
 
     calculate_target_partitions 1 start ~create_surplus:true partitions in
 
+  let logical_partitions =
+    let start = List.fold_left (
+      fun total p ->
+        match p.p_type with
+          | ContentExtendedPartition -> total +^ p.p_target_start | _ -> 0L ) 0L partitions
+    in
+    (* align logical partitions, too *)
+    let start = roundup64 (start +^ 1L) alignment in
+    calculate_target_partitions 5 start ~create_surplus:false logical_partitions in
+
   (* For GPT, the part type simply becomes partition name, so we don't
    * handle the case specifically. *)
   let mbr_part_type x =
@@ -1109,6 +1163,11 @@ read the man page virt-resize(1).
       g#part_add "/dev/sdb" (mbr_part_type p) p.p_target_start p.p_target_end
   ) partitions;
 
+  List.iter (
+    fun p ->
+      g#part_add "/dev/sdb" "logical" p.p_target_start p.p_target_end
+  ) logical_partitions;
+
   (* Copy over the data. *)
   let copy_partition p =
       match p.p_operation with
@@ -1134,18 +1193,12 @@ read the man page virt-resize(1).
          | ContentUnknown | ContentPV _ | ContentFS _ ->
            g#copy_device_to_device ~size:copysize ~sparse source target
 
-         | ContentExtendedPartition ->
-           (* You can't just copy an extended partition by name, eg.
-            * source = "/dev/sda2", because the device name only covers
-            * the first 1K of the partition.  Instead, copy the
-            * source bytes from the parent disk (/dev/sda).
-            *)
-           let srcoffset = p.p_part.G.part_start in
-           g#copy_device_to_device ~srcoffset ~size:copysize "/dev/sda" target
+         | ContentExtendedPartition -> ()
         )
       | OpIgnore | OpDelete -> ()
   in
   List.iter copy_partition partitions;
+  List.iter copy_partition logical_partitions;
 
   (* Set bootable and MBR IDs.  Do this *after* copying over the data,
    * so that we can magically change the primary partition to an extended
@@ -1169,6 +1222,7 @@ read the man page virt-resize(1).
       | GPT, (No_ID|MBR_ID _) | MBR, (No_ID|GPT_Type _) -> ()
   in
   List.iter set_partition_bootable_and_id partitions;
+  List.iter set_partition_bootable_and_id logical_partitions;
 
   (* Fix the bootloader if we aligned the first partition. *)
   if align_first_partition_and_fix_bootloader then (
@@ -1221,6 +1275,13 @@ read the man page virt-resize(1).
         can_expand_content p.p_type
       | { p_operation = (OpCopy | OpIgnore | OpDelete) } -> false
     ) partitions
+    ||
+    List.exists (
+      function
+      | ({ p_operation = OpResize _ } as p) ->
+        can_expand_content p.p_type
+      | { p_operation = (OpCopy | OpIgnore | OpDelete) } -> false
+    ) logical_partitions
     || List.exists (
       function
       | ({ lv_operation = LVOpExpand } as lv) ->
@@ -1283,6 +1344,7 @@ read the man page virt-resize(1).
         -> ()
     in
     List.iter expand_partition_content partitions;
+    List.iter expand_partition_content logical_partitions;
 
     (* Expand logical volume content as required. *)
     List.iter (
-- 
1.9.3




More information about the Libguestfs mailing list