@@ -16,14 +16,15 @@ module D = Debug.Make (struct let name = __MODULE__ end)
1616
1717open D
1818
19- let run_qcow_tool qcow_tool ?input_fd ? output_fd ( _progress_cb : int -> unit )
20- (args : string list ) =
19+ let run_qcow_tool qcow_tool ?( replace_fds = [] ) ? input_fd ? output_fd
20+ (_progress_cb : int -> unit ) ( args : string list ) =
2121 info " Executing %s %s" qcow_tool (String. concat " " args) ;
2222 let open Forkhelpers in
2323 match
2424 with_logfile_fd " qcow-tool" (fun log_fd ->
2525 let pid =
26- safe_close_and_exec input_fd output_fd (Some log_fd) [] qcow_tool args
26+ safe_close_and_exec input_fd output_fd (Some log_fd) replace_fds
27+ qcow_tool args
2728 in
2829 let _, status = waitpid pid in
2930 if status <> Unix. WEXITED 0 then (
@@ -46,14 +47,56 @@ let update_task_progress (__context : Context.t) (x : int) =
4647
4748let receive (progress_cb : int -> unit ) (unix_fd : Unix.file_descr )
4849 (path : string ) =
49- let args = [path] in
50+ let args = [" stream_decode " ; path] in
5051 let qcow_tool = ! Xapi_globs. qcow_stream_tool in
5152 run_qcow_tool qcow_tool progress_cb args ~input_fd: unix_fd
5253
54+ let read_header qcow_path =
55+ let args = [" read_headers" ; qcow_path] in
56+ let qcow_tool = ! Xapi_globs. qcow_stream_tool in
57+ let pipe_reader, pipe_writer = Unix. pipe ~cloexec: true () in
58+
59+ let progress_cb _ = () in
60+ Xapi_stdext_pervasives.Pervasiveext. finally
61+ (fun () -> run_qcow_tool qcow_tool progress_cb args ~output_fd: pipe_writer)
62+ (fun () -> Unix. close pipe_writer) ;
63+ pipe_reader
64+
5365let send ?relative_to (progress_cb : int -> unit ) (unix_fd : Unix.file_descr )
5466 (path : string ) (_size : Int64.t ) =
67+ let qcow_of_device =
68+ Vhd_tool_wrapper. backing_file_of_device ~driver: " qcow2"
69+ in
70+ let qcow_path = qcow_of_device path in
71+
72+ (* If VDI is backed by QCOW, parse the header to determine nonzero clusters
73+ to avoid reading all of the raw disk *)
74+ let input_fd = Option. map read_header qcow_path in
75+
76+ (* Parse the header of the VDI we are diffing against as well *)
77+ let relative_to_qcow_path = Option. bind relative_to qcow_of_device in
78+ let diff_fd = Option. map read_header relative_to_qcow_path in
79+
80+ let unique_string = Uuidx. (to_string (make () )) in
5581 let args =
56- [path] @ match relative_to with None -> [] | Some vdi -> [" --diff" ; vdi]
82+ [path]
83+ @ (match relative_to with None -> [] | Some vdi -> [" --diff" ; vdi])
84+ @ ( match relative_to_qcow_path with
85+ | None ->
86+ []
87+ | Some _ ->
88+ [" --json-header-diff" ; unique_string]
89+ )
90+ @ match qcow_path with None -> [] | Some _ -> [" --json-header" ]
5791 in
5892 let qcow_tool = ! Xapi_globs. qcow_to_stdout in
59- run_qcow_tool qcow_tool progress_cb args ~output_fd: unix_fd
93+ let replace_fds = Option. map (fun fd -> [(unique_string, fd)]) diff_fd in
94+ Xapi_stdext_pervasives.Pervasiveext. finally
95+ (fun () ->
96+ run_qcow_tool qcow_tool progress_cb args ?input_fd ~output_fd: unix_fd
97+ ?replace_fds
98+ )
99+ (fun () ->
100+ Option. iter Unix. close input_fd ;
101+ Option. iter Unix. close diff_fd
102+ )
0 commit comments