Signed-off-by: Hu Tao <hutao(a)cn.fujitsu.com>
---
resize/resize.ml | 84 +++++++++++++++++++++++++++++++++++++++++++++++++-------
1 file changed, 74 insertions(+), 10 deletions(-)
diff --git a/resize/resize.ml b/resize/resize.ml
index cc76aa0..fc622ba 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,29 @@ 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
+ (* the start of logical partitions is aligned *)
+ | 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 +897,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) ->
@@ -1031,6 +1072,7 @@ read the man page virt-resize(1).
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. *)
@@ -1046,6 +1088,7 @@ read the man page virt-resize(1).
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. *)
@@ -1056,7 +1099,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
)
@@ -1100,6 +1145,17 @@ 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
+ | _ -> total +^ 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
+
let mbr_part_type x =
match parttype, x.p_part.G.part_num <= 4_l, x.p_type with
(* for GPT, all partitions are regarded as Primary Partition. *)
@@ -1115,6 +1171,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
@@ -1140,18 +1201,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
@@ -1175,6 +1230,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 (
@@ -1227,6 +1283,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) ->
@@ -1289,6 +1352,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