vhost-user: allow slave to send fds via slave channel

Introduce VHOST_USER_PROTOCOL_F_SLAVE_SEND_FD protocol
feature to allow slave to send at most 8 descriptors
in each message to master via ancillary data using the
slave channel.

Suggested-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Tiwei Bie <tiwei.bie@intel.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
Tiwei Bie 2018-05-24 18:33:32 +08:00 committed by Michael S. Tsirkin
parent 988a27754b
commit 5f57fbeaaf
2 changed files with 22 additions and 10 deletions

View File

@ -367,6 +367,10 @@ The fd is provided via VHOST_USER_SET_SLAVE_REQ_FD ancillary data.
A slave may then send VHOST_USER_SLAVE_* messages to the master A slave may then send VHOST_USER_SLAVE_* messages to the master
using this fd communication channel. using this fd communication channel.
If VHOST_USER_PROTOCOL_F_SLAVE_SEND_FD protocol feature is negotiated,
slave can send file descriptors (at most 8 descriptors in each message)
to master via ancillary data using this fd communication channel.
Protocol features Protocol features
----------------- -----------------
@ -380,6 +384,7 @@ Protocol features
#define VHOST_USER_PROTOCOL_F_CRYPTO_SESSION 7 #define VHOST_USER_PROTOCOL_F_CRYPTO_SESSION 7
#define VHOST_USER_PROTOCOL_F_PAGEFAULT 8 #define VHOST_USER_PROTOCOL_F_PAGEFAULT 8
#define VHOST_USER_PROTOCOL_F_CONFIG 9 #define VHOST_USER_PROTOCOL_F_CONFIG 9
#define VHOST_USER_PROTOCOL_F_SLAVE_SEND_FD 10
Master message types Master message types
-------------------- --------------------

View File

@ -30,6 +30,7 @@
#define VHOST_MEMORY_MAX_NREGIONS 8 #define VHOST_MEMORY_MAX_NREGIONS 8
#define VHOST_USER_F_PROTOCOL_FEATURES 30 #define VHOST_USER_F_PROTOCOL_FEATURES 30
#define VHOST_USER_SLAVE_MAX_FDS 8
/* /*
* Maximum size of virtio device config space * Maximum size of virtio device config space
@ -47,6 +48,7 @@ enum VhostUserProtocolFeature {
VHOST_USER_PROTOCOL_F_CRYPTO_SESSION = 7, VHOST_USER_PROTOCOL_F_CRYPTO_SESSION = 7,
VHOST_USER_PROTOCOL_F_PAGEFAULT = 8, VHOST_USER_PROTOCOL_F_PAGEFAULT = 8,
VHOST_USER_PROTOCOL_F_CONFIG = 9, VHOST_USER_PROTOCOL_F_CONFIG = 9,
VHOST_USER_PROTOCOL_F_SLAVE_SEND_FD = 10,
VHOST_USER_PROTOCOL_F_MAX VHOST_USER_PROTOCOL_F_MAX
}; };
@ -854,10 +856,10 @@ static void slave_read(void *opaque)
int size, ret = 0; int size, ret = 0;
struct iovec iov; struct iovec iov;
struct msghdr msgh; struct msghdr msgh;
int fd = -1; int fd[VHOST_USER_SLAVE_MAX_FDS];
char control[CMSG_SPACE(sizeof(fd))]; char control[CMSG_SPACE(sizeof(fd))];
struct cmsghdr *cmsg; struct cmsghdr *cmsg;
size_t fdsize; int i, fdsize = 0;
memset(&msgh, 0, sizeof(msgh)); memset(&msgh, 0, sizeof(msgh));
msgh.msg_iov = &iov; msgh.msg_iov = &iov;
@ -865,6 +867,8 @@ static void slave_read(void *opaque)
msgh.msg_control = control; msgh.msg_control = control;
msgh.msg_controllen = sizeof(control); msgh.msg_controllen = sizeof(control);
memset(fd, -1, sizeof(fd));
/* Read header */ /* Read header */
iov.iov_base = &hdr; iov.iov_base = &hdr;
iov.iov_len = VHOST_USER_HDR_SIZE; iov.iov_len = VHOST_USER_HDR_SIZE;
@ -885,7 +889,7 @@ static void slave_read(void *opaque)
if (cmsg->cmsg_level == SOL_SOCKET && if (cmsg->cmsg_level == SOL_SOCKET &&
cmsg->cmsg_type == SCM_RIGHTS) { cmsg->cmsg_type == SCM_RIGHTS) {
fdsize = cmsg->cmsg_len - CMSG_LEN(0); fdsize = cmsg->cmsg_len - CMSG_LEN(0);
memcpy(&fd, CMSG_DATA(cmsg), fdsize); memcpy(fd, CMSG_DATA(cmsg), fdsize);
break; break;
} }
} }
@ -913,14 +917,15 @@ static void slave_read(void *opaque)
break; break;
default: default:
error_report("Received unexpected msg type."); error_report("Received unexpected msg type.");
if (fd != -1) {
close(fd);
}
ret = -EINVAL; ret = -EINVAL;
} }
/* Message handlers need to make sure that fd will be consumed. */ /* Close the remaining file descriptors. */
fd = -1; for (i = 0; i < fdsize; i++) {
if (fd[i] != -1) {
close(fd[i]);
}
}
/* /*
* REPLY_ACK feature handling. Other reply types has to be managed * REPLY_ACK feature handling. Other reply types has to be managed
@ -954,8 +959,10 @@ err:
qemu_set_fd_handler(u->slave_fd, NULL, NULL, NULL); qemu_set_fd_handler(u->slave_fd, NULL, NULL, NULL);
close(u->slave_fd); close(u->slave_fd);
u->slave_fd = -1; u->slave_fd = -1;
if (fd != -1) { for (i = 0; i < fdsize; i++) {
close(fd); if (fd[i] != -1) {
close(fd[i]);
}
} }
return; return;
} }