numam-dpdk/examples/vhost_blk/blk.c
Jin Yu 91d3e2d429 examples/vhost_blk: refactor to increase readability
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>
2020-05-05 15:54:26 +02:00

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;
}