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