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

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