Signed-off-by: Hu Tao <hu...@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 _______________________________________________ Libguestfs mailing list Libguestfs@redhat.com https://www.redhat.com/mailman/listinfo/libguestfs