91d3e2d429
Refactor the code and make it easier to read. It's useful for understanding the inflight APIs and how packed ring works. Update the RST because the packed ring patch has been merged to QEMU master and ring_packed parameter changes to packed. Signed-off-by: Jin Yu <jin.yu@intel.com> Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
126 lines
2.9 KiB
C
126 lines
2.9 KiB
C
/* SPDX-License-Identifier: BSD-3-Clause
|
|
* Copyright(c) 2010-2019 Intel Corporation
|
|
*/
|
|
|
|
/**
|
|
* This work is largely based on the "vhost-user-blk" implementation by
|
|
* SPDK(https://github.com/spdk/spdk).
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdint.h>
|
|
#include <unistd.h>
|
|
#include <assert.h>
|
|
#include <ctype.h>
|
|
#include <string.h>
|
|
#include <stddef.h>
|
|
|
|
#include <rte_atomic.h>
|
|
#include <rte_cycles.h>
|
|
#include <rte_log.h>
|
|
#include <rte_malloc.h>
|
|
#include <rte_byteorder.h>
|
|
#include <rte_string_fns.h>
|
|
|
|
#include "vhost_blk.h"
|
|
#include "blk_spec.h"
|
|
|
|
static void
|
|
vhost_strcpy_pad(void *dst, const char *src, size_t size, int pad)
|
|
{
|
|
size_t len;
|
|
|
|
len = strlen(src);
|
|
if (len < size) {
|
|
memcpy(dst, src, len);
|
|
memset((char *)dst + len, pad, size - len);
|
|
} else {
|
|
memcpy(dst, src, size);
|
|
}
|
|
}
|
|
|
|
static int
|
|
vhost_bdev_blk_readwrite(struct vhost_block_dev *bdev,
|
|
struct vhost_blk_task *task,
|
|
uint64_t lba_512, __rte_unused uint32_t xfer_len)
|
|
{
|
|
uint32_t i;
|
|
uint64_t offset;
|
|
uint32_t nbytes = 0;
|
|
|
|
offset = lba_512 * 512;
|
|
|
|
/* iovs[0] is the head and iovs[iovs_cnt - 1] is the tail
|
|
* Middle is the data range
|
|
*/
|
|
for (i = 1; i < task->iovs_cnt - 1; i++) {
|
|
if (task->dxfer_dir == BLK_DIR_TO_DEV)
|
|
memcpy(bdev->data + offset, task->iovs[i].iov_base,
|
|
task->iovs[i].iov_len);
|
|
else
|
|
memcpy(task->iovs[i].iov_base, bdev->data + offset,
|
|
task->iovs[i].iov_len);
|
|
offset += task->iovs[i].iov_len;
|
|
nbytes += task->iovs[i].iov_len;
|
|
}
|
|
|
|
return nbytes;
|
|
}
|
|
|
|
int
|
|
vhost_bdev_process_blk_commands(struct vhost_block_dev *bdev,
|
|
struct vhost_blk_task *task)
|
|
{
|
|
size_t used_len;
|
|
|
|
if (unlikely(task->data_len > (bdev->blockcnt * bdev->blocklen))) {
|
|
fprintf(stderr, "read or write beyond capacity\n");
|
|
return VIRTIO_BLK_S_UNSUPP;
|
|
}
|
|
|
|
switch (task->req->type) {
|
|
case VIRTIO_BLK_T_IN:
|
|
if (unlikely(task->data_len == 0 ||
|
|
(task->data_len & (512 - 1)) != 0)) {
|
|
fprintf(stderr,
|
|
"%s - passed IO buffer is not multiple of 512b"
|
|
"(req_idx = %"PRIu16").\n",
|
|
task->req->type ? "WRITE" : "READ",
|
|
task->req_idx);
|
|
return VIRTIO_BLK_S_UNSUPP;
|
|
}
|
|
|
|
task->dxfer_dir = BLK_DIR_FROM_DEV;
|
|
vhost_bdev_blk_readwrite(bdev, task,
|
|
task->req->sector, task->data_len);
|
|
break;
|
|
case VIRTIO_BLK_T_OUT:
|
|
if (unlikely(task->data_len == 0 ||
|
|
(task->data_len & (512 - 1)) != 0)) {
|
|
fprintf(stderr,
|
|
"%s - passed IO buffer is not multiple of 512b"
|
|
"(req_idx = %"PRIu16").\n",
|
|
task->req->type ? "WRITE" : "READ",
|
|
task->req_idx);
|
|
return VIRTIO_BLK_S_UNSUPP;
|
|
}
|
|
|
|
task->dxfer_dir = BLK_DIR_TO_DEV;
|
|
vhost_bdev_blk_readwrite(bdev, task,
|
|
task->req->sector, task->data_len);
|
|
break;
|
|
case VIRTIO_BLK_T_GET_ID:
|
|
if (!task->iovs_cnt || task->data_len)
|
|
return VIRTIO_BLK_S_UNSUPP;
|
|
used_len = RTE_MIN((size_t)VIRTIO_BLK_ID_BYTES, task->data_len);
|
|
vhost_strcpy_pad(task->iovs[0].iov_base,
|
|
bdev->product_name, used_len, ' ');
|
|
break;
|
|
default:
|
|
fprintf(stderr, "unsupported cmd\n");
|
|
return VIRTIO_BLK_S_UNSUPP;
|
|
}
|
|
|
|
return VIRTIO_BLK_S_OK;
|
|
}
|