postcopy: Add vhost-user flag for postcopy and check it
Add a vhost feature flag for postcopy support, and use the postcopy notifier to check it before allowing postcopy. Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com> Reviewed-by: Peter Xu <peterx@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
1693c64c27
commit
9ccbfe14dd
@ -48,6 +48,8 @@ enum VhostUserProtocolFeature {
|
|||||||
VHOST_USER_PROTOCOL_F_NET_MTU = 4,
|
VHOST_USER_PROTOCOL_F_NET_MTU = 4,
|
||||||
VHOST_USER_PROTOCOL_F_SLAVE_REQ = 5,
|
VHOST_USER_PROTOCOL_F_SLAVE_REQ = 5,
|
||||||
VHOST_USER_PROTOCOL_F_CROSS_ENDIAN = 6,
|
VHOST_USER_PROTOCOL_F_CROSS_ENDIAN = 6,
|
||||||
|
VHOST_USER_PROTOCOL_F_CRYPTO_SESSION = 7,
|
||||||
|
VHOST_USER_PROTOCOL_F_PAGEFAULT = 8,
|
||||||
|
|
||||||
VHOST_USER_PROTOCOL_F_MAX
|
VHOST_USER_PROTOCOL_F_MAX
|
||||||
};
|
};
|
||||||
|
@ -290,6 +290,15 @@ Once the source has finished migration, rings will be stopped by
|
|||||||
the source. No further update must be done before rings are
|
the source. No further update must be done before rings are
|
||||||
restarted.
|
restarted.
|
||||||
|
|
||||||
|
In postcopy migration the slave is started before all the memory has been
|
||||||
|
received from the source host, and care must be taken to avoid accessing pages
|
||||||
|
that have yet to be received. The slave opens a 'userfault'-fd and registers
|
||||||
|
the memory with it; this fd is then passed back over to the master.
|
||||||
|
The master services requests on the userfaultfd for pages that are accessed
|
||||||
|
and when the page is available it performs WAKE ioctl's on the userfaultfd
|
||||||
|
to wake the stalled slave. The client indicates support for this via the
|
||||||
|
VHOST_USER_PROTOCOL_F_PAGEFAULT feature.
|
||||||
|
|
||||||
Memory access
|
Memory access
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
@ -369,6 +378,7 @@ Protocol features
|
|||||||
#define VHOST_USER_PROTOCOL_F_SLAVE_REQ 5
|
#define VHOST_USER_PROTOCOL_F_SLAVE_REQ 5
|
||||||
#define VHOST_USER_PROTOCOL_F_CROSS_ENDIAN 6
|
#define VHOST_USER_PROTOCOL_F_CROSS_ENDIAN 6
|
||||||
#define VHOST_USER_PROTOCOL_F_CRYPTO_SESSION 7
|
#define VHOST_USER_PROTOCOL_F_CRYPTO_SESSION 7
|
||||||
|
#define VHOST_USER_PROTOCOL_F_PAGEFAULT 8
|
||||||
|
|
||||||
Master message types
|
Master message types
|
||||||
--------------------
|
--------------------
|
||||||
|
@ -18,6 +18,8 @@
|
|||||||
#include "qemu/error-report.h"
|
#include "qemu/error-report.h"
|
||||||
#include "qemu/sockets.h"
|
#include "qemu/sockets.h"
|
||||||
#include "sysemu/cryptodev.h"
|
#include "sysemu/cryptodev.h"
|
||||||
|
#include "migration/migration.h"
|
||||||
|
#include "migration/postcopy-ram.h"
|
||||||
|
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
@ -41,7 +43,7 @@ enum VhostUserProtocolFeature {
|
|||||||
VHOST_USER_PROTOCOL_F_SLAVE_REQ = 5,
|
VHOST_USER_PROTOCOL_F_SLAVE_REQ = 5,
|
||||||
VHOST_USER_PROTOCOL_F_CROSS_ENDIAN = 6,
|
VHOST_USER_PROTOCOL_F_CROSS_ENDIAN = 6,
|
||||||
VHOST_USER_PROTOCOL_F_CRYPTO_SESSION = 7,
|
VHOST_USER_PROTOCOL_F_CRYPTO_SESSION = 7,
|
||||||
|
VHOST_USER_PROTOCOL_F_PAGEFAULT = 8,
|
||||||
VHOST_USER_PROTOCOL_F_MAX
|
VHOST_USER_PROTOCOL_F_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -164,8 +166,10 @@ static VhostUserMsg m __attribute__ ((unused));
|
|||||||
#define VHOST_USER_VERSION (0x1)
|
#define VHOST_USER_VERSION (0x1)
|
||||||
|
|
||||||
struct vhost_user {
|
struct vhost_user {
|
||||||
|
struct vhost_dev *dev;
|
||||||
CharBackend *chr;
|
CharBackend *chr;
|
||||||
int slave_fd;
|
int slave_fd;
|
||||||
|
NotifierWithReturn postcopy_notifier;
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool ioeventfd_enabled(void)
|
static bool ioeventfd_enabled(void)
|
||||||
@ -791,6 +795,33 @@ out:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int vhost_user_postcopy_notifier(NotifierWithReturn *notifier,
|
||||||
|
void *opaque)
|
||||||
|
{
|
||||||
|
struct PostcopyNotifyData *pnd = opaque;
|
||||||
|
struct vhost_user *u = container_of(notifier, struct vhost_user,
|
||||||
|
postcopy_notifier);
|
||||||
|
struct vhost_dev *dev = u->dev;
|
||||||
|
|
||||||
|
switch (pnd->reason) {
|
||||||
|
case POSTCOPY_NOTIFY_PROBE:
|
||||||
|
if (!virtio_has_feature(dev->protocol_features,
|
||||||
|
VHOST_USER_PROTOCOL_F_PAGEFAULT)) {
|
||||||
|
/* TODO: Get the device name into this error somehow */
|
||||||
|
error_setg(pnd->errp,
|
||||||
|
"vhost-user backend not capable of postcopy");
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
/* We ignore notifications we don't know */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int vhost_user_init(struct vhost_dev *dev, void *opaque)
|
static int vhost_user_init(struct vhost_dev *dev, void *opaque)
|
||||||
{
|
{
|
||||||
uint64_t features, protocol_features;
|
uint64_t features, protocol_features;
|
||||||
@ -802,6 +833,7 @@ static int vhost_user_init(struct vhost_dev *dev, void *opaque)
|
|||||||
u = g_new0(struct vhost_user, 1);
|
u = g_new0(struct vhost_user, 1);
|
||||||
u->chr = opaque;
|
u->chr = opaque;
|
||||||
u->slave_fd = -1;
|
u->slave_fd = -1;
|
||||||
|
u->dev = dev;
|
||||||
dev->opaque = u;
|
dev->opaque = u;
|
||||||
|
|
||||||
err = vhost_user_get_features(dev, &features);
|
err = vhost_user_get_features(dev, &features);
|
||||||
@ -858,6 +890,9 @@ static int vhost_user_init(struct vhost_dev *dev, void *opaque)
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u->postcopy_notifier.notify = vhost_user_postcopy_notifier;
|
||||||
|
postcopy_add_notifier(&u->postcopy_notifier);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -868,6 +903,10 @@ static int vhost_user_cleanup(struct vhost_dev *dev)
|
|||||||
assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_USER);
|
assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_USER);
|
||||||
|
|
||||||
u = dev->opaque;
|
u = dev->opaque;
|
||||||
|
if (u->postcopy_notifier.notify) {
|
||||||
|
postcopy_remove_notifier(&u->postcopy_notifier);
|
||||||
|
u->postcopy_notifier.notify = NULL;
|
||||||
|
}
|
||||||
if (u->slave_fd >= 0) {
|
if (u->slave_fd >= 0) {
|
||||||
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);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user