Skip to content

Commit 7f0c155

Browse files
Christian Lindiglindig
authored andcommitted
CA-384537 support NBD for CD device
Passing an NBD to qemu using qmp: open the socket and pass it to qmp. Compared to the existing case that the CD is opened as a raw device the handling of the socket is slightly different: it does not require a Qmp.Remove_fd. Signed-off-by: Christian Lindig <christian.lindig@cloud.com>
1 parent c8338d4 commit 7f0c155

File tree

1 file changed

+36
-1
lines changed

1 file changed

+36
-1
lines changed

ocaml/xenopsd/xc/device.ml

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2990,14 +2990,22 @@ module Backend = struct
29902990
| _ ->
29912991
internal_error "unexpected disk for devid %d" devid
29922992

2993+
(* parse NBD URI. We are not using the URI module because the
2994+
format is not compliant but used by qemu. Using sscanf instead
2995+
to recognise and parse the specific URI *)
29932996
let is_nbd str =
2994-
try Scanf.sscanf str "nbd:unix:%s@:exportname=%s" (fun x y -> true)
2997+
try Scanf.sscanf str "nbd:unix:%s@:exportname=%s" (fun _ _ -> true)
29952998
with _ -> false
29962999

29973000
let nbd str =
29983001
try Scanf.sscanf str "nbd:unix:%s@:exportname=%s" (fun x y -> (x, y))
29993002
with _ -> internal_error "%s: failed to parse '%s'" __FUNCTION__ str
30003003

3004+
let with_socket path f =
3005+
let addr = Unix.ADDR_UNIX path in
3006+
let fd = Unix.socket Unix.PF_UNIX Unix.SOCK_STREAM 0 in
3007+
finally (fun () -> Unix.connect fd addr ; f fd) (fun () -> Unix.close fd)
3008+
30013009
let qemu_media_change ~xs device _type params =
30023010
debug "%s: params='%s'" __FUNCTION__ params ;
30033011
Vbd_Common.qemu_media_change ~xs device _type params ;
@@ -3008,6 +3016,33 @@ module Backend = struct
30083016
match params with
30093017
| "" ->
30103018
qmp_send_cmd domid Qmp.(Eject (cd, Some true)) |> ignore
3019+
| params when is_nbd params ->
3020+
let path, exportname = nbd params in
3021+
info "%s: domain=%d NBD socket=%s" __FUNCTION__ domid path ;
3022+
with_socket path @@ fun fd ->
3023+
let cmd = Qmp.(Add_fd None) in
3024+
let fd_info =
3025+
match qmp_send_cmd ~send_fd:fd domid cmd with
3026+
| Qmp.Fd_info x ->
3027+
x
3028+
| other ->
3029+
internal_error "Unexpected result for QMP command: %s"
3030+
Qmp.(other |> as_msg |> string_of_message)
3031+
in
3032+
let filename =
3033+
Printf.sprintf "nbd:fd:%d:exportname=%s" fd_info.Qmp.fdset_id
3034+
exportname
3035+
in
3036+
let medium =
3037+
Qmp.
3038+
{
3039+
medium_device= cd
3040+
; medium_filename= filename
3041+
; medium_format= Some "raw"
3042+
}
3043+
in
3044+
let cmd = Qmp.(Blockdev_change_medium medium) in
3045+
qmp_send_cmd domid cmd |> ignore
30113046
| params ->
30123047
Unixext.with_file params [Unix.O_RDONLY] 0o640 @@ fun fd_cd ->
30133048
let cmd = Qmp.(Add_fd None) in

0 commit comments

Comments
 (0)