From abca41c3081476f1fcc8ca383734d7b8c74a6ef7 Mon Sep 17 00:00:00 2001 From: David Scott Date: Fri, 1 May 2015 14:24:53 +0100 Subject: [PATCH 1/2] xenvmd: add an API to flush metadata updates for an LV This will be needed as part of a "deactivate" CLI command. The implementation simply flushes all outstanding ToLVM queues since it does not know on which queue updates may be present. Signed-off-by: David Scott --- idl/xenvm_interface.ml | 4 ++++ xenvmd/xenvmd.ml | 25 +++++++++++++++++++------ 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/idl/xenvm_interface.ml b/idl/xenvm_interface.ml index 2804509..03df446 100644 --- a/idl/xenvm_interface.ml +++ b/idl/xenvm_interface.ml @@ -16,6 +16,10 @@ external remove : name:string -> unit = "" external resize : name:string -> size:int64 -> unit = "" external set_status : name:string -> readonly:bool -> unit = "" +external flush : name:string -> unit = "" +(** [flush lv] processes all pending allocations for this LV, such that + future calls to [get_lv] will return accurate metadata. *) + external shutdown : unit -> unit = "" type queue = { diff --git a/xenvmd/xenvmd.ml b/xenvmd/xenvmd.ml index 171b975..1e1329a 100644 --- a/xenvmd/xenvmd.ml +++ b/xenvmd/xenvmd.ml @@ -279,7 +279,10 @@ module VolumeManager = struct free_LVs := (name, (freeLVM,freeLVMid)) :: !free_LVs; return () - let flush name = + (* Hold this mutex when actively flushing from the ToLVM queues *) + let flush_m = Lwt_mutex.create () + + let flush_already_locked name = if not(List.mem_assoc name !to_LVMs) then return () else begin @@ -309,7 +312,7 @@ module VolumeManager = struct ToLVM.suspend to_lvm >>= fun () -> (* There may still be updates in the ToLVM queue *) - flush name + Lwt_mutex.with_lock flush_m (fun () -> flush_already_locked name) >>= fun () -> debug "ToLVM queue for %s has been suspended and flushed" name; to_LVMs := List.filter (fun (n, _) -> n <> name) !to_LVMs; @@ -358,6 +361,15 @@ module VolumeManager = struct ) !to_LVMs end + let flush_all () = + Lwt_mutex.with_lock Host.flush_m + (fun () -> + Lwt_list.iter_s + (fun (host, _) -> + Host.flush_already_locked host + ) !to_LVMs + ) + let shutdown () = Lwt_list.iter_s (fun (host, _) -> @@ -566,6 +578,10 @@ module Impl = struct return (`Ok ({ vg with Vg.lvs = Vg.LVs.empty }, lv)) )) + let flush context ~name = + (* We don't know where [name] is attached so we have to flush everything *) + VolumeManager.flush_all () + let shutdown context () = VolumeManager.shutdown () >>= fun () -> @@ -616,10 +632,7 @@ let run port config daemon = >>= fun () -> (* 2. Are there any pending LVM updates from hosts? *) - Lwt_list.iter_s - (fun (host, _) -> - VolumeManager.Host.flush host - ) !VolumeManager.to_LVMs + VolumeManager.flush_all () >>= fun () -> debug "sleeping for 5s"; From dd8b846a2d8b9e612dd616d46240af5db4c9bf5f Mon Sep 17 00:00:00 2001 From: David Scott Date: Fri, 1 May 2015 14:27:38 +0100 Subject: [PATCH 2/2] lvchange: when deactivating, call flush() This ensures that future calls to activate on other hosts will see the current metadata. Signed-off-by: David Scott --- xenvm/lvchange.ml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/xenvm/lvchange.ml b/xenvm/lvchange.ml index c4a37b6..f8284ae 100644 --- a/xenvm/lvchange.ml +++ b/xenvm/lvchange.ml @@ -42,6 +42,7 @@ let lvchange_activate copts vg_name lv_name physical_device = ) let deactivate vg lv = + let open Xenvm_common in let name = Mapper.name_of vg lv in let all = Devmapper.ls () in if List.mem name all @@ -49,7 +50,7 @@ let deactivate vg lv = (* Delete the device node *) let path = dev_path_of vg.Lvm.Vg.name lv.Lvm.Lv.name in Lwt.catch (fun () -> Lwt_unix.unlink path) (fun _ -> Lwt.return ()) >>= fun () -> - return () + Client.flush ~name:lv.Lvm.Lv.name let lvchange_deactivate copts vg_name lv_name = let open Xenvm_common in