mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-12-17 21:26:13 -07:00
vhost-user: Support transferring inflight buffer between qemu and backend
This patch introduces two new messages VHOST_USER_GET_INFLIGHT_FD and VHOST_USER_SET_INFLIGHT_FD to support transferring a shared buffer between qemu and backend. Firstly, qemu uses VHOST_USER_GET_INFLIGHT_FD to get the shared buffer from backend. Then qemu should send it back through VHOST_USER_SET_INFLIGHT_FD each time we start vhost-user. This shared buffer is used to track inflight I/O by backend. Qemu should retrieve a new one when vm reset. Signed-off-by: Xie Yongji <xieyongji@baidu.com> Signed-off-by: Chai Wen <chaiwen@baidu.com> Signed-off-by: Zhang Yu <zhangyu31@baidu.com> Message-Id: <20190228085355.9614-2-xieyongji@baidu.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
parent
1b8fff5758
commit
5ad204bf2a
5 changed files with 516 additions and 0 deletions
|
|
@ -56,6 +56,7 @@ enum VhostUserProtocolFeature {
|
|||
VHOST_USER_PROTOCOL_F_CONFIG = 9,
|
||||
VHOST_USER_PROTOCOL_F_SLAVE_SEND_FD = 10,
|
||||
VHOST_USER_PROTOCOL_F_HOST_NOTIFIER = 11,
|
||||
VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD = 12,
|
||||
VHOST_USER_PROTOCOL_F_MAX
|
||||
};
|
||||
|
||||
|
|
@ -93,6 +94,8 @@ typedef enum VhostUserRequest {
|
|||
VHOST_USER_POSTCOPY_ADVISE = 28,
|
||||
VHOST_USER_POSTCOPY_LISTEN = 29,
|
||||
VHOST_USER_POSTCOPY_END = 30,
|
||||
VHOST_USER_GET_INFLIGHT_FD = 31,
|
||||
VHOST_USER_SET_INFLIGHT_FD = 32,
|
||||
VHOST_USER_MAX
|
||||
} VhostUserRequest;
|
||||
|
||||
|
|
@ -151,6 +154,13 @@ typedef struct VhostUserVringArea {
|
|||
uint64_t offset;
|
||||
} VhostUserVringArea;
|
||||
|
||||
typedef struct VhostUserInflight {
|
||||
uint64_t mmap_size;
|
||||
uint64_t mmap_offset;
|
||||
uint16_t num_queues;
|
||||
uint16_t queue_size;
|
||||
} VhostUserInflight;
|
||||
|
||||
typedef struct {
|
||||
VhostUserRequest request;
|
||||
|
||||
|
|
@ -173,6 +183,7 @@ typedef union {
|
|||
VhostUserConfig config;
|
||||
VhostUserCryptoSession session;
|
||||
VhostUserVringArea area;
|
||||
VhostUserInflight inflight;
|
||||
} VhostUserPayload;
|
||||
|
||||
typedef struct VhostUserMsg {
|
||||
|
|
@ -1770,6 +1781,100 @@ static bool vhost_user_mem_section_filter(struct vhost_dev *dev,
|
|||
return result;
|
||||
}
|
||||
|
||||
static int vhost_user_get_inflight_fd(struct vhost_dev *dev,
|
||||
uint16_t queue_size,
|
||||
struct vhost_inflight *inflight)
|
||||
{
|
||||
void *addr;
|
||||
int fd;
|
||||
struct vhost_user *u = dev->opaque;
|
||||
CharBackend *chr = u->user->chr;
|
||||
VhostUserMsg msg = {
|
||||
.hdr.request = VHOST_USER_GET_INFLIGHT_FD,
|
||||
.hdr.flags = VHOST_USER_VERSION,
|
||||
.payload.inflight.num_queues = dev->nvqs,
|
||||
.payload.inflight.queue_size = queue_size,
|
||||
.hdr.size = sizeof(msg.payload.inflight),
|
||||
};
|
||||
|
||||
if (!virtio_has_feature(dev->protocol_features,
|
||||
VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (vhost_user_write(dev, &msg, NULL, 0) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (vhost_user_read(dev, &msg) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (msg.hdr.request != VHOST_USER_GET_INFLIGHT_FD) {
|
||||
error_report("Received unexpected msg type. "
|
||||
"Expected %d received %d",
|
||||
VHOST_USER_GET_INFLIGHT_FD, msg.hdr.request);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (msg.hdr.size != sizeof(msg.payload.inflight)) {
|
||||
error_report("Received bad msg size.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!msg.payload.inflight.mmap_size) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
fd = qemu_chr_fe_get_msgfd(chr);
|
||||
if (fd < 0) {
|
||||
error_report("Failed to get mem fd");
|
||||
return -1;
|
||||
}
|
||||
|
||||
addr = mmap(0, msg.payload.inflight.mmap_size, PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED, fd, msg.payload.inflight.mmap_offset);
|
||||
|
||||
if (addr == MAP_FAILED) {
|
||||
error_report("Failed to mmap mem fd");
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
inflight->addr = addr;
|
||||
inflight->fd = fd;
|
||||
inflight->size = msg.payload.inflight.mmap_size;
|
||||
inflight->offset = msg.payload.inflight.mmap_offset;
|
||||
inflight->queue_size = queue_size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vhost_user_set_inflight_fd(struct vhost_dev *dev,
|
||||
struct vhost_inflight *inflight)
|
||||
{
|
||||
VhostUserMsg msg = {
|
||||
.hdr.request = VHOST_USER_SET_INFLIGHT_FD,
|
||||
.hdr.flags = VHOST_USER_VERSION,
|
||||
.payload.inflight.mmap_size = inflight->size,
|
||||
.payload.inflight.mmap_offset = inflight->offset,
|
||||
.payload.inflight.num_queues = dev->nvqs,
|
||||
.payload.inflight.queue_size = inflight->queue_size,
|
||||
.hdr.size = sizeof(msg.payload.inflight),
|
||||
};
|
||||
|
||||
if (!virtio_has_feature(dev->protocol_features,
|
||||
VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (vhost_user_write(dev, &msg, &inflight->fd, 1) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool vhost_user_init(VhostUserState *user, CharBackend *chr, Error **errp)
|
||||
{
|
||||
if (user->chr) {
|
||||
|
|
@ -1829,4 +1934,6 @@ const VhostOps user_ops = {
|
|||
.vhost_crypto_create_session = vhost_user_crypto_create_session,
|
||||
.vhost_crypto_close_session = vhost_user_crypto_close_session,
|
||||
.vhost_backend_mem_section_filter = vhost_user_mem_section_filter,
|
||||
.vhost_get_inflight_fd = vhost_user_get_inflight_fd,
|
||||
.vhost_set_inflight_fd = vhost_user_set_inflight_fd,
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue