1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright (C) 2017 Intel Corporation.
3 * All rights reserved.
4 */
5
6 #include "spdk/stdinc.h"
7
8 #include "spdk/bdev.h"
9 #include "spdk/endian.h"
10 #include "spdk/env.h"
11 #include "spdk/thread.h"
12 #include "spdk/string.h"
13 #include "spdk/util.h"
14 #include "spdk/json.h"
15
16 #include "spdk_internal/assert.h"
17 #include "spdk/bdev_module.h"
18 #include "spdk/log.h"
19 #include "spdk_internal/virtio.h"
20 #include "spdk_internal/vhost_user.h"
21
22 #include <linux/virtio_blk.h>
23 #include <linux/virtio_ids.h>
24
25 #include "bdev_virtio.h"
26
27 struct virtio_blk_dev {
28 struct virtio_dev vdev;
29 struct spdk_bdev bdev;
30 bool readonly;
31 bool unmap;
32 };
33
34 struct virtio_blk_io_ctx {
35 struct iovec iov_req;
36 struct iovec iov_resp;
37 struct iovec iov_unmap;
38 struct virtio_blk_outhdr req;
39 struct virtio_blk_discard_write_zeroes unmap;
40 uint8_t resp;
41 };
42
43 struct bdev_virtio_blk_io_channel {
44 struct virtio_dev *vdev;
45
46 /** Virtqueue exclusively assigned to this channel. */
47 struct virtqueue *vq;
48
49 /** Virtio response poller. */
50 struct spdk_poller *poller;
51 };
52
53 /* Features desired/implemented by this driver. */
54 #define VIRTIO_BLK_DEV_SUPPORTED_FEATURES \
55 (1ULL << VIRTIO_BLK_F_SIZE_MAX | \
56 1ULL << VIRTIO_BLK_F_SEG_MAX | \
57 1ULL << VIRTIO_BLK_F_BLK_SIZE | \
58 1ULL << VIRTIO_BLK_F_TOPOLOGY | \
59 1ULL << VIRTIO_BLK_F_MQ | \
60 1ULL << VIRTIO_BLK_F_RO | \
61 1ULL << VIRTIO_BLK_F_DISCARD | \
62 1ULL << VIRTIO_RING_F_EVENT_IDX)
63
64 /* 10 sec for max poll period */
65 #define VIRTIO_BLK_HOTPLUG_POLL_PERIOD_MAX 10000000ULL
66 /* Default poll period is 100ms */
67 #define VIRTIO_BLK_HOTPLUG_POLL_PERIOD_DEFAULT 100000ULL
68
69 static struct spdk_poller *g_blk_hotplug_poller = NULL;
70 static int g_blk_hotplug_fd = -1;
71
72 static int bdev_virtio_initialize(void);
73 static int bdev_virtio_blk_get_ctx_size(void);
74
75 static struct spdk_bdev_module virtio_blk_if = {
76 .name = "virtio_blk",
77 .module_init = bdev_virtio_initialize,
78 .get_ctx_size = bdev_virtio_blk_get_ctx_size,
79 };
80
81 SPDK_BDEV_MODULE_REGISTER(virtio_blk, &virtio_blk_if)
82
83 static int bdev_virtio_blk_ch_create_cb(void *io_device, void *ctx_buf);
84 static void bdev_virtio_blk_ch_destroy_cb(void *io_device, void *ctx_buf);
85
86 static struct virtio_blk_io_ctx *
bdev_virtio_blk_init_io_vreq(struct spdk_io_channel * ch,struct spdk_bdev_io * bdev_io)87 bdev_virtio_blk_init_io_vreq(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io)
88 {
89 struct virtio_blk_outhdr *req;
90 uint8_t *resp;
91 struct virtio_blk_discard_write_zeroes *desc;
92
93 struct virtio_blk_io_ctx *io_ctx = (struct virtio_blk_io_ctx *)bdev_io->driver_ctx;
94
95 req = &io_ctx->req;
96 resp = &io_ctx->resp;
97 desc = &io_ctx->unmap;
98
99 io_ctx->iov_req.iov_base = req;
100 io_ctx->iov_req.iov_len = sizeof(*req);
101
102 io_ctx->iov_resp.iov_base = resp;
103 io_ctx->iov_resp.iov_len = sizeof(*resp);
104
105 io_ctx->iov_unmap.iov_base = desc;
106 io_ctx->iov_unmap.iov_len = sizeof(*desc);
107
108 memset(req, 0, sizeof(*req));
109 return io_ctx;
110 }
111
112 static void
bdev_virtio_blk_send_io(struct spdk_io_channel * ch,struct spdk_bdev_io * bdev_io)113 bdev_virtio_blk_send_io(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io)
114 {
115 struct bdev_virtio_blk_io_channel *virtio_channel = spdk_io_channel_get_ctx(ch);
116 struct virtqueue *vq = virtio_channel->vq;
117 struct virtio_blk_io_ctx *io_ctx = (struct virtio_blk_io_ctx *)bdev_io->driver_ctx;
118 int rc;
119
120 rc = virtqueue_req_start(vq, bdev_io, bdev_io->u.bdev.iovcnt + 2);
121 if (rc == -ENOMEM) {
122 spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_NOMEM);
123 return;
124 } else if (rc != 0) {
125 spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED);
126 return;
127 }
128
129 virtqueue_req_add_iovs(vq, &io_ctx->iov_req, 1, SPDK_VIRTIO_DESC_RO);
130 if (bdev_io->type == SPDK_BDEV_IO_TYPE_UNMAP) {
131 virtqueue_req_add_iovs(vq, &io_ctx->iov_unmap, 1, SPDK_VIRTIO_DESC_RO);
132 } else {
133 virtqueue_req_add_iovs(vq, bdev_io->u.bdev.iovs, bdev_io->u.bdev.iovcnt,
134 bdev_io->type == SPDK_BDEV_IO_TYPE_READ ?
135 SPDK_VIRTIO_DESC_WR : SPDK_VIRTIO_DESC_RO);
136 }
137 virtqueue_req_add_iovs(vq, &io_ctx->iov_resp, 1, SPDK_VIRTIO_DESC_WR);
138
139 virtqueue_req_flush(vq);
140 }
141
142 static void
bdev_virtio_command(struct spdk_io_channel * ch,struct spdk_bdev_io * bdev_io)143 bdev_virtio_command(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io)
144 {
145 struct virtio_blk_io_ctx *io_ctx = bdev_virtio_blk_init_io_vreq(ch, bdev_io);
146 struct virtio_blk_outhdr *req = &io_ctx->req;
147 struct virtio_blk_discard_write_zeroes *desc = &io_ctx->unmap;
148
149 if (bdev_io->type == SPDK_BDEV_IO_TYPE_READ) {
150 req->type = VIRTIO_BLK_T_IN;
151 } else if (bdev_io->type == SPDK_BDEV_IO_TYPE_WRITE) {
152 req->type = VIRTIO_BLK_T_OUT;
153 } else if (bdev_io->type == SPDK_BDEV_IO_TYPE_UNMAP) {
154 req->type = VIRTIO_BLK_T_DISCARD;
155 desc->sector = bdev_io->u.bdev.offset_blocks *
156 spdk_bdev_get_block_size(bdev_io->bdev) / 512;
157 desc->num_sectors = bdev_io->u.bdev.num_blocks *
158 spdk_bdev_get_block_size(bdev_io->bdev) / 512;
159 desc->flags = 0;
160 }
161
162 req->sector = bdev_io->u.bdev.offset_blocks *
163 spdk_bdev_get_block_size(bdev_io->bdev) / 512;
164
165 bdev_virtio_blk_send_io(ch, bdev_io);
166 }
167
168 static void
bdev_virtio_get_buf_cb(struct spdk_io_channel * ch,struct spdk_bdev_io * bdev_io,bool success)169 bdev_virtio_get_buf_cb(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io,
170 bool success)
171 {
172 if (!success) {
173 spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED);
174 return;
175 }
176
177 bdev_virtio_command(ch, bdev_io);
178 }
179
180 static int
_bdev_virtio_submit_request(struct spdk_io_channel * ch,struct spdk_bdev_io * bdev_io)181 _bdev_virtio_submit_request(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io)
182 {
183 struct virtio_blk_dev *bvdev = bdev_io->bdev->ctxt;
184
185 switch (bdev_io->type) {
186 case SPDK_BDEV_IO_TYPE_READ:
187 spdk_bdev_io_get_buf(bdev_io, bdev_virtio_get_buf_cb,
188 bdev_io->u.bdev.num_blocks * bdev_io->bdev->blocklen);
189 return 0;
190 case SPDK_BDEV_IO_TYPE_WRITE:
191 if (bvdev->readonly) {
192 spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED);
193 } else {
194 bdev_virtio_command(ch, bdev_io);
195 }
196 return 0;
197 case SPDK_BDEV_IO_TYPE_RESET:
198 spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_SUCCESS);
199 return 0;
200 case SPDK_BDEV_IO_TYPE_UNMAP:
201 if (bvdev->unmap) {
202 bdev_virtio_command(ch, bdev_io);
203 } else {
204 spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED);
205 }
206 return 0;
207 case SPDK_BDEV_IO_TYPE_FLUSH:
208 default:
209 return -1;
210 }
211
212 SPDK_UNREACHABLE();
213 }
214
215 static void
bdev_virtio_submit_request(struct spdk_io_channel * ch,struct spdk_bdev_io * bdev_io)216 bdev_virtio_submit_request(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io)
217 {
218 if (_bdev_virtio_submit_request(ch, bdev_io) < 0) {
219 spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED);
220 }
221 }
222
223 static bool
bdev_virtio_io_type_supported(void * ctx,enum spdk_bdev_io_type io_type)224 bdev_virtio_io_type_supported(void *ctx, enum spdk_bdev_io_type io_type)
225 {
226 struct virtio_blk_dev *bvdev = ctx;
227
228 switch (io_type) {
229 case SPDK_BDEV_IO_TYPE_READ:
230 case SPDK_BDEV_IO_TYPE_RESET:
231 return true;
232 case SPDK_BDEV_IO_TYPE_WRITE:
233 return !bvdev->readonly;
234 case SPDK_BDEV_IO_TYPE_UNMAP:
235 return bvdev->unmap;
236 case SPDK_BDEV_IO_TYPE_FLUSH:
237 default:
238 return false;
239 }
240 }
241
242 static struct spdk_io_channel *
bdev_virtio_get_io_channel(void * ctx)243 bdev_virtio_get_io_channel(void *ctx)
244 {
245 struct virtio_blk_dev *bvdev = ctx;
246
247 return spdk_get_io_channel(bvdev);
248 }
249
250 static void
virtio_blk_dev_unregister_cb(void * io_device)251 virtio_blk_dev_unregister_cb(void *io_device)
252 {
253 struct virtio_blk_dev *bvdev = io_device;
254 struct virtio_dev *vdev = &bvdev->vdev;
255
256 virtio_dev_stop(vdev);
257 virtio_dev_destruct(vdev);
258 spdk_bdev_destruct_done(&bvdev->bdev, 0);
259 free(bvdev);
260 }
261
262 static int
bdev_virtio_disk_destruct(void * ctx)263 bdev_virtio_disk_destruct(void *ctx)
264 {
265 struct virtio_blk_dev *bvdev = ctx;
266
267 spdk_io_device_unregister(bvdev, virtio_blk_dev_unregister_cb);
268 return 1;
269 }
270
271 int
bdev_virtio_blk_dev_remove(const char * name,bdev_virtio_remove_cb cb_fn,void * cb_arg)272 bdev_virtio_blk_dev_remove(const char *name, bdev_virtio_remove_cb cb_fn, void *cb_arg)
273 {
274 return spdk_bdev_unregister_by_name(name, &virtio_blk_if, cb_fn, cb_arg);
275 }
276
277 static int
bdev_virtio_dump_json_config(void * ctx,struct spdk_json_write_ctx * w)278 bdev_virtio_dump_json_config(void *ctx, struct spdk_json_write_ctx *w)
279 {
280 struct virtio_blk_dev *bvdev = ctx;
281
282 virtio_dev_dump_json_info(&bvdev->vdev, w);
283 return 0;
284 }
285
286 static void
bdev_virtio_write_config_json(struct spdk_bdev * bdev,struct spdk_json_write_ctx * w)287 bdev_virtio_write_config_json(struct spdk_bdev *bdev, struct spdk_json_write_ctx *w)
288 {
289 struct virtio_blk_dev *bvdev = bdev->ctxt;
290
291 spdk_json_write_object_begin(w);
292
293 spdk_json_write_named_string(w, "method", "bdev_virtio_attach_controller");
294
295 spdk_json_write_named_object_begin(w, "params");
296 spdk_json_write_named_string(w, "name", bvdev->vdev.name);
297 spdk_json_write_named_string(w, "dev_type", "blk");
298
299 /* Write transport specific parameters. */
300 bvdev->vdev.backend_ops->write_json_config(&bvdev->vdev, w);
301
302 spdk_json_write_object_end(w);
303
304 spdk_json_write_object_end(w);
305 }
306
307 static const struct spdk_bdev_fn_table virtio_fn_table = {
308 .destruct = bdev_virtio_disk_destruct,
309 .submit_request = bdev_virtio_submit_request,
310 .io_type_supported = bdev_virtio_io_type_supported,
311 .get_io_channel = bdev_virtio_get_io_channel,
312 .dump_info_json = bdev_virtio_dump_json_config,
313 .write_config_json = bdev_virtio_write_config_json,
314 };
315
316 static void
bdev_virtio_io_cpl(struct spdk_bdev_io * bdev_io)317 bdev_virtio_io_cpl(struct spdk_bdev_io *bdev_io)
318 {
319 struct virtio_blk_io_ctx *io_ctx = (struct virtio_blk_io_ctx *)bdev_io->driver_ctx;
320
321 spdk_bdev_io_complete(bdev_io, io_ctx->resp == VIRTIO_BLK_S_OK ?
322 SPDK_BDEV_IO_STATUS_SUCCESS : SPDK_BDEV_IO_STATUS_FAILED);
323 }
324
325 static int
bdev_virtio_poll(void * arg)326 bdev_virtio_poll(void *arg)
327 {
328 struct bdev_virtio_blk_io_channel *ch = arg;
329 void *io[32];
330 uint32_t io_len[32];
331 uint16_t i, cnt;
332
333 cnt = virtio_recv_pkts(ch->vq, io, io_len, SPDK_COUNTOF(io));
334 for (i = 0; i < cnt; ++i) {
335 bdev_virtio_io_cpl(io[i]);
336 }
337
338 return cnt;
339 }
340
341 static int
bdev_virtio_blk_ch_create_cb(void * io_device,void * ctx_buf)342 bdev_virtio_blk_ch_create_cb(void *io_device, void *ctx_buf)
343 {
344 struct virtio_blk_dev *bvdev = io_device;
345 struct virtio_dev *vdev = &bvdev->vdev;
346 struct bdev_virtio_blk_io_channel *ch = ctx_buf;
347 struct virtqueue *vq;
348 int32_t queue_idx;
349
350 queue_idx = virtio_dev_find_and_acquire_queue(vdev, 0);
351 if (queue_idx < 0) {
352 SPDK_ERRLOG("Couldn't get an unused queue for the io_channel.\n");
353 return -1;
354 }
355
356 vq = vdev->vqs[queue_idx];
357
358 ch->vdev = vdev;
359 ch->vq = vq;
360
361 ch->poller = SPDK_POLLER_REGISTER(bdev_virtio_poll, ch, 0);
362 return 0;
363 }
364
365 static void
bdev_virtio_blk_ch_destroy_cb(void * io_device,void * ctx_buf)366 bdev_virtio_blk_ch_destroy_cb(void *io_device, void *ctx_buf)
367 {
368 struct virtio_blk_dev *bvdev = io_device;
369 struct virtio_dev *vdev = &bvdev->vdev;
370 struct bdev_virtio_blk_io_channel *ch = ctx_buf;
371 struct virtqueue *vq = ch->vq;
372
373 spdk_poller_unregister(&ch->poller);
374 virtio_dev_release_queue(vdev, vq->vq_queue_index);
375 }
376
377 static int
virtio_blk_dev_init(struct virtio_blk_dev * bvdev,uint16_t max_queues)378 virtio_blk_dev_init(struct virtio_blk_dev *bvdev, uint16_t max_queues)
379 {
380 struct virtio_dev *vdev = &bvdev->vdev;
381 struct spdk_bdev *bdev = &bvdev->bdev;
382 uint64_t capacity, num_blocks;
383 uint32_t block_size, size_max, seg_max;
384 uint16_t host_max_queues;
385 int rc;
386
387 if (virtio_dev_has_feature(vdev, VIRTIO_BLK_F_BLK_SIZE)) {
388 rc = virtio_dev_read_dev_config(vdev, offsetof(struct virtio_blk_config, blk_size),
389 &block_size, sizeof(block_size));
390 if (rc) {
391 SPDK_ERRLOG("%s: config read failed: %s\n", vdev->name, spdk_strerror(-rc));
392 return rc;
393 }
394
395 if (block_size == 0 || block_size % 512 != 0) {
396 SPDK_ERRLOG("%s: invalid block size (%"PRIu32"). Must be "
397 "a multiple of 512.\n", vdev->name, block_size);
398 return -EIO;
399 }
400 } else {
401 block_size = 512;
402 }
403
404 rc = virtio_dev_read_dev_config(vdev, offsetof(struct virtio_blk_config, capacity),
405 &capacity, sizeof(capacity));
406 if (rc) {
407 SPDK_ERRLOG("%s: config read failed: %s\n", vdev->name, spdk_strerror(-rc));
408 return rc;
409 }
410
411 /* `capacity` is a number of 512-byte sectors. */
412 num_blocks = capacity * 512 / block_size;
413 if (num_blocks == 0) {
414 SPDK_ERRLOG("%s: size too small (size: %"PRIu64", blocksize: %"PRIu32").\n",
415 vdev->name, capacity * 512, block_size);
416 return -EIO;
417 }
418
419 if ((capacity * 512) % block_size != 0) {
420 SPDK_WARNLOG("%s: size has been rounded down to the nearest block size boundary. "
421 "(block size: %"PRIu32", previous size: %"PRIu64", new size: %"PRIu64")\n",
422 vdev->name, block_size, capacity * 512, num_blocks * block_size);
423 }
424
425 if (virtio_dev_has_feature(vdev, VIRTIO_BLK_F_MQ)) {
426 rc = virtio_dev_read_dev_config(vdev, offsetof(struct virtio_blk_config, num_queues),
427 &host_max_queues, sizeof(host_max_queues));
428 if (rc) {
429 SPDK_ERRLOG("%s: config read failed: %s\n", vdev->name, spdk_strerror(-rc));
430 return rc;
431 }
432 } else {
433 host_max_queues = 1;
434 }
435
436 if (virtio_dev_has_feature(vdev, VIRTIO_BLK_F_SIZE_MAX)) {
437 rc = virtio_dev_read_dev_config(vdev, offsetof(struct virtio_blk_config, size_max),
438 &size_max, sizeof(size_max));
439 if (rc) {
440 SPDK_ERRLOG("%s: config read failed: %s\n", vdev->name, spdk_strerror(-rc));
441 return rc;
442 }
443
444 if (spdk_unlikely(size_max < block_size)) {
445 SPDK_WARNLOG("%s: minimum segment size is set to block size %u forcefully.\n",
446 vdev->name, block_size);
447 size_max = block_size;
448 }
449
450 bdev->max_segment_size = size_max;
451 }
452
453 if (virtio_dev_has_feature(vdev, VIRTIO_BLK_F_SEG_MAX)) {
454 rc = virtio_dev_read_dev_config(vdev, offsetof(struct virtio_blk_config, seg_max),
455 &seg_max, sizeof(seg_max));
456 if (rc) {
457 SPDK_ERRLOG("%s: config read failed: %s\n", vdev->name, spdk_strerror(-rc));
458 return rc;
459 }
460
461 if (spdk_unlikely(seg_max == 0)) {
462 SPDK_ERRLOG("%s: virtio blk SEG_MAX can't be 0\n", vdev->name);
463 return -EINVAL;
464 }
465
466 bdev->max_num_segments = seg_max;
467 }
468
469 if (virtio_dev_has_feature(vdev, VIRTIO_BLK_F_RO)) {
470 bvdev->readonly = true;
471 }
472
473 if (virtio_dev_has_feature(vdev, VIRTIO_BLK_F_DISCARD)) {
474 bvdev->unmap = true;
475 }
476
477 if (max_queues == 0) {
478 SPDK_ERRLOG("%s: requested 0 request queues (%"PRIu16" available).\n",
479 vdev->name, host_max_queues);
480 return -EINVAL;
481 }
482
483 if (max_queues > host_max_queues) {
484 SPDK_WARNLOG("%s: requested %"PRIu16" request queues "
485 "but only %"PRIu16" available.\n",
486 vdev->name, max_queues, host_max_queues);
487 max_queues = host_max_queues;
488 }
489
490 /* bdev is tied with the virtio device; we can reuse the name */
491 bdev->name = vdev->name;
492 rc = virtio_dev_start(vdev, max_queues, 0);
493 if (rc != 0) {
494 return rc;
495 }
496
497 bdev->product_name = "VirtioBlk Disk";
498 bdev->write_cache = 0;
499 bdev->blocklen = block_size;
500 bdev->blockcnt = num_blocks;
501
502 bdev->ctxt = bvdev;
503 bdev->fn_table = &virtio_fn_table;
504 bdev->module = &virtio_blk_if;
505
506 spdk_io_device_register(bvdev, bdev_virtio_blk_ch_create_cb,
507 bdev_virtio_blk_ch_destroy_cb,
508 sizeof(struct bdev_virtio_blk_io_channel),
509 vdev->name);
510
511 rc = spdk_bdev_register(bdev);
512 if (rc) {
513 SPDK_ERRLOG("Failed to register bdev name=%s\n", bdev->name);
514 spdk_io_device_unregister(bvdev, NULL);
515 virtio_dev_stop(vdev);
516 return rc;
517 }
518
519 return 0;
520 }
521
522 static struct virtio_blk_dev *
virtio_pci_blk_dev_create(const char * name,struct virtio_pci_ctx * pci_ctx)523 virtio_pci_blk_dev_create(const char *name, struct virtio_pci_ctx *pci_ctx)
524 {
525 static int pci_dev_counter = 0;
526 struct virtio_blk_dev *bvdev;
527 struct virtio_dev *vdev;
528 char *default_name = NULL;
529 uint16_t num_queues;
530 int rc;
531
532 bvdev = calloc(1, sizeof(*bvdev));
533 if (bvdev == NULL) {
534 SPDK_ERRLOG("virtio device calloc failed\n");
535 return NULL;
536 }
537 vdev = &bvdev->vdev;
538
539 if (name == NULL) {
540 default_name = spdk_sprintf_alloc("VirtioBlk%"PRIu32, pci_dev_counter++);
541 if (default_name == NULL) {
542 free(vdev);
543 return NULL;
544 }
545 name = default_name;
546 }
547
548 rc = virtio_pci_dev_init(vdev, name, pci_ctx);
549 free(default_name);
550
551 if (rc != 0) {
552 free(bvdev);
553 return NULL;
554 }
555
556 rc = virtio_dev_reset(vdev, VIRTIO_BLK_DEV_SUPPORTED_FEATURES);
557 if (rc != 0) {
558 goto fail;
559 }
560
561 /* TODO: add a way to limit usable virtqueues */
562 if (virtio_dev_has_feature(vdev, VIRTIO_BLK_F_MQ)) {
563 rc = virtio_dev_read_dev_config(vdev, offsetof(struct virtio_blk_config, num_queues),
564 &num_queues, sizeof(num_queues));
565 if (rc) {
566 SPDK_ERRLOG("%s: config read failed: %s\n", vdev->name, spdk_strerror(-rc));
567 goto fail;
568 }
569 } else {
570 num_queues = 1;
571 }
572
573 rc = virtio_blk_dev_init(bvdev, num_queues);
574 if (rc != 0) {
575 goto fail;
576 }
577
578 return bvdev;
579
580 fail:
581 vdev->ctx = NULL;
582 virtio_dev_destruct(vdev);
583 free(bvdev);
584 return NULL;
585 }
586
587 static struct virtio_blk_dev *
virtio_user_blk_dev_create(const char * name,const char * path,uint16_t num_queues,uint32_t queue_size)588 virtio_user_blk_dev_create(const char *name, const char *path,
589 uint16_t num_queues, uint32_t queue_size)
590 {
591 struct virtio_blk_dev *bvdev;
592 uint64_t feature_bits;
593 int rc;
594
595 bvdev = calloc(1, sizeof(*bvdev));
596 if (bvdev == NULL) {
597 SPDK_ERRLOG("calloc failed for virtio device %s: %s\n", name, path);
598 return NULL;
599 }
600
601 rc = virtio_user_dev_init(&bvdev->vdev, name, path, queue_size);
602 if (rc != 0) {
603 SPDK_ERRLOG("Failed to create virito device %s: %s\n", name, path);
604 free(bvdev);
605 return NULL;
606 }
607
608 feature_bits = VIRTIO_BLK_DEV_SUPPORTED_FEATURES;
609 feature_bits |= (1ULL << VHOST_USER_F_PROTOCOL_FEATURES);
610 rc = virtio_dev_reset(&bvdev->vdev, feature_bits);
611 if (rc != 0) {
612 virtio_dev_destruct(&bvdev->vdev);
613 free(bvdev);
614 return NULL;
615 }
616
617 rc = virtio_blk_dev_init(bvdev, num_queues);
618 if (rc != 0) {
619 virtio_dev_destruct(&bvdev->vdev);
620 free(bvdev);
621 return NULL;
622 }
623
624 return bvdev;
625 }
626
627 struct bdev_virtio_pci_dev_create_ctx {
628 const char *name;
629 struct virtio_blk_dev *ret;
630 };
631
632 static int
bdev_virtio_pci_blk_dev_create_cb(struct virtio_pci_ctx * pci_ctx,void * ctx)633 bdev_virtio_pci_blk_dev_create_cb(struct virtio_pci_ctx *pci_ctx, void *ctx)
634 {
635 struct bdev_virtio_pci_dev_create_ctx *create_ctx = ctx;
636
637 create_ctx->ret = virtio_pci_blk_dev_create(create_ctx->name, pci_ctx);
638 if (create_ctx->ret == NULL) {
639 return -1;
640 }
641
642 return 0;
643 }
644
645 struct spdk_bdev *
bdev_virtio_pci_blk_dev_create(const char * name,struct spdk_pci_addr * pci_addr)646 bdev_virtio_pci_blk_dev_create(const char *name, struct spdk_pci_addr *pci_addr)
647 {
648 struct bdev_virtio_pci_dev_create_ctx create_ctx;
649
650 create_ctx.name = name;
651 create_ctx.ret = NULL;
652
653 virtio_pci_dev_attach(bdev_virtio_pci_blk_dev_create_cb, &create_ctx,
654 VIRTIO_ID_BLOCK, pci_addr);
655
656 if (create_ctx.ret == NULL) {
657 return NULL;
658 }
659
660 return &create_ctx.ret->bdev;
661 }
662
663 static int
bdev_virtio_pci_blk_monitor(void * arg)664 bdev_virtio_pci_blk_monitor(void *arg)
665 {
666 const char *vdev_name;
667 struct bdev_virtio_pci_dev_create_ctx create_ctx;
668
669 while ((vdev_name = virtio_pci_dev_event_process(g_blk_hotplug_fd, VIRTIO_ID_BLOCK)) != NULL) {
670 bdev_virtio_blk_dev_remove(vdev_name, NULL, NULL);
671 }
672
673 /* Enumerate virtio pci_blk device */
674 memset(&create_ctx, 0, sizeof(create_ctx));
675 virtio_pci_dev_enumerate(bdev_virtio_pci_blk_dev_create_cb, &create_ctx,
676 VIRTIO_ID_BLOCK);
677
678 return SPDK_POLLER_BUSY;
679 }
680
681 int
bdev_virtio_pci_blk_set_hotplug(bool enabled,uint64_t period_us)682 bdev_virtio_pci_blk_set_hotplug(bool enabled, uint64_t period_us)
683 {
684 if (enabled == true && !spdk_process_is_primary()) {
685 return -EPERM;
686 }
687
688 if (g_blk_hotplug_poller) {
689 close(g_blk_hotplug_fd);
690 spdk_poller_unregister(&g_blk_hotplug_poller);
691 }
692
693 if (!enabled) {
694 return 0;
695 }
696
697 g_blk_hotplug_fd = spdk_pci_event_listen();
698 if (g_blk_hotplug_fd < 0) {
699 return g_blk_hotplug_fd;
700 }
701
702 period_us = period_us ? period_us : VIRTIO_BLK_HOTPLUG_POLL_PERIOD_DEFAULT;
703 period_us = spdk_min(period_us, VIRTIO_BLK_HOTPLUG_POLL_PERIOD_MAX);
704 g_blk_hotplug_poller = spdk_poller_register(bdev_virtio_pci_blk_monitor, NULL, period_us);
705 if (!g_blk_hotplug_poller) {
706 close(g_blk_hotplug_fd);
707 return -1;
708 }
709
710 return 0;
711 }
712
713 static int
bdev_virtio_initialize(void)714 bdev_virtio_initialize(void)
715 {
716 return 0;
717 }
718
719 struct spdk_bdev *
bdev_virtio_user_blk_dev_create(const char * name,const char * path,unsigned num_queues,unsigned queue_size)720 bdev_virtio_user_blk_dev_create(const char *name, const char *path,
721 unsigned num_queues, unsigned queue_size)
722 {
723 struct virtio_blk_dev *bvdev;
724
725 bvdev = virtio_user_blk_dev_create(name, path, num_queues, queue_size);
726 if (bvdev == NULL) {
727 return NULL;
728 }
729
730 return &bvdev->bdev;
731 }
732
733 struct spdk_bdev *
bdev_virtio_vfio_user_blk_dev_create(const char * name,const char * path)734 bdev_virtio_vfio_user_blk_dev_create(const char *name, const char *path)
735 {
736 struct virtio_blk_dev *bvdev;
737 uint16_t num_queues = 0;
738 int rc;
739
740 bvdev = calloc(1, sizeof(*bvdev));
741 if (bvdev == NULL) {
742 SPDK_ERRLOG("calloc failed for virtio device %s: %s\n", name, path);
743 return NULL;
744 }
745
746 rc = virtio_vfio_user_dev_init(&bvdev->vdev, name, path);
747 if (rc != 0) {
748 SPDK_ERRLOG("Failed to create %s as virtio device\n", path);
749 free(bvdev);
750 return NULL;
751 }
752
753 rc = virtio_dev_reset(&bvdev->vdev, VIRTIO_BLK_DEV_SUPPORTED_FEATURES);
754 if (rc != 0) {
755 SPDK_ERRLOG("Failed to reset %s as virtio device\n", path);
756 virtio_dev_destruct(&bvdev->vdev);
757 free(bvdev);
758 return NULL;
759 }
760
761 if (virtio_dev_has_feature(&bvdev->vdev, VIRTIO_BLK_F_MQ)) {
762 rc = virtio_dev_read_dev_config(&bvdev->vdev, offsetof(struct virtio_blk_config, num_queues),
763 &num_queues, sizeof(num_queues));
764 if (rc) {
765 SPDK_ERRLOG("%s: config read failed: %s\n", name, spdk_strerror(-rc));
766 virtio_dev_destruct(&bvdev->vdev);
767 free(bvdev);
768 return NULL;
769 }
770 } else {
771 num_queues = 1;
772 }
773
774 rc = virtio_blk_dev_init(bvdev, num_queues);
775 if (rc != 0) {
776 SPDK_ERRLOG("Failed to initialize %s as virtio device\n", path);
777 virtio_dev_destruct(&bvdev->vdev);
778 free(bvdev);
779 return NULL;
780 }
781
782 return &bvdev->bdev;
783 }
784
785 static int
bdev_virtio_blk_get_ctx_size(void)786 bdev_virtio_blk_get_ctx_size(void)
787 {
788 return sizeof(struct virtio_blk_io_ctx);
789 }
790
791 SPDK_LOG_REGISTER_COMPONENT(virtio_blk)
792