1
2
3
4
5
6
7
8
9
10#include <stdio.h>
11#include <stdint.h>
12#include <unistd.h>
13#include <assert.h>
14#include <ctype.h>
15#include <string.h>
16#include <stddef.h>
17
18#include <rte_atomic.h>
19#include <rte_cycles.h>
20#include <rte_log.h>
21#include <rte_malloc.h>
22#include <rte_byteorder.h>
23#include <rte_string_fns.h>
24
25#include "vhost_blk.h"
26#include "blk_spec.h"
27
28static void
29vhost_strcpy_pad(void *dst, const char *src, size_t size, int pad)
30{
31 size_t len;
32
33 len = strlen(src);
34 if (len < size) {
35 memcpy(dst, src, len);
36 memset((char *)dst + len, pad, size - len);
37 } else {
38 memcpy(dst, src, size);
39 }
40}
41
42static int
43vhost_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)
46{
47 uint32_t i;
48 uint64_t offset;
49 uint32_t nbytes = 0;
50
51 offset = lba_512 * 512;
52
53
54
55
56 for (i = 1; i < task->iovs_cnt - 1; i++) {
57 if (task->dxfer_dir == BLK_DIR_TO_DEV)
58 memcpy(bdev->data + offset, task->iovs[i].iov_base,
59 task->iovs[i].iov_len);
60 else
61 memcpy(task->iovs[i].iov_base, bdev->data + offset,
62 task->iovs[i].iov_len);
63 offset += task->iovs[i].iov_len;
64 nbytes += task->iovs[i].iov_len;
65 }
66
67 return nbytes;
68}
69
70int
71vhost_bdev_process_blk_commands(struct vhost_block_dev *bdev,
72 struct vhost_blk_task *task)
73{
74 size_t used_len;
75
76 if (unlikely(task->data_len > (bdev->blockcnt * bdev->blocklen))) {
77 fprintf(stderr, "read or write beyond capacity\n");
78 return VIRTIO_BLK_S_UNSUPP;
79 }
80
81 switch (task->req->type) {
82 case VIRTIO_BLK_T_IN:
83 if (unlikely(task->data_len == 0 ||
84 (task->data_len & (512 - 1)) != 0)) {
85 fprintf(stderr,
86 "%s - passed IO buffer is not multiple of 512b"
87 "(req_idx = %"PRIu16").\n",
88 task->req->type ? "WRITE" : "READ",
89 task->req_idx);
90 return VIRTIO_BLK_S_UNSUPP;
91 }
92
93 task->dxfer_dir = BLK_DIR_FROM_DEV;
94 vhost_bdev_blk_readwrite(bdev, task,
95 task->req->sector, task->data_len);
96 break;
97 case VIRTIO_BLK_T_OUT:
98 if (unlikely(task->data_len == 0 ||
99 (task->data_len & (512 - 1)) != 0)) {
100 fprintf(stderr,
101 "%s - passed IO buffer is not multiple of 512b"
102 "(req_idx = %"PRIu16").\n",
103 task->req->type ? "WRITE" : "READ",
104 task->req_idx);
105 return VIRTIO_BLK_S_UNSUPP;
106 }
107
108 task->dxfer_dir = BLK_DIR_TO_DEV;
109 vhost_bdev_blk_readwrite(bdev, task,
110 task->req->sector, task->data_len);
111 break;
112 case VIRTIO_BLK_T_GET_ID:
113 if (!task->iovs_cnt || task->data_len)
114 return VIRTIO_BLK_S_UNSUPP;
115 used_len = RTE_MIN((size_t)VIRTIO_BLK_ID_BYTES, task->data_len);
116 vhost_strcpy_pad(task->iovs[0].iov_base,
117 bdev->product_name, used_len, ' ');
118 break;
119 default:
120 fprintf(stderr, "unsupported cmd\n");
121 return VIRTIO_BLK_S_UNSUPP;
122 }
123
124 return VIRTIO_BLK_S_OK;
125}
126