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_atomic.h>
19 #include <rte_cycles.h>
21 #include <rte_malloc.h>
22 #include <rte_byteorder.h>
23 #include <rte_string_fns.h>
25 #include "vhost_blk.h"
29 vhost_strcpy_pad(void *dst, const char *src, size_t size, int pad)
35 memcpy(dst, src, len);
36 memset((char *)dst + len, pad, size - len);
38 memcpy(dst, src, size);
43 vhost_bdev_blk_readwrite(struct vhost_block_dev *bdev,
44 struct vhost_blk_task *task,
45 uint64_t lba_512, __rte_unused uint32_t xfer_len)
51 offset = lba_512 * 512;
53 for (i = 0; i < task->iovs_cnt; i++) {
54 if (task->dxfer_dir == BLK_DIR_TO_DEV)
55 memcpy(bdev->data + offset, task->iovs[i].iov_base,
56 task->iovs[i].iov_len);
58 memcpy(task->iovs[i].iov_base, bdev->data + offset,
59 task->iovs[i].iov_len);
60 offset += task->iovs[i].iov_len;
61 nbytes += task->iovs[i].iov_len;
68 vhost_bdev_process_blk_commands(struct vhost_block_dev *bdev,
69 struct vhost_blk_task *task)
73 if (unlikely(task->data_len > (bdev->blockcnt * bdev->blocklen))) {
74 fprintf(stderr, "read or write beyond capacity\n");
75 return VIRTIO_BLK_S_UNSUPP;
78 switch (task->req->type) {
80 if (unlikely(task->data_len == 0 ||
81 (task->data_len & (512 - 1)) != 0)) {
83 "%s - passed IO buffer is not multiple of 512b"
84 "(req_idx = %"PRIu16").\n",
85 task->req->type ? "WRITE" : "READ",
87 return VIRTIO_BLK_S_UNSUPP;
90 task->dxfer_dir = BLK_DIR_FROM_DEV;
91 vhost_bdev_blk_readwrite(bdev, task,
92 task->req->sector, task->data_len);
94 case VIRTIO_BLK_T_OUT:
95 if (unlikely(task->data_len == 0 ||
96 (task->data_len & (512 - 1)) != 0)) {
98 "%s - passed IO buffer is not multiple of 512b"
99 "(req_idx = %"PRIu16").\n",
100 task->req->type ? "WRITE" : "READ",
102 return VIRTIO_BLK_S_UNSUPP;
105 if (task->readtype) {
106 fprintf(stderr, "type isn't right\n");
107 return VIRTIO_BLK_S_IOERR;
109 task->dxfer_dir = BLK_DIR_TO_DEV;
110 vhost_bdev_blk_readwrite(bdev, task,
111 task->req->sector, task->data_len);
113 case VIRTIO_BLK_T_GET_ID:
114 if (!task->iovs_cnt || task->data_len)
115 return VIRTIO_BLK_S_UNSUPP;
116 used_len = min(VIRTIO_BLK_ID_BYTES, task->data_len);
117 vhost_strcpy_pad(task->iovs[0].iov_base,
118 bdev->product_name, used_len, ' ');
121 fprintf(stderr, "unsupported cmd\n");
122 return VIRTIO_BLK_S_UNSUPP;
125 return VIRTIO_BLK_S_OK;