d043e2db87
To support reconnecting after restart or crash, VDUSE backend might need to resubmit inflight I/Os. This stores the metadata such as the index of inflight I/O's descriptors to a shm file so that VDUSE backend can restore them during reconnecting. Signed-off-by: Xie Yongji <xieyongji@bytedance.com> Message-Id: <20220523084611.91-9-xieyongji@bytedance.com> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
248 lines
6.3 KiB
C
248 lines
6.3 KiB
C
/*
|
|
* VDUSE (vDPA Device in Userspace) library
|
|
*
|
|
* Copyright (C) 2022 Bytedance Inc. and/or its affiliates. All rights reserved.
|
|
*
|
|
* Author:
|
|
* Xie Yongji <xieyongji@bytedance.com>
|
|
*
|
|
* This work is licensed under the terms of the GNU GPL, version 2 or
|
|
* later. See the COPYING file in the top-level directory.
|
|
*/
|
|
|
|
#ifndef LIBVDUSE_H
|
|
#define LIBVDUSE_H
|
|
|
|
#include <stdint.h>
|
|
#include <sys/uio.h>
|
|
|
|
#define VIRTQUEUE_MAX_SIZE 1024
|
|
|
|
/* VDUSE device structure */
|
|
typedef struct VduseDev VduseDev;
|
|
|
|
/* Virtqueue structure */
|
|
typedef struct VduseVirtq VduseVirtq;
|
|
|
|
/* Some operation of VDUSE backend */
|
|
typedef struct VduseOps {
|
|
/* Called when virtqueue can be processed */
|
|
void (*enable_queue)(VduseDev *dev, VduseVirtq *vq);
|
|
/* Called when virtqueue processing should be stopped */
|
|
void (*disable_queue)(VduseDev *dev, VduseVirtq *vq);
|
|
} VduseOps;
|
|
|
|
/* Describing elements of the I/O buffer */
|
|
typedef struct VduseVirtqElement {
|
|
/* Descriptor table index */
|
|
unsigned int index;
|
|
/* Number of physically-contiguous device-readable descriptors */
|
|
unsigned int out_num;
|
|
/* Number of physically-contiguous device-writable descriptors */
|
|
unsigned int in_num;
|
|
/* Array to store physically-contiguous device-writable descriptors */
|
|
struct iovec *in_sg;
|
|
/* Array to store physically-contiguous device-readable descriptors */
|
|
struct iovec *out_sg;
|
|
} VduseVirtqElement;
|
|
|
|
|
|
/**
|
|
* vduse_get_virtio_features:
|
|
*
|
|
* Get supported virtio features
|
|
*
|
|
* Returns: supported feature bits
|
|
*/
|
|
uint64_t vduse_get_virtio_features(void);
|
|
|
|
/**
|
|
* vduse_queue_get_dev:
|
|
* @vq: specified virtqueue
|
|
*
|
|
* Get corresponding VDUSE device from the virtqueue.
|
|
*
|
|
* Returns: a pointer to VDUSE device on success, NULL on failure.
|
|
*/
|
|
VduseDev *vduse_queue_get_dev(VduseVirtq *vq);
|
|
|
|
/**
|
|
* vduse_queue_get_fd:
|
|
* @vq: specified virtqueue
|
|
*
|
|
* Get the kick fd for the virtqueue.
|
|
*
|
|
* Returns: file descriptor on success, -1 on failure.
|
|
*/
|
|
int vduse_queue_get_fd(VduseVirtq *vq);
|
|
|
|
/**
|
|
* vduse_queue_pop:
|
|
* @vq: specified virtqueue
|
|
* @sz: the size of struct to return (must be >= VduseVirtqElement)
|
|
*
|
|
* Pop an element from virtqueue available ring.
|
|
*
|
|
* Returns: a pointer to a structure containing VduseVirtqElement on success,
|
|
* NULL on failure.
|
|
*/
|
|
void *vduse_queue_pop(VduseVirtq *vq, size_t sz);
|
|
|
|
/**
|
|
* vduse_queue_push:
|
|
* @vq: specified virtqueue
|
|
* @elem: pointer to VduseVirtqElement returned by vduse_queue_pop()
|
|
* @len: length in bytes to write
|
|
*
|
|
* Push an element to virtqueue used ring.
|
|
*/
|
|
void vduse_queue_push(VduseVirtq *vq, const VduseVirtqElement *elem,
|
|
unsigned int len);
|
|
/**
|
|
* vduse_queue_notify:
|
|
* @vq: specified virtqueue
|
|
*
|
|
* Request to notify the queue.
|
|
*/
|
|
void vduse_queue_notify(VduseVirtq *vq);
|
|
|
|
/**
|
|
* vduse_dev_get_priv:
|
|
* @dev: VDUSE device
|
|
*
|
|
* Get the private pointer passed to vduse_dev_create().
|
|
*
|
|
* Returns: private pointer on success, NULL on failure.
|
|
*/
|
|
void *vduse_dev_get_priv(VduseDev *dev);
|
|
|
|
/**
|
|
* vduse_dev_get_queue:
|
|
* @dev: VDUSE device
|
|
* @index: virtqueue index
|
|
*
|
|
* Get the specified virtqueue.
|
|
*
|
|
* Returns: a pointer to the virtqueue on success, NULL on failure.
|
|
*/
|
|
VduseVirtq *vduse_dev_get_queue(VduseDev *dev, int index);
|
|
|
|
/**
|
|
* vduse_dev_get_fd:
|
|
* @dev: VDUSE device
|
|
*
|
|
* Get the control message fd for the VDUSE device.
|
|
*
|
|
* Returns: file descriptor on success, -1 on failure.
|
|
*/
|
|
int vduse_dev_get_fd(VduseDev *dev);
|
|
|
|
/**
|
|
* vduse_dev_handler:
|
|
* @dev: VDUSE device
|
|
*
|
|
* Used to process the control message.
|
|
*
|
|
* Returns: file descriptor on success, -errno on failure.
|
|
*/
|
|
int vduse_dev_handler(VduseDev *dev);
|
|
|
|
/**
|
|
* vduse_dev_update_config:
|
|
* @dev: VDUSE device
|
|
* @size: the size to write to configuration space
|
|
* @offset: the offset from the beginning of configuration space
|
|
* @buffer: the buffer used to write from
|
|
*
|
|
* Update device configuration space and inject a config interrupt.
|
|
*
|
|
* Returns: 0 on success, -errno on failure.
|
|
*/
|
|
int vduse_dev_update_config(VduseDev *dev, uint32_t size,
|
|
uint32_t offset, char *buffer);
|
|
|
|
/**
|
|
* vduse_dev_setup_queue:
|
|
* @dev: VDUSE device
|
|
* @index: virtqueue index
|
|
* @max_size: the max size of virtqueue
|
|
*
|
|
* Setup the specified virtqueue.
|
|
*
|
|
* Returns: 0 on success, -errno on failure.
|
|
*/
|
|
int vduse_dev_setup_queue(VduseDev *dev, int index, int max_size);
|
|
|
|
/**
|
|
* vduse_set_reconnect_log_file:
|
|
* @dev: VDUSE device
|
|
* @file: filename of reconnect log
|
|
*
|
|
* Specify the file to store log for reconnecting. It should
|
|
* be called before vduse_dev_setup_queue().
|
|
*
|
|
* Returns: 0 on success, -errno on failure.
|
|
*/
|
|
int vduse_set_reconnect_log_file(VduseDev *dev, const char *filename);
|
|
|
|
/**
|
|
* vduse_dev_create_by_fd:
|
|
* @fd: passed file descriptor
|
|
* @num_queues: the number of virtqueues
|
|
* @ops: the operation of VDUSE backend
|
|
* @priv: private pointer
|
|
*
|
|
* Create VDUSE device from a passed file descriptor.
|
|
*
|
|
* Returns: pointer to VDUSE device on success, NULL on failure.
|
|
*/
|
|
VduseDev *vduse_dev_create_by_fd(int fd, uint16_t num_queues,
|
|
const VduseOps *ops, void *priv);
|
|
|
|
/**
|
|
* vduse_dev_create_by_name:
|
|
* @name: VDUSE device name
|
|
* @num_queues: the number of virtqueues
|
|
* @ops: the operation of VDUSE backend
|
|
* @priv: private pointer
|
|
*
|
|
* Create VDUSE device on /dev/vduse/$NAME.
|
|
*
|
|
* Returns: pointer to VDUSE device on success, NULL on failure.
|
|
*/
|
|
VduseDev *vduse_dev_create_by_name(const char *name, uint16_t num_queues,
|
|
const VduseOps *ops, void *priv);
|
|
|
|
/**
|
|
* vduse_dev_create:
|
|
* @name: VDUSE device name
|
|
* @device_id: virtio device id
|
|
* @vendor_id: virtio vendor id
|
|
* @features: virtio features
|
|
* @num_queues: the number of virtqueues
|
|
* @config_size: the size of the configuration space
|
|
* @config: the buffer of the configuration space
|
|
* @ops: the operation of VDUSE backend
|
|
* @priv: private pointer
|
|
*
|
|
* Create VDUSE device.
|
|
*
|
|
* Returns: pointer to VDUSE device on success, NULL on failure.
|
|
*/
|
|
VduseDev *vduse_dev_create(const char *name, uint32_t device_id,
|
|
uint32_t vendor_id, uint64_t features,
|
|
uint16_t num_queues, uint32_t config_size,
|
|
char *config, const VduseOps *ops, void *priv);
|
|
|
|
/**
|
|
* vduse_dev_destroy:
|
|
* @dev: VDUSE device
|
|
*
|
|
* Destroy the VDUSE device.
|
|
*
|
|
* Returns: 0 on success, -errno on failure.
|
|
*/
|
|
int vduse_dev_destroy(VduseDev *dev);
|
|
|
|
#endif
|