Blame SOURCES/0027-o-rhv-Unmount-the-temporary-NFS-mountpoint-as-late-a.patch

c1a9fa
From 0d92a42aab3fb0e7569294675666976724156128 Mon Sep 17 00:00:00 2001
c1a9fa
From: "Richard W.M. Jones" <rjones@redhat.com>
c1a9fa
Date: Thu, 14 Jul 2022 13:15:49 +0100
c1a9fa
Subject: [PATCH] -o rhv: Unmount the temporary NFS mountpoint as late as
c1a9fa
 possible
c1a9fa
c1a9fa
To partially avoid a potential race against nbdkit or qemu-nbd
c1a9fa
releasing files on the mountpoint before they exit, unmount as late as
c1a9fa
we can.
c1a9fa
c1a9fa
See also https://bugzilla.redhat.com/show_bug.cgi?id=1953286#c26
c1a9fa
c1a9fa
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
c1a9fa
(cherry picked from commit e96357fc3b26aaf96eaa21afa36c894a27af6261)
c1a9fa
---
c1a9fa
 common               | 2 +-
c1a9fa
 output/output_rhv.ml | 4 ++--
c1a9fa
 2 files changed, 3 insertions(+), 3 deletions(-)
c1a9fa
c1a9fa
Submodule common fd964c1b..1000604f:
c1a9fa
diff --git a/common/mltools/on_exit.ml b/common/mltools/on_exit.ml
c1a9fa
index cae12e73..f8ef74e1 100644
c1a9fa
--- a/common/mltools/on_exit.ml
c1a9fa
+++ b/common/mltools/on_exit.ml
c1a9fa
@@ -23,39 +23,39 @@ open Common_gettext.Gettext
c1a9fa
 open Unix
c1a9fa
 open Printf
c1a9fa
 
c1a9fa
-(* List of files to unlink. *)
c1a9fa
-let files = ref []
c1a9fa
+type action =
c1a9fa
+  | Unlink of string     (* filename *)
c1a9fa
+  | Rm_rf of string      (* directory *)
c1a9fa
+  | Kill of int * int    (* signal, pid *)
c1a9fa
+  | Fn of (unit -> unit) (* generic function *)
c1a9fa
 
c1a9fa
-(* List of directories to remove. *)
c1a9fa
-let rmdirs = ref []
c1a9fa
-
c1a9fa
-(* List of PIDs to kill. *)
c1a9fa
-let kills = ref []
c1a9fa
-
c1a9fa
-(* List of functions to call. *)
c1a9fa
-let fns = ref []
c1a9fa
+(* List of (priority, action). *)
c1a9fa
+let actions = ref []
c1a9fa
 
c1a9fa
 (* Perform a single exit action, printing any exception but
c1a9fa
  * otherwise ignoring failures.
c1a9fa
  *)
c1a9fa
-let do_action f arg =
c1a9fa
-  try f arg with exn -> debug "%s" (Printexc.to_string exn)
c1a9fa
+let do_action action =
c1a9fa
+  try
c1a9fa
+    match action with
c1a9fa
+    | Unlink file -> Unix.unlink file
c1a9fa
+    | Rm_rf dir ->
c1a9fa
+       let cmd = sprintf "rm -rf -- %s" (Filename.quote dir) in
c1a9fa
+       ignore (Tools_utils.shell_command cmd)
c1a9fa
+    | Kill (signal, pid) ->
c1a9fa
+       kill pid signal
c1a9fa
+    | Fn f -> f ()
c1a9fa
+  with exn -> debug "%s" (Printexc.to_string exn)
c1a9fa
 
c1a9fa
 (* Make sure the actions are performed only once. *)
c1a9fa
 let done_actions = ref false
c1a9fa
 
c1a9fa
-(* Perform the exit actions. *)
c1a9fa
+(* Perform the exit actions in priority order (lowest prio first). *)
c1a9fa
 let do_actions () =
c1a9fa
   if not !done_actions then (
c1a9fa
-    List.iter (do_action (fun f -> f ())) !fns;
c1a9fa
-    List.iter (do_action (fun (signal, pid) -> kill pid signal)) !kills;
c1a9fa
-    List.iter (do_action (fun file -> Unix.unlink file)) !files;
c1a9fa
-    List.iter (do_action (
c1a9fa
-      fun dir ->
c1a9fa
-        let cmd = sprintf "rm -rf -- %s" (Filename.quote dir) in
c1a9fa
-        ignore (Tools_utils.shell_command cmd)
c1a9fa
-      )
c1a9fa
-    ) !rmdirs;
c1a9fa
+    let actions = List.sort (fun (a, _) (b, _) -> compare a b) !actions in
c1a9fa
+    let actions = List.map snd actions in
c1a9fa
+    List.iter do_action actions
c1a9fa
   );
c1a9fa
   done_actions := true
c1a9fa
 
c1a9fa
@@ -94,18 +94,18 @@ let register () =
c1a9fa
   );
