143 lines
5.4 KiB
Diff
143 lines
5.4 KiB
Diff
|
From 80831868395d161af8c47edf2f54234c63581d8d Mon Sep 17 00:00:00 2001
|
|||
|
From: "Richard W.M. Jones" <rjones@redhat.com>
|
|||
|
Date: Fri, 28 Jan 2022 09:30:29 +0000
|
|||
|
Subject: [PATCH] qemu-nbd: Implement output compression for qcow2 files
|
|||
|
|
|||
|
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
|
|||
|
(cherry picked from commit 71c4301909cb307def02ebcd0e89beee4138e7f2)
|
|||
|
---
|
|||
|
lib/qemuNBD.ml | 11 +++++++++--
|
|||
|
lib/qemuNBD.mli | 5 +++++
|
|||
|
output/output.ml | 39 ++++++++++++++++++++++++++++++++++++---
|
|||
|
output/output.mli | 1 +
|
|||
|
4 files changed, 51 insertions(+), 5 deletions(-)
|
|||
|
|
|||
|
diff --git a/lib/qemuNBD.ml b/lib/qemuNBD.ml
|
|||
|
index ae21b17c..bbb65f41 100644
|
|||
|
--- a/lib/qemuNBD.ml
|
|||
|
+++ b/lib/qemuNBD.ml
|
|||
|
@@ -55,14 +55,16 @@ type cmd = {
|
|||
|
disk : string;
|
|||
|
mutable snapshot : bool;
|
|||
|
mutable format : string option;
|
|||
|
+ mutable imgopts : bool;
|
|||
|
}
|
|||
|
|
|||
|
-let create disk = { disk; snapshot = false; format = None }
|
|||
|
+let create disk = { disk; snapshot = false; format = None; imgopts = false }
|
|||
|
|
|||
|
let set_snapshot cmd snap = cmd.snapshot <- snap
|
|||
|
let set_format cmd format = cmd.format <- format
|
|||
|
+let set_image_opts cmd imgopts = cmd.imgopts <- imgopts
|
|||
|
|
|||
|
-let run_unix socket { disk; snapshot; format } =
|
|||
|
+let run_unix socket { disk; snapshot; format; imgopts } =
|
|||
|
assert (disk <> "");
|
|||
|
|
|||
|
(* Create a temporary directory where we place the PID file. *)
|
|||
|
@@ -85,6 +87,11 @@ let run_unix socket { disk; snapshot; format } =
|
|||
|
(* -s adds a protective overlay. *)
|
|||
|
if snapshot then List.push_back args "-s";
|
|||
|
|
|||
|
+ (* --image-opts reinterprets the filename parameter as a set of
|
|||
|
+ * image options.
|
|||
|
+ *)
|
|||
|
+ if imgopts then List.push_back args "--image-opts";
|
|||
|
+
|
|||
|
if have_selinux && qemu_nbd_has_selinux_label_option () then (
|
|||
|
List.push_back args "--selinux-label";
|
|||
|
List.push_back args "system_u:object_r:svirt_socket_t:s0"
|
|||
|
diff --git a/lib/qemuNBD.mli b/lib/qemuNBD.mli
|
|||
|
index e10d3106..afe9d944 100644
|
|||
|
--- a/lib/qemuNBD.mli
|
|||
|
+++ b/lib/qemuNBD.mli
|
|||
|
@@ -43,6 +43,11 @@ val set_snapshot : cmd -> bool -> unit
|
|||
|
val set_format : cmd -> string option -> unit
|
|||
|
(** Set the format [--format] parameter. *)
|
|||
|
|
|||
|
+val set_image_opts : cmd -> bool -> unit
|
|||
|
+(** Set whether the [--image-opts] parameter is used. This changes
|
|||
|
+ the meaning of the [filename] parameter to a set of image options.
|
|||
|
+ Consult the qemu-nbd man page for more details. *)
|
|||
|
+
|
|||
|
val run_unix : string -> cmd -> string * int
|
|||
|
(** Start qemu-nbd command listening on a Unix domain socket,
|
|||
|
waiting for the process to start up.
|
|||
|
diff --git a/output/output.ml b/output/output.ml
|
|||
|
index 5c6670b9..23c3932d 100644
|
|||
|
--- a/output/output.ml
|
|||
|
+++ b/output/output.ml
|
|||
|
@@ -69,7 +69,7 @@ let error_if_disk_count_gt dir n =
|
|||
|
if Sys.file_exists socket then
|
|||
|
error (f_"this output module doesn't support copying more than %d disks") n
|
|||
|
|
|||
|
-let output_to_local_file ?(changeuid = fun f -> f ())
|
|||
|
+let output_to_local_file ?(changeuid = fun f -> f ()) ?(compressed = false)
|
|||
|
output_alloc output_format filename size socket =
|
|||
|
(* Check nbdkit is installed and has the required plugin. *)
|
|||
|
if not (Nbdkit.is_installed ()) then
|
|||
|
@@ -78,6 +78,24 @@ let output_to_local_file ?(changeuid = fun f -> f ())
|
|||
|
error (f_"nbdkit-file-plugin is not installed or not working");
|
|||
|
let nbdkit_config = Nbdkit.config () in
|
|||
|
|
|||
|
+ if compressed then (
|
|||
|
+ (* Only allow compressed with -of qcow2. *)
|
|||
|
+ if output_format <> "qcow2" then
|
|||
|
+ error (f_"‘-oo compressed’ is only allowed when the output format \
|
|||
|
+ is a local qcow2-format file, i.e. ‘-of qcow2’");
|
|||
|
+
|
|||
|
+ (* Check nbdcopy is new enough. This assumes that the version of
|
|||
|
+ * libnbd is the same as the version of nbdcopy, but parsing this
|
|||
|
+ * is easier. We can remove this check when we build-depend on
|
|||
|
+ * libnbd >= 1.14.
|
|||
|
+ *)
|
|||
|
+ let version =
|
|||
|
+ NBD.create () |> NBD.get_version |>
|
|||
|
+ String.nsplit "." |> List.map int_of_string in
|
|||
|
+ if version < [1; 13; 5] then
|
|||
|
+ error (f_"-oo compressed option requires nbdcopy >= 1.13.5")
|
|||
|
+ );
|
|||
|
+
|
|||
|
let g = open_guestfs () in
|
|||
|
let preallocation =
|
|||
|
match output_alloc with
|
|||
|
@@ -103,9 +121,24 @@ let output_to_local_file ?(changeuid = fun f -> f ())
|
|||
|
On_exit.kill pid
|
|||
|
|
|||
|
| "qcow2" ->
|
|||
|
- let cmd = QemuNBD.create filename in
|
|||
|
+ let cmd =
|
|||
|
+ if compressed then (
|
|||
|
+ let qemu_quote str = String.replace str "," ",," in
|
|||
|
+ let image_opts = [ "driver=compress";
|
|||
|
+ "file.driver=qcow2";
|
|||
|
+ "file.file.driver=file";
|
|||
|
+ "file.file.filename=" ^ qemu_quote filename ] in
|
|||
|
+ let image_opts = String.concat "," image_opts in
|
|||
|
+ let cmd = QemuNBD.create image_opts in
|
|||
|
+ QemuNBD.set_image_opts cmd true;
|
|||
|
+ cmd
|
|||
|
+ )
|
|||
|
+ else (* not compressed *) (
|
|||
|
+ let cmd = QemuNBD.create filename in
|
|||
|
+ QemuNBD.set_format cmd (Some "qcow2");
|
|||
|
+ cmd
|
|||
|
+ ) in
|
|||
|
QemuNBD.set_snapshot cmd false;
|
|||
|
- QemuNBD.set_format cmd (Some "qcow2");
|
|||
|
let _, pid = QemuNBD.run_unix socket cmd in
|
|||
|
On_exit.kill pid
|
|||
|
|
|||
|
diff --git a/output/output.mli b/output/output.mli
|
|||
|
index 8d3d6865..c1f0f53d 100644
|
|||
|
--- a/output/output.mli
|
|||
|
+++ b/output/output.mli
|
|||
|
@@ -84,6 +84,7 @@ val error_if_disk_count_gt : string -> int -> unit
|
|||
|
called. *)
|
|||
|
|
|||
|
val output_to_local_file : ?changeuid:((unit -> unit) -> unit) ->
|
|||
|
+ ?compressed:bool ->
|
|||
|
Types.output_allocation ->
|
|||
|
string -> string -> int64 -> string ->
|
|||
|
unit
|