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