4 * Copyright (c) Intel Corporation.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
17 * * Neither the name of Intel Corporation nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 #include "spdk/string.h"
37 #include "spdk/util.h"
39 #include <linux/nbd.h>
41 #include "nbd_internal.h"
42 #include "spdk_internal/log.h"
44 struct rpc_start_nbd_disk
{
50 free_rpc_start_nbd_disk(struct rpc_start_nbd_disk
*req
)
53 free(req
->nbd_device
);
56 static const struct spdk_json_object_decoder rpc_start_nbd_disk_decoders
[] = {
57 {"bdev_name", offsetof(struct rpc_start_nbd_disk
, bdev_name
), spdk_json_decode_string
},
58 {"nbd_device", offsetof(struct rpc_start_nbd_disk
, nbd_device
), spdk_json_decode_string
},
62 spdk_rpc_start_nbd_disk(struct spdk_jsonrpc_request
*request
,
63 const struct spdk_json_val
*params
)
65 struct rpc_start_nbd_disk req
= {};
66 struct spdk_json_write_ctx
*w
;
67 struct spdk_nbd_disk
*nbd
;
69 if (spdk_json_decode_object(params
, rpc_start_nbd_disk_decoders
,
70 SPDK_COUNTOF(rpc_start_nbd_disk_decoders
),
72 SPDK_ERRLOG("spdk_json_decode_object failed\n");
76 if (req
.nbd_device
== NULL
|| req
.bdev_name
== NULL
) {
80 /* make sure nbd_device is not registered */
81 nbd
= spdk_nbd_disk_find_by_nbd_path(req
.nbd_device
);
86 nbd
= spdk_nbd_start(req
.bdev_name
, req
.nbd_device
);
91 w
= spdk_jsonrpc_begin_result(request
);
93 free_rpc_start_nbd_disk(&req
);
97 spdk_json_write_string(w
, req
.nbd_device
);
98 spdk_jsonrpc_end_result(request
, w
);
99 free_rpc_start_nbd_disk(&req
);
103 free_rpc_start_nbd_disk(&req
);
104 spdk_jsonrpc_send_error_response(request
, SPDK_JSONRPC_ERROR_INVALID_PARAMS
, "Invalid parameters");
107 SPDK_RPC_REGISTER("start_nbd_disk", spdk_rpc_start_nbd_disk
, SPDK_RPC_RUNTIME
)
109 struct rpc_stop_nbd_disk
{
114 free_rpc_stop_nbd_disk(struct rpc_stop_nbd_disk
*req
)
116 free(req
->nbd_device
);
119 static const struct spdk_json_object_decoder rpc_stop_nbd_disk_decoders
[] = {
120 {"nbd_device", offsetof(struct rpc_stop_nbd_disk
, nbd_device
), spdk_json_decode_string
},
123 struct nbd_disconnect_arg
{
124 struct spdk_jsonrpc_request
*request
;
125 struct spdk_nbd_disk
*nbd
;
129 nbd_disconnect_thread(void *arg
)
131 struct nbd_disconnect_arg
*thd_arg
= arg
;
132 struct spdk_json_write_ctx
*w
;
134 spdk_unaffinitize_thread();
136 nbd_disconnect(thd_arg
->nbd
);
138 w
= spdk_jsonrpc_begin_result(thd_arg
->request
);
143 spdk_json_write_bool(w
, true);
144 spdk_jsonrpc_end_result(thd_arg
->request
, w
);
152 spdk_rpc_stop_nbd_disk(struct spdk_jsonrpc_request
*request
,
153 const struct spdk_json_val
*params
)
155 struct rpc_stop_nbd_disk req
= {};
156 struct spdk_nbd_disk
*nbd
;
158 struct nbd_disconnect_arg
*thd_arg
= NULL
;
161 if (spdk_json_decode_object(params
, rpc_stop_nbd_disk_decoders
,
162 SPDK_COUNTOF(rpc_stop_nbd_disk_decoders
),
164 SPDK_ERRLOG("spdk_json_decode_object failed\n");
165 spdk_jsonrpc_send_error_response(request
, SPDK_JSONRPC_ERROR_INVALID_PARAMS
,
166 "Invalid parameters");
170 if (req
.nbd_device
== NULL
) {
171 spdk_jsonrpc_send_error_response(request
, SPDK_JSONRPC_ERROR_INVALID_PARAMS
,
172 "Invalid parameters");
176 /* make sure nbd_device is registered */
177 nbd
= spdk_nbd_disk_find_by_nbd_path(req
.nbd_device
);
179 spdk_jsonrpc_send_error_response(request
, SPDK_JSONRPC_ERROR_INVALID_PARAMS
,
180 "Invalid parameters");
185 * thd_arg should be freed by created thread
186 * if thread is created successfully.
188 thd_arg
= malloc(sizeof(*thd_arg
));
190 SPDK_ERRLOG("could not allocate nbd disconnect thread arg\n");
191 spdk_jsonrpc_send_error_response(request
, SPDK_JSONRPC_ERROR_INTERNAL_ERROR
, "Out of memory");
195 thd_arg
->request
= request
;
199 * NBD ioctl of disconnect will block until data are flushed.
200 * Create separate thread to execute it.
202 rc
= pthread_create(&tid
, NULL
, nbd_disconnect_thread
, (void *)thd_arg
);
204 SPDK_ERRLOG("could not create nbd disconnect thread: %s\n", spdk_strerror(rc
));
205 spdk_jsonrpc_send_error_response(request
, SPDK_JSONRPC_ERROR_INTERNAL_ERROR
, spdk_strerror(rc
));
210 rc
= pthread_detach(tid
);
212 SPDK_ERRLOG("could not detach nbd disconnect thread: %s\n", spdk_strerror(rc
));
217 free_rpc_stop_nbd_disk(&req
);
220 SPDK_RPC_REGISTER("stop_nbd_disk", spdk_rpc_stop_nbd_disk
, SPDK_RPC_RUNTIME
)
223 spdk_rpc_dump_nbd_info(struct spdk_json_write_ctx
*w
,
224 struct spdk_nbd_disk
*nbd
)
226 spdk_json_write_object_begin(w
);
228 spdk_json_write_name(w
, "nbd_device");
229 spdk_json_write_string(w
, spdk_nbd_disk_get_nbd_path(nbd
));
231 spdk_json_write_name(w
, "bdev_name");
232 spdk_json_write_string(w
, spdk_nbd_disk_get_bdev_name(nbd
));
234 spdk_json_write_object_end(w
);
237 struct rpc_get_nbd_disks
{
242 free_rpc_get_nbd_disks(struct rpc_get_nbd_disks
*r
)
247 static const struct spdk_json_object_decoder rpc_get_nbd_disks_decoders
[] = {
248 {"nbd_device", offsetof(struct rpc_get_nbd_disks
, nbd_device
), spdk_json_decode_string
, true},
252 spdk_rpc_get_nbd_disks(struct spdk_jsonrpc_request
*request
,
253 const struct spdk_json_val
*params
)
255 struct rpc_get_nbd_disks req
= {};
256 struct spdk_json_write_ctx
*w
;
257 struct spdk_nbd_disk
*nbd
= NULL
;
259 if (params
!= NULL
) {
260 if (spdk_json_decode_object(params
, rpc_get_nbd_disks_decoders
,
261 SPDK_COUNTOF(rpc_get_nbd_disks_decoders
),
263 SPDK_ERRLOG("spdk_json_decode_object failed\n");
267 if (req
.nbd_device
) {
268 nbd
= spdk_nbd_disk_find_by_nbd_path(req
.nbd_device
);
270 SPDK_ERRLOG("nbd device '%s' does not exist\n", req
.nbd_device
);
274 free_rpc_get_nbd_disks(&req
);
278 w
= spdk_jsonrpc_begin_result(request
);
283 spdk_json_write_array_begin(w
);
286 spdk_rpc_dump_nbd_info(w
, nbd
);
288 for (nbd
= spdk_nbd_disk_first(); nbd
!= NULL
; nbd
= spdk_nbd_disk_next(nbd
)) {
289 spdk_rpc_dump_nbd_info(w
, nbd
);
293 spdk_json_write_array_end(w
);
295 spdk_jsonrpc_end_result(request
, w
);
300 spdk_jsonrpc_send_error_response(request
, SPDK_JSONRPC_ERROR_INVALID_PARAMS
, "Invalid parameters");
302 free_rpc_get_nbd_disks(&req
);
304 SPDK_RPC_REGISTER("get_nbd_disks", spdk_rpc_get_nbd_disks
, SPDK_RPC_RUNTIME
)