Skip to content

Commit 8f94586

Browse files
authored
CP-53446: Split plug and unplug atomics to enable live migration downtime reduction later (#6362)
Split the plug and unplug atomics into separate attach/activate and deactivate/detach atomics. This is gated by two separate flags and both are switched off by default. When switched on, this should still be a no-op by calling them in serial where plug/unplug are currently used, but will allow us to later use these atomics separately elsewhere for optimisation. Opening this as a draft PR as plug/unplug is fundamental so the logic needs to be watertight before we consider merging.
2 parents cfeac55 + 1a46f33 commit 8f94586

File tree

7 files changed

+423
-208
lines changed

7 files changed

+423
-208
lines changed

ocaml/xenopsd/lib/storage.ml

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -62,20 +62,20 @@ let vm_of_domid vmdomid =
6262
"Invalid domid, could not be converted to int, passing empty string." ;
6363
Storage_interface.Vm.of_string ""
6464

65-
let attach_and_activate ~task ~_vm ~vmdomid ~dp ~sr ~vdi ~read_write =
65+
let attach ~task ~_vm ~vmdomid ~dp ~sr ~vdi ~read_write =
66+
let dbg = get_dbg task in
67+
Xenops_task.with_subtask task
68+
(Printf.sprintf "VDI.attach3 %s" dp)
69+
(transform_exception (fun () ->
70+
Client.VDI.attach3 dbg dp sr vdi vmdomid read_write
71+
)
72+
)
73+
74+
let activate ~task ~_vm ~vmdomid ~dp ~sr ~vdi =
6675
let dbg = get_dbg task in
67-
let result =
68-
Xenops_task.with_subtask task
69-
(Printf.sprintf "VDI.attach3 %s" dp)
70-
(transform_exception (fun () ->
71-
Client.VDI.attach3 dbg dp sr vdi vmdomid read_write
72-
)
73-
)
74-
in
7576
Xenops_task.with_subtask task
7677
(Printf.sprintf "VDI.activate3 %s" dp)
77-
(transform_exception (fun () -> Client.VDI.activate3 dbg dp sr vdi vmdomid)) ;
78-
result
78+
(transform_exception (fun () -> Client.VDI.activate3 dbg dp sr vdi vmdomid))
7979

8080
let deactivate task dp sr vdi vmdomid =
8181
debug "Deactivating disk %s %s" (Sr.string_of sr) (Vdi.string_of vdi) ;

ocaml/xenopsd/lib/xenops_server.ml

Lines changed: 68 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ let finally = Xapi_stdext_pervasives.Pervasiveext.finally
3737

3838
let domain_shutdown_ack_timeout = ref 60.
3939

40+
let xenopsd_vbd_plug_unplug_legacy = ref true
41+
4042
type context = {
4143
transferred_fd: Unix.file_descr option
4244
(** some API calls take a file descriptor argument *)
@@ -122,10 +124,14 @@ type atomic =
122124
| VM_hook_script_stable of (Vm.id * Xenops_hooks.script * string * Vm.id)
123125
| VM_hook_script of (Vm.id * Xenops_hooks.script * string)
124126
| VBD_plug of Vbd.id
127+
| VBD_attach of Vbd.id
128+
| VBD_activate of Vbd.id
125129
| VBD_epoch_begin of (Vbd.id * disk * bool)
126130
| VBD_epoch_end of (Vbd.id * disk)
127131
| VBD_set_qos of Vbd.id
128132
| VBD_unplug of Vbd.id * bool
133+
| VBD_deactivate of Vbd.id * bool
134+
| VBD_detach of Vbd.id
129135
| VBD_insert of Vbd.id * disk
130136
| VBD_set_active of Vbd.id * bool
131137
| VM_remove of Vm.id
@@ -195,6 +201,10 @@ let rec name_of_atomic = function
195201
"VM_hook_script"
196202
| VBD_plug _ ->
197203
"VBD_plug"
204+
| VBD_attach _ ->
205+
"VBD_attach"
206+
| VBD_activate _ ->
207+
"VBD_activate"
198208
| VBD_epoch_begin _ ->
199209
"VBD_epoch_begin"
200210
| VBD_epoch_end _ ->
@@ -203,6 +213,10 @@ let rec name_of_atomic = function
203213
"VBD_set_qos"
204214
| VBD_unplug _ ->
205215
"VBD_unplug"
216+
| VBD_deactivate _ ->
217+
"VBD_deactivate"
218+
| VBD_detach _ ->
219+
"VBD_detach"
206220
| VBD_insert _ ->
207221
"VBD_insert"
208222
| VBD_set_active _ ->
@@ -1580,6 +1594,26 @@ let parallel_map name ~id lst f = parallel name ~id (List.concat_map f lst)
15801594

15811595
let map_or_empty f x = Option.value ~default:[] (Option.map f x)
15821596

1597+
(* Creates a Serial of 2 or more Atomics. If the number of Atomics could be
1598+
less than this, use serial or serial_concat *)
1599+
let serial_of name ~id at1 at2 ats =
1600+
Serial (id, Printf.sprintf "%s VM=%s" name id, at1 :: at2 :: ats)
1601+
1602+
let vbd_plug vbd_id =
1603+
if !xenopsd_vbd_plug_unplug_legacy then
1604+
VBD_plug vbd_id
1605+
else
1606+
serial_of "VBD.attach_and_activate" ~id:(VBD_DB.vm_of vbd_id)
1607+
(VBD_attach vbd_id) (VBD_activate vbd_id) []
1608+
1609+
let vbd_unplug vbd_id force =
1610+
if !xenopsd_vbd_plug_unplug_legacy then
1611+
VBD_unplug (vbd_id, force)
1612+
else
1613+
serial_of "VBD.deactivate_and_detach" ~id:(VBD_DB.vm_of vbd_id)
1614+
(VBD_deactivate (vbd_id, force))
1615+
(VBD_detach vbd_id) []
1616+
15831617
let rec atomics_of_operation = function
15841618
| VM_start (id, force) ->
15851619
let vbds_rw, vbds_ro = VBD_DB.vbds id |> vbd_plug_sets in
@@ -1604,7 +1638,7 @@ let rec atomics_of_operation = function
16041638
[VBD_epoch_begin (vbd.Vbd.id, x, vbd.Vbd.persistent)]
16051639
)
16061640
vbd.Vbd.backend
1607-
; [VBD_plug vbd.Vbd.id]
1641+
; [vbd_plug vbd.Vbd.id]
16081642
]
16091643
)
16101644
in
@@ -1668,7 +1702,7 @@ let rec atomics_of_operation = function
16681702
]
16691703
; parallel_concat "Devices.unplug" ~id
16701704
[
1671-
List.map (fun vbd -> VBD_unplug (vbd.Vbd.id, true)) vbds
1705+
List.map (fun vbd -> vbd_unplug vbd.Vbd.id true) vbds
16721706
; List.map (fun vif -> VIF_unplug (vif.Vif.id, true)) vifs
16731707
; List.map (fun pci -> PCI_unplug pci.Pci.id) pcis
16741708
]
@@ -1692,7 +1726,7 @@ let rec atomics_of_operation = function
16921726
let name_one = pf "VBD.activate_and_plug %s" typ in
16931727
parallel_map name_multi ~id vbds (fun vbd ->
16941728
serial name_one ~id
1695-
[VBD_set_active (vbd.Vbd.id, true); VBD_plug vbd.Vbd.id]
1729+
[VBD_set_active (vbd.Vbd.id, true); vbd_plug vbd.Vbd.id]
16961730
)
16971731
in
16981732
[
@@ -1825,9 +1859,9 @@ let rec atomics_of_operation = function
18251859
]
18261860
|> List.concat
18271861
| VBD_hotplug id ->
1828-
[VBD_set_active (id, true); VBD_plug id]
1862+
[VBD_set_active (id, true); vbd_plug id]
18291863
| VBD_hotunplug (id, force) ->
1830-
[VBD_unplug (id, force); VBD_set_active (id, false)]
1864+
[vbd_unplug id force; VBD_set_active (id, false)]
18311865
| VIF_hotplug id ->
18321866
[VIF_set_active (id, true); VIF_plug id]
18331867
| VIF_hotunplug (id, force) ->
@@ -2017,7 +2051,16 @@ let rec perform_atomic ~progress_callback ?result (op : atomic)
20172051
Xenops_hooks.vm ~script ~reason ~id ~extra_args
20182052
| VBD_plug id ->
20192053
debug "VBD.plug %s" (VBD_DB.string_of_id id) ;
2020-
B.VBD.plug t (VBD_DB.vm_of id) (VBD_DB.read_exn id) ;
2054+
B.VBD.attach t (VBD_DB.vm_of id) (VBD_DB.read_exn id) ;
2055+
B.VBD.activate t (VBD_DB.vm_of id) (VBD_DB.read_exn id) ;
2056+
VBD_DB.signal id
2057+
| VBD_attach id ->
2058+
debug "VBD.attach %s" (VBD_DB.string_of_id id) ;
2059+
B.VBD.attach t (VBD_DB.vm_of id) (VBD_DB.read_exn id) ;
2060+
VBD_DB.signal id
2061+
| VBD_activate id ->
2062+
debug "VBD.activate %s" (VBD_DB.string_of_id id) ;
2063+
B.VBD.activate t (VBD_DB.vm_of id) (VBD_DB.read_exn id) ;
20212064
VBD_DB.signal id
20222065
| VBD_set_active (id, b) ->
20232066
debug "VBD.set_active %s %b" (VBD_DB.string_of_id id) b ;
@@ -2036,8 +2079,22 @@ let rec perform_atomic ~progress_callback ?result (op : atomic)
20362079
| VBD_unplug (id, force) ->
20372080
debug "VBD.unplug %s" (VBD_DB.string_of_id id) ;
20382081
finally
2039-
(fun () -> B.VBD.unplug t (VBD_DB.vm_of id) (VBD_DB.read_exn id) force)
2082+
(fun () ->
2083+
B.VBD.deactivate t (VBD_DB.vm_of id) (VBD_DB.read_exn id) force ;
2084+
B.VBD.detach t (VBD_DB.vm_of id) (VBD_DB.read_exn id)
2085+
)
20402086
(fun () -> VBD_DB.signal id)
2087+
| VBD_deactivate (id, force) ->
2088+
debug "VBD.deactivate %s" (VBD_DB.string_of_id id) ;
2089+
finally
2090+
(fun () ->
2091+
B.VBD.deactivate t (VBD_DB.vm_of id) (VBD_DB.read_exn id) force
2092+
)
2093+
(fun () -> VBD_DB.signal id)
2094+
| VBD_detach id ->
2095+
debug "VBD.detach %s" (VBD_DB.string_of_id id) ;
2096+
B.VBD.detach t (VBD_DB.vm_of id) (VBD_DB.read_exn id) ;
2097+
VBD_DB.signal id
20412098
| VBD_insert (id, disk) -> (
20422099
(* NB this is also used to "refresh" ie signal a qemu that it should
20432100
re-open a device, useful for when a physical CDROM is inserted into the
@@ -2445,11 +2502,15 @@ and trigger_cleanup_after_failure_atom op t =
24452502
match op with
24462503
| VBD_eject id
24472504
| VBD_plug id
2505+
| VBD_attach id
2506+
| VBD_activate id
24482507
| VBD_set_active (id, _)
24492508
| VBD_epoch_begin (id, _, _)
24502509
| VBD_epoch_end (id, _)
24512510
| VBD_set_qos id
24522511
| VBD_unplug (id, _)
2512+
| VBD_deactivate (id, _)
2513+
| VBD_detach id
24532514
| VBD_insert (id, _) ->
24542515
immediate_operation dbg (fst id) (VBD_check_state id)
24552516
| VIF_plug id

ocaml/xenopsd/lib/xenops_server_plugin.ml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -207,9 +207,13 @@ module type S = sig
207207

208208
val epoch_end : Xenops_task.task_handle -> Vm.id -> disk -> unit
209209

210-
val plug : Xenops_task.task_handle -> Vm.id -> Vbd.t -> unit
210+
val attach : Xenops_task.task_handle -> Vm.id -> Vbd.t -> unit
211211

212-
val unplug : Xenops_task.task_handle -> Vm.id -> Vbd.t -> bool -> unit
212+
val activate : Xenops_task.task_handle -> Vm.id -> Vbd.t -> unit
213+
214+
val deactivate : Xenops_task.task_handle -> Vm.id -> Vbd.t -> bool -> unit
215+
216+
val detach : Xenops_task.task_handle -> Vm.id -> Vbd.t -> unit
213217

214218
val insert : Xenops_task.task_handle -> Vm.id -> Vbd.t -> disk -> unit
215219

ocaml/xenopsd/lib/xenops_server_simulator.ml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -673,9 +673,13 @@ module VBD = struct
673673

674674
let epoch_end _ (_vm : Vm.id) (_disk : disk) = ()
675675

676-
let plug _ (vm : Vm.id) (vbd : Vbd.t) = with_lock m (add_vbd vm vbd)
676+
let attach _ (vm : Vm.id) (vbd : Vbd.t) = with_lock m (add_vbd vm vbd)
677677

678-
let unplug _ vm vbd _ = with_lock m (remove_vbd vm vbd)
678+
let activate _ (_vm : Vm.id) (_vbd : Vbd.t) = ()
679+
680+
let deactivate _ vm vbd _ = with_lock m (remove_vbd vm vbd)
681+
682+
let detach _ _vm _vbd = ()
679683

680684
let insert _ _vm _vbd _disk = ()
681685

ocaml/xenopsd/lib/xenops_server_skeleton.ml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,9 +145,13 @@ module VBD = struct
145145

146146
let epoch_end _ _ _ = ()
147147

148-
let plug _ _ _ = unimplemented "VBD.plug"
148+
let attach _ _ _ = unimplemented "VBD.attach"
149149

150-
let unplug _ _ _ _ = unimplemented "VBD.unplug"
150+
let activate _ _ _ = unimplemented "VBD.activate"
151+
152+
let deactivate _ _ _ _ = unimplemented "VBD.deactivate"
153+
154+
let detach _ _ _ = unimplemented "VBD.detach"
151155

152156
let insert _ _ _ _ = unimplemented "VBD.insert"
153157

ocaml/xenopsd/lib/xenopsd.ml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,11 @@ let options =
283283
, (fun () -> string_of_int !test_open)
284284
, "TESTING only: open N file descriptors"
285285
)
286+
; ( "xenopsd-vbd-plug-unplug-legacy"
287+
, Arg.Bool (fun x -> Xenops_server.xenopsd_vbd_plug_unplug_legacy := x)
288+
, (fun () -> string_of_bool !Xenops_server.xenopsd_vbd_plug_unplug_legacy)
289+
, "False if we want to split the plug atomic into attach/activate"
290+
)
286291
]
287292

288293
let path () = Filename.concat !sockets_path "xenopsd"

0 commit comments

Comments
 (0)