Skip to content

Commit 2d55b95

Browse files
committed
qcow_tool_wrapper: Read headers of QCOW2-backed VDIs on export
Pass the JSON output of read_headers into qcow2-to-stdout to handle the export further. Signed-off-by: Andrii Sultanov <[email protected]>
1 parent 28670f1 commit 2d55b95

File tree

1 file changed

+49
-6
lines changed

1 file changed

+49
-6
lines changed

ocaml/xapi/qcow_tool_wrapper.ml

Lines changed: 49 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,15 @@ module D = Debug.Make (struct let name = __MODULE__ end)
1616

1717
open 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

4748
let 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+
5365
let 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

Comments
 (0)