[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[Libguestfs] [PATCH 7/7] resize: Add workaround for qcow2 disk cache bug in qemu (RHBZ#836710).



From: "Richard W.M. Jones" <rjones redhat com>

Best to read the comment.
---
 resize/Makefile.am |    2 +-
 resize/resize.ml   |   33 ++++++++++++++++++++++++++++++++-
 2 files changed, 33 insertions(+), 2 deletions(-)

diff --git a/resize/Makefile.am b/resize/Makefile.am
index 70ace37..1234c96 100644
--- a/resize/Makefile.am
+++ b/resize/Makefile.am
@@ -56,7 +56,7 @@ bin_SCRIPTS = virt-resize
 # -I $(top_builddir)/src/.libs is a hack which forces corresponding -L
 # option to be passed to gcc, so we don't try linking against an
 # installed copy of libguestfs.
-OCAMLPACKAGES = -package str -I $(top_builddir)/src/.libs -I ../ocaml
+OCAMLPACKAGES = -package str,unix -I $(top_builddir)/src/.libs -I ../ocaml
 if HAVE_OCAML_PKG_GETTEXT
 OCAMLPACKAGES += -package gettext-stub
 endif
diff --git a/resize/resize.ml b/resize/resize.ml
index cd4c9d6..3118d74 100644
--- a/resize/resize.ml
+++ b/resize/resize.ml
@@ -1010,6 +1010,36 @@ let () =
 
 (* Copy over the data. *)
 let () =
+  (* Obviously when you've got a function called 'hack_for_...' you
+   * know it cannot be good.
+   *
+   * This works around a bug in qemu's qcow2 block driver.  If there
+   * are I/Os in flight and you send SIGTERM to qemu, then qemu
+   * segfaults.  This particularly happens when the output file is
+   * growing rapidly (because of the partition copies below) and we
+   * close the handle (which kills qemu).
+   *
+   * The ugly workaround is to monitor the disk file and wait until it
+   * stops growing before closing the handle.
+   *
+   * https://bugzilla.redhat.com/show_bug.cgi?id=836710
+   * https://bugzilla.redhat.com/show_bug.cgi?id=836913
+   *)
+  let hack_for_rhbz836710 g ?format outfile =
+    match format with
+    | None | Some "qcow2" -> (* only for qcow2 or auto *)
+      let get_size () = (Unix.LargeFile.stat outfile).Unix.LargeFile.st_size in
+      let rec loop size =
+        g#sync ();
+        g#sleep 1;
+        let size' = get_size () in
+        if size <> size' then
+          loop size'
+      in
+      loop (get_size ())
+    | _ -> ()
+  in
+
   List.iter (
     fun p ->
       match p.p_operation with
@@ -1033,7 +1063,8 @@ let () =
 
         (match p.p_type with
          | ContentUnknown | ContentPV _ | ContentFS _ ->
-           g#copy_device_to_device ~size:copysize source target
+           g#copy_device_to_device ~size:copysize source target;
+           hack_for_rhbz836710 g ?format:output_format outfile
 
          | ContentExtendedPartition ->
            (* You can't just copy an extended partition by name, eg.
-- 
1.7.10.4


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]