c1a9fa
   registered := true
c1a9fa
 
c1a9fa
-let f fn =
c1a9fa
+let f ?(prio = 5000) fn =
c1a9fa
   register ();
c1a9fa
-  List.push_front fn fns
c1a9fa
+  List.push_front (prio, Fn fn) actions
c1a9fa
 
c1a9fa
-let unlink filename =
c1a9fa
+let unlink ?(prio = 5000) filename =
c1a9fa
   register ();
c1a9fa
-  List.push_front filename files
c1a9fa
+  List.push_front (prio, Unlink filename) actions
c1a9fa
 
c1a9fa
-let rm_rf dir =
c1a9fa
+let rm_rf ?(prio = 5000) dir =
c1a9fa
   register ();
c1a9fa
-  List.push_front dir rmdirs
c1a9fa
+  List.push_front (prio, Rm_rf dir) actions
c1a9fa
 
c1a9fa
-let kill ?(signal = Sys.sigterm) pid =
c1a9fa
+let kill ?(prio = 5000) ?(signal = Sys.sigterm) pid =
c1a9fa
   register ();
c1a9fa
-  List.push_front (signal, pid) kills
c1a9fa
+  List.push_front (prio, Kill (signal, pid)) actions
c1a9fa
diff --git a/common/mltools/on_exit.mli b/common/mltools/on_exit.mli
c1a9fa
index 9bcf104f..66a85542 100644
c1a9fa
--- a/common/mltools/on_exit.mli
c1a9fa
+++ b/common/mltools/on_exit.mli
c1a9fa
@@ -28,6 +28,12 @@
c1a9fa
     killing another process, so we provide simple
c1a9fa
     wrappers for those common actions here.
c1a9fa
 
c1a9fa
+    Actions can be ordered by setting the optional [?prio]
c1a9fa
+    parameter in the range 0..9999.  By default actions
c1a9fa
+    have priority 5000.  Lower numbered actions run first.
c1a9fa
+    Higher numbered actions run last.  So to have an action
c1a9fa
+    run at the very end before exit you might use [~prio:9999]
c1a9fa
+
c1a9fa
     Note this module registers signal handlers for
c1a9fa
     SIGINT, SIGQUIT, SIGTERM and SIGHUP.  This means
c1a9fa
     that any program that links with mltools.cmxa
c1a9fa
@@ -39,18 +45,20 @@
c1a9fa
     Your cleanup action might no longer run unless the
c1a9fa
     program calls {!Stdlib.exit}. *)
c1a9fa
 
c1a9fa
-val f : (unit -> unit) -> unit
c1a9fa
+val f : ?prio:int -> (unit -> unit) -> unit
c1a9fa
 (** Register a function [f] which runs when the program exits.
c1a9fa
     Similar to [Stdlib.at_exit] but also runs if the program is
c1a9fa
-    killed with a signal that we can catch. *)
c1a9fa
+    killed with a signal that we can catch.
c1a9fa
 
c1a9fa
-val unlink : string -> unit
c1a9fa
+    [?prio] is the priority, default 5000.  See the description above. *)
c1a9fa
+
c1a9fa
+val unlink : ?prio:int -> string -> unit
c1a9fa
 (** Unlink a single temporary file on exit. *)
c1a9fa
 
c1a9fa
-val rm_rf : string -> unit
c1a9fa
+val rm_rf : ?prio:int -> string -> unit
c1a9fa
 (** Recursively remove a temporary directory on exit (using [rm -rf]). *)
c1a9fa
 
c1a9fa
-val kill : ?signal:int -> int -> unit
c1a9fa
+val kill : ?prio:int -> ?signal:int -> int -> unit
c1a9fa
 (** Kill [PID] on exit.  The signal sent defaults to [Sys.sigterm].
c1a9fa
 
c1a9fa
     Use this with care since you can end up unintentionally killing
c1a9fa
diff --git a/output/output_rhv.ml b/output/output_rhv.ml
c1a9fa
index 8571e07b..15a2c14a 100644
c1a9fa
--- a/output/output_rhv.ml
c1a9fa
+++ b/output/output_rhv.ml
c1a9fa
@@ -204,8 +204,8 @@ module RHV = struct
c1a9fa
        if run_command cmd <> 0 then
c1a9fa
          error (f_"mount command failed, see earlier errors.\n\nThis probably means you didn't specify the right %s path [-os %s], or else you need to rerun virt-v2v as root.") domain_class os;
c1a9fa
 
c1a9fa
-       (* Make sure it is unmounted at exit. *)
c1a9fa
-       On_exit.f (
c1a9fa
+       (* Make sure it is unmounted at exit, as late as possible (prio=9999) *)
c1a9fa
+       On_exit.f ~prio:9999 (
c1a9fa
          fun () ->
c1a9fa
            let cmd = [ "umount"; mp ] in
c1a9fa
            ignore (run_command cmd);