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
|