@@ -331,6 +331,21 @@ Message types
This message is only sent if VHOST_USER_PROTOCOL_F_SLAVE_REQ
feature is available.
+Slave message types
+-------------------
+
+ * VHOST_USER_SLAVE_SHUTDOWN:
+ Id: 1
+ Master payload: N/A
+ Slave payload: u64
+
+ Request the master to shutdown the slave. A 0 reply is for
+ success, in which case the slave may close all connections
+ immediately and quit. A non-zero reply cancels the request.
+
+ Before a reply comes, the master may make other requests in
+ order to flush or sync state.
+
Migration
---------
@@ -55,6 +55,7 @@ typedef enum VhostUserRequest {
typedef enum VhostUserSlaveRequest {
VHOST_USER_SLAVE_NONE = 0,
+ VHOST_USER_SLAVE_SHUTDOWN = 1,
VHOST_USER_SLAVE_MAX
} VhostUserSlaveRequest;
@@ -140,7 +141,7 @@ static VhostUserRequest vhost_user_request_translate(unsigned long int request)
case VHOST_SET_VRING_ERR:
return VHOST_USER_SET_VRING_ERR;
default:
- return VHOST_USER_MAX;
+ return request;
}
}
@@ -375,6 +376,21 @@ static int slave_can_receive(void *opaque)
return VHOST_USER_HDR_SIZE;
}
+static int vhost_user_slave_write(struct vhost_dev *dev, VhostUserMsg *msg,
+ int *fds, int fd_num)
+{
+ struct vhost_user *u = dev->opaque;
+ CharDriverState *chr = u->slave_chr;
+ int size = VHOST_USER_HDR_SIZE + msg->size;
+
+ if (fd_num) {
+ qemu_chr_fe_set_msgfds(chr, fds, fd_num);
+ }
+
+ return qemu_chr_fe_write_all(chr, (const uint8_t *) msg, size) == size ?
+ 0 : -1;
+}
+
static void slave_receive(void *opaque, const uint8_t *buf, int size)
{
struct vhost_dev *dev = opaque;
@@ -386,6 +402,18 @@ static void slave_receive(void *opaque, const uint8_t *buf, int size)
}
switch (msg->request) {
+ case VHOST_USER_SLAVE_SHUTDOWN: {
+ uint64_t success = 1;
+
+ if (dev->stop) {
+ dev->stop(dev);
+ success = 0;
+ }
+
+ msg->u64 = success;
+ vhost_user_slave_write(dev, msg, NULL, 0);
+ return;
+ }
default:
error_report("Received unexpected msg type.");
}