]> git.proxmox.com Git - ceph.git/blame - ceph/src/spdk/module/bdev/virtio/bdev_virtio_rpc.c
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / spdk / module / bdev / virtio / bdev_virtio_rpc.c
CommitLineData
11fdf7f2
TL
1/*-
2 * BSD LICENSE
3 *
4 * Copyright (c) Intel Corporation.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
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
16 * distribution.
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.
20 *
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.
32 */
33
34#include "spdk/stdinc.h"
35
36#include "spdk/string.h"
37#include "spdk/rpc.h"
38#include "spdk/util.h"
39#include "spdk_internal/log.h"
40
41#include "bdev_virtio.h"
42
43#define SPDK_VIRTIO_USER_DEFAULT_VQ_COUNT 1
44#define SPDK_VIRTIO_USER_DEFAULT_QUEUE_SIZE 512
45
11fdf7f2
TL
46struct rpc_remove_virtio_dev {
47 char *name;
48};
49
50static const struct spdk_json_object_decoder rpc_remove_virtio_dev[] = {
51 {"name", offsetof(struct rpc_remove_virtio_dev, name), spdk_json_decode_string },
52};
53
11fdf7f2 54static void
f67539c2 55rpc_bdev_virtio_detach_controller_cb(void *ctx, int errnum)
11fdf7f2
TL
56{
57 struct spdk_jsonrpc_request *request = ctx;
58 struct spdk_json_write_ctx *w;
59
60 if (errnum != 0) {
61 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
62 spdk_strerror(-errnum));
63 return;
64 }
65
66 w = spdk_jsonrpc_begin_result(request);
11fdf7f2
TL
67 spdk_json_write_bool(w, true);
68 spdk_jsonrpc_end_result(request, w);
69}
70
71static void
f67539c2
TL
72rpc_bdev_virtio_detach_controller(struct spdk_jsonrpc_request *request,
73 const struct spdk_json_val *params)
11fdf7f2
TL
74{
75 struct rpc_remove_virtio_dev req = {NULL};
f67539c2 76 int rc = 0;
11fdf7f2
TL
77
78 if (spdk_json_decode_object(params, rpc_remove_virtio_dev,
79 SPDK_COUNTOF(rpc_remove_virtio_dev),
80 &req)) {
f67539c2
TL
81 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
82 "spdk_json_decode_object failed");
83 goto cleanup;
11fdf7f2
TL
84 }
85
f67539c2 86 rc = bdev_virtio_blk_dev_remove(req.name, rpc_bdev_virtio_detach_controller_cb, request);
11fdf7f2 87 if (rc == -ENODEV) {
f67539c2 88 rc = bdev_virtio_scsi_dev_remove(req.name, rpc_bdev_virtio_detach_controller_cb, request);
11fdf7f2
TL
89 }
90
91 if (rc != 0) {
f67539c2 92 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
11fdf7f2
TL
93 }
94
f67539c2 95cleanup:
11fdf7f2
TL
96 free(req.name);
97}
f67539c2
TL
98SPDK_RPC_REGISTER("bdev_virtio_detach_controller",
99 rpc_bdev_virtio_detach_controller, SPDK_RPC_RUNTIME)
100SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_virtio_detach_controller, remove_virtio_bdev)
11fdf7f2
TL
101
102static void
f67539c2
TL
103rpc_bdev_virtio_scsi_get_devices(struct spdk_jsonrpc_request *request,
104 const struct spdk_json_val *params)
11fdf7f2
TL
105{
106 struct spdk_json_write_ctx *w;
107
108 if (params != NULL) {
109 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
f67539c2 110 "bdev_virtio_scsi_get_devices requires no parameters");
11fdf7f2
TL
111 return;
112 }
113
114 w = spdk_jsonrpc_begin_result(request);
11fdf7f2
TL
115 bdev_virtio_scsi_dev_list(w);
116 spdk_jsonrpc_end_result(request, w);
117}
f67539c2
TL
118SPDK_RPC_REGISTER("bdev_virtio_scsi_get_devices",
119 rpc_bdev_virtio_scsi_get_devices, SPDK_RPC_RUNTIME)
120SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_virtio_scsi_get_devices, get_virtio_scsi_devs)
11fdf7f2 121
f67539c2 122struct rpc_bdev_virtio_attach_controller_ctx {
11fdf7f2
TL
123 char *name;
124 char *trtype;
125 char *traddr;
126 char *dev_type;
127 uint32_t vq_count;
128 uint32_t vq_size;
129 struct spdk_jsonrpc_request *request;
130};
131
f67539c2
TL
132static const struct spdk_json_object_decoder rpc_bdev_virtio_attach_controller_ctx[] = {
133 {"name", offsetof(struct rpc_bdev_virtio_attach_controller_ctx, name), spdk_json_decode_string },
134 {"trtype", offsetof(struct rpc_bdev_virtio_attach_controller_ctx, trtype), spdk_json_decode_string },
135 {"traddr", offsetof(struct rpc_bdev_virtio_attach_controller_ctx, traddr), spdk_json_decode_string },
136 {"dev_type", offsetof(struct rpc_bdev_virtio_attach_controller_ctx, dev_type), spdk_json_decode_string },
137 {"vq_count", offsetof(struct rpc_bdev_virtio_attach_controller_ctx, vq_count), spdk_json_decode_uint32, true },
138 {"vq_size", offsetof(struct rpc_bdev_virtio_attach_controller_ctx, vq_size), spdk_json_decode_uint32, true },
11fdf7f2
TL
139};
140
141static void
f67539c2 142free_rpc_bdev_virtio_attach_controller_ctx(struct rpc_bdev_virtio_attach_controller_ctx *req)
11fdf7f2
TL
143{
144 free(req->name);
145 free(req->trtype);
146 free(req->traddr);
147 free(req->dev_type);
148 free(req);
149}
150
151static void
f67539c2 152rpc_create_virtio_dev_cb(void *ctx, int result, struct spdk_bdev **bdevs, size_t cnt)
11fdf7f2 153{
f67539c2 154 struct rpc_bdev_virtio_attach_controller_ctx *req = ctx;
11fdf7f2
TL
155 struct spdk_json_write_ctx *w;
156 size_t i;
157
158 if (result) {
159 spdk_jsonrpc_send_error_response(req->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
160 spdk_strerror(-result));
f67539c2 161 free_rpc_bdev_virtio_attach_controller_ctx(req);
11fdf7f2
TL
162 return;
163 }
164
165 w = spdk_jsonrpc_begin_result(req->request);
f67539c2 166 spdk_json_write_array_begin(w);
11fdf7f2 167
f67539c2
TL
168 for (i = 0; i < cnt; i++) {
169 spdk_json_write_string(w, spdk_bdev_get_name(bdevs[i]));
11fdf7f2
TL
170 }
171
f67539c2
TL
172 spdk_json_write_array_end(w);
173 spdk_jsonrpc_end_result(req->request, w);
174
175 free_rpc_bdev_virtio_attach_controller_ctx(ctx);
11fdf7f2
TL
176}
177
178static void
f67539c2
TL
179rpc_bdev_virtio_attach_controller(struct spdk_jsonrpc_request *request,
180 const struct spdk_json_val *params)
11fdf7f2 181{
f67539c2 182 struct rpc_bdev_virtio_attach_controller_ctx *req;
11fdf7f2
TL
183 struct spdk_bdev *bdev;
184 struct spdk_pci_addr pci_addr;
185 bool pci;
186 int rc;
187
188 req = calloc(1, sizeof(*req));
189 if (!req) {
190 SPDK_ERRLOG("calloc() failed\n");
f67539c2 191 spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM));
11fdf7f2
TL
192 return;
193 }
194
f67539c2
TL
195 if (spdk_json_decode_object(params, rpc_bdev_virtio_attach_controller_ctx,
196 SPDK_COUNTOF(rpc_bdev_virtio_attach_controller_ctx),
11fdf7f2 197 req)) {
f67539c2
TL
198 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
199 "spdk_json_decode_object failed");
200 goto cleanup;
11fdf7f2
TL
201 }
202
203 if (strcmp(req->trtype, "pci") == 0) {
204 if (req->vq_count != 0 || req->vq_size != 0) {
205 SPDK_ERRLOG("VQ count or size is not allowed for PCI transport type\n");
f67539c2 206 spdk_jsonrpc_send_error_response(request, EINVAL,
11fdf7f2 207 "vq_count or vq_size is not allowed for PCI transport type.");
f67539c2 208 goto cleanup;
11fdf7f2
TL
209 }
210
211 if (spdk_pci_addr_parse(&pci_addr, req->traddr) != 0) {
212 SPDK_ERRLOG("Invalid PCI address '%s'\n", req->traddr);
f67539c2
TL
213 spdk_jsonrpc_send_error_response_fmt(request, EINVAL, "Invalid PCI address '%s'", req->traddr);
214 goto cleanup;
11fdf7f2
TL
215 }
216
217 pci = true;
218 } else if (strcmp(req->trtype, "user") == 0) {
219 req->vq_count = req->vq_count == 0 ? SPDK_VIRTIO_USER_DEFAULT_VQ_COUNT : req->vq_count;
220 req->vq_size = req->vq_size == 0 ? SPDK_VIRTIO_USER_DEFAULT_QUEUE_SIZE : req->vq_size;
221 pci = false;
222 } else {
223 SPDK_ERRLOG("Invalid trtype '%s'\n", req->trtype);
f67539c2
TL
224 spdk_jsonrpc_send_error_response_fmt(request, EINVAL, "Invalid trtype '%s'", req->trtype);
225 goto cleanup;
11fdf7f2
TL
226 }
227
228 req->request = request;
229 if (strcmp(req->dev_type, "blk") == 0) {
230 if (pci) {
231 bdev = bdev_virtio_pci_blk_dev_create(req->name, &pci_addr);
232 } else {
233 bdev = bdev_virtio_user_blk_dev_create(req->name, req->traddr, req->vq_count, req->vq_size);
234 }
235
236 /* Virtio blk doesn't use callback so call it manually to send result. */
237 rc = bdev ? 0 : -EINVAL;
f67539c2 238 rpc_create_virtio_dev_cb(req, rc, &bdev, bdev ? 1 : 0);
11fdf7f2
TL
239 } else if (strcmp(req->dev_type, "scsi") == 0) {
240 if (pci) {
f67539c2 241 rc = bdev_virtio_pci_scsi_dev_create(req->name, &pci_addr, rpc_create_virtio_dev_cb, req);
11fdf7f2
TL
242 } else {
243 rc = bdev_virtio_user_scsi_dev_create(req->name, req->traddr, req->vq_count, req->vq_size,
f67539c2 244 rpc_create_virtio_dev_cb, req);
11fdf7f2
TL
245 }
246
247 if (rc < 0) {
248 /* In case of error callback is not called so do it manually to send result. */
f67539c2 249 rpc_create_virtio_dev_cb(req, rc, NULL, 0);
11fdf7f2
TL
250 }
251 } else {
252 SPDK_ERRLOG("Invalid dev_type '%s'\n", req->dev_type);
f67539c2
TL
253 spdk_jsonrpc_send_error_response_fmt(request, EINVAL, "Invalid dev_type '%s'", req->dev_type);
254 goto cleanup;
11fdf7f2
TL
255 }
256
257 return;
f67539c2
TL
258
259cleanup:
260 free_rpc_bdev_virtio_attach_controller_ctx(req);
11fdf7f2 261}
f67539c2
TL
262SPDK_RPC_REGISTER("bdev_virtio_attach_controller",
263 rpc_bdev_virtio_attach_controller, SPDK_RPC_RUNTIME);
264SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_virtio_attach_controller, construct_virtio_dev)