1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2010-2019 Intel Corporation
6 * This work is largely based on the "vhost-user-blk" implementation by
7 * SPDK(https://github.com/spdk/spdk).
18 #include <rte_cycles.h>
20 #include <rte_malloc.h>
21 #include <rte_byteorder.h>
22 #include <rte_string_fns.h>
24 #include "vhost_blk.h"
28 vhost_strcpy_pad(void *dst, const char *src, size_t size, int pad)
34 memcpy(dst, src, len);
35 memset((char *)dst + len, pad, size - len);
37 memcpy(dst, src, size);
42 vhost_bdev_blk_readwrite(struct vhost_block_dev *bdev,
43 struct vhost_blk_task *task,
44 uint64_t lba_512, __rte_unused uint32_t xfer_len)
50 offset = lba_512 * 512;
52 /* iovs[0] is the head and iovs[iovs_cnt - 1] is the tail
53 * Middle is the data range
55 for (i = 1; i < task->iovs_cnt - 1; i++) {
56 if (task->dxfer_dir == BLK_DIR_TO_DEV)
57 memcpy(bdev->data + offset, task->iovs[i].iov_base,
58 task->iovs[i].iov_len);
60 memcpy(task->iovs[i].iov_base, bdev->data + offset,
61 task->iovs[i].iov_len);
62 offset += task->iovs[i].iov_len;
63 nbytes += task->iovs[i].iov_len;
70 vhost_bdev_process_blk_commands(struct vhost_block_dev *bdev,
71 struct vhost_blk_task *task)
75 if (unlikely(task->data_len > (bdev->blockcnt * bdev->blocklen))) {
76 fprintf(stderr, "read or write beyond capacity\n");
77 return VIRTIO_BLK_S_UNSUPP;
80 switch (task->req->type) {
82 if (unlikely(task->data_len == 0 ||
83 (task->data_len & (512 - 1)) != 0)) {
85 "%s - passed IO buffer is not multiple of 512b"
86 "(req_idx = %"PRIu16").\n",
87 task->req->type ? "WRITE" : "READ",
89 return VIRTIO_BLK_S_UNSUPP;
92 task->dxfer_dir = BLK_DIR_FROM_DEV;
93 vhost_bdev_blk_readwrite(bdev, task,
94 task->req->sector, task->data_len);
96 case VIRTIO_BLK_T_OUT:
97 if (unlikely(task->data_len == 0 ||
98 (task->data_len & (512 - 1)) != 0)) {
100 "%s - passed IO buffer is not multiple of 512b"
101 "(req_idx = %"PRIu16").\n",
102 task->req->type ? "WRITE" : "READ",
104 return VIRTIO_BLK_S_UNSUPP;
107 task->dxfer_dir = BLK_DIR_TO_DEV;
108 vhost_bdev_blk_readwrite(bdev, task,
109 task->req->sector, task->data_len);
111 case VIRTIO_BLK_T_GET_ID:
112 if (!task->iovs_cnt || task->data_len)
113 return VIRTIO_BLK_S_UNSUPP;
114 used_len = RTE_MIN((size_t)VIRTIO_BLK_ID_BYTES, task->data_len);
115 vhost_strcpy_pad(task->iovs[0].iov_base,
116 bdev->product_name, used_len, ' ');
119 fprintf(stderr, "unsupported cmd\n");
120 return VIRTIO_BLK_S_UNSUPP;
123 return VIRTIO_BLK_S_OK;