Page MenuHomeFreeBSD

D34721.id105514.diff
No OneTemporary

D34721.id105514.diff

diff --git a/usr.sbin/bhyve/migration.c b/usr.sbin/bhyve/migration.c
--- a/usr.sbin/bhyve/migration.c
+++ b/usr.sbin/bhyve/migration.c
@@ -633,6 +633,179 @@
return (error);
}
+
+static inline const struct vm_snapshot_dev_info *
+find_entry_for_dev(const char *name)
+{
+ int i;
+ int ndevs;
+ const struct vm_snapshot_dev_info *snapshot_devs;
+
+ snapshot_devs = get_snapshot_devs(&ndevs);
+
+ for (i = 0; i < ndevs; i++) {
+ if (strncmp(name, snapshot_devs[i].dev_name, MAX_DEV_NAME_LEN) == 0) {
+ return (&snapshot_devs[i]);
+ }
+ }
+
+ return NULL;
+}
+
+static inline int
+migrate_transfer_dev(struct vmctx *ctx, int socket, const char *dev,
+ char *buffer, size_t len, enum migration_transfer_req req)
+{
+ int rc;
+ size_t data_size;
+ struct migration_message_type msg;
+ struct vm_snapshot_meta *meta;
+ const struct vm_snapshot_dev_info *dev_info;
+
+ if ((req != MIGRATION_SEND_REQ) && (req != MIGRATION_RECV_REQ)) {
+ DPRINTF("Unknown transfer request option");
+ return (-1);
+ }
+
+ memset(&msg, 0, sizeof(msg));
+ memset(buffer, 0, len);
+ if (req == MIGRATION_SEND_REQ) {
+ dev_info = find_entry_for_dev(dev);
+ if (dev_info == NULL) {
+ EPRINTF("Could not find the device %s "
+ "or migration not implemented yet for it.", dev);
+ return (0);
+ }
+
+ meta = ALLOCA_VM_SNAPSHOT_META(ctx, dev, 0, buffer, len, VM_SNAPSHOT_SAVE);
+
+ memset(meta->buffer.buf_start, 0, meta->buffer.buf_size);
+ meta->buffer.buf = meta->buffer.buf_start;
+ meta->buffer.buf_rem = meta->buffer.buf_size;
+
+ rc = (*dev_info->snapshot_cb)(meta);
+ if (rc < 0) {
+ DPRINTF("Could not get info about %s dev", dev);
+ return (-1);
+ }
+
+ data_size = vm_get_snapshot_size(meta);
+
+ msg.type = MESSAGE_TYPE_DEV;
+ msg.len = data_size;
+ strlcpy(msg.name, dev, MAX_DEV_NAME_LEN);
+ }
+
+ rc = migration_transfer_data(socket, &msg, sizeof(msg), req);
+ if (rc < 0) {
+ DPRINTF("Could not transfer msg for %s dev", dev);
+ return (-1);
+ }
+
+ if (req == MIGRATION_RECV_REQ) {
+ if (msg.type != MESSAGE_TYPE_DEV) {
+ DPRINTF("Wrong message type for device.");
+ return (-1);
+ }
+
+ data_size = msg.len;
+ }
+
+ if (data_size == 0)
+ return (0); // this type of device is not used
+
+
+ rc = migration_transfer_data(socket, buffer, data_size, req);
+ if (rc < 0) {
+ DPRINTF("Could not transfer %s dev", dev);
+ return (-1);
+ }
+
+ if (req == MIGRATION_RECV_REQ) {
+ dev_info = find_entry_for_dev(msg.name);
+ if (dev_info == NULL) {
+ EPRINTF("Could not find the device %s "
+ "or migration not implemented yet for it.", msg.name);
+ return (0);
+ }
+ meta = ALLOCA_VM_SNAPSHOT_META(ctx, msg.name, 0, buffer, data_size, VM_SNAPSHOT_RESTORE);
+ meta->buffer.buf = meta->buffer.buf_start;
+ meta->buffer.buf_rem = meta->buffer.buf_size;
+
+ rc = (*dev_info->snapshot_cb)(meta);
+ if (rc != 0) {
+ EPRINTF("Could not restore %s dev", msg.name);
+ return (-1);
+ }
+ }
+
+ return (0);
+}
+
+static int
+migrate_devs(struct vmctx *ctx, int socket, enum migration_transfer_req req)
+{
+ int i, num_items;
+ int rc, error;
+ char *buffer;
+ const struct vm_snapshot_dev_info *snapshot_devs;
+
+ error = 0;
+ buffer = malloc(SNAPSHOT_BUFFER_SIZE);
+ if (buffer == NULL) {
+ EPRINTF("Could not allocate memory");
+ error = -1;
+ goto end;
+ }
+
+ if (req == MIGRATION_SEND_REQ) {
+ /*
+ * Send to the destination the number of devices that will
+ * be migrated.
+ */
+ snapshot_devs = get_snapshot_devs(&num_items);
+
+ rc = migration_transfer_data(socket, &num_items, sizeof(num_items), req);
+ if (rc < 0) {
+ DPRINTF("Could not send num_items to destination");
+ return (-1);
+ }
+
+ for (i = 0; i < num_items; i++) {
+ rc = migrate_transfer_dev(ctx, socket, snapshot_devs[i].dev_name,
+ buffer, SNAPSHOT_BUFFER_SIZE, req);
+
+ if (rc < 0) {
+ DPRINTF("Could not send %s", snapshot_devs[i].dev_name);
+ error = -1;
+ goto end;
+ }
+ }
+ } else if (req == MIGRATION_RECV_REQ) {
+ /* receive the number of devices that will be migrated */
+ rc = migration_transfer_data(socket, &num_items, sizeof(num_items), MIGRATION_RECV_REQ);
+ if (rc < 0) {
+ DPRINTF("Could not recv num_items from source");
+ return (-1);
+ }
+
+ for (i = 0; i < num_items; i++) {
+ rc = migrate_transfer_dev(ctx, socket, NULL, buffer, SNAPSHOT_BUFFER_SIZE, req);
+ if (rc < 0) {
+ DPRINTF("Could not recv device");
+ error = -1;
+ goto end;
+ }
+ }
+ }
+
+end:
+ if (buffer != NULL)
+ free(buffer);
+
+ return (error);
+}
+
static inline int
migrate_connections(struct migrate_req req, int *socket_fd,
int *connection_socket_fd,
@@ -785,6 +958,13 @@
goto unlock_vm_and_exit;
}
+ rc = migrate_devs(ctx, s, MIGRATION_SEND_REQ);
+ if (rc < 0) {
+ EPRINTF("Could not send pci devs to destination");
+ error = rc;
+ goto unlock_vm_and_exit;
+ }
+
rc = migration_transfer_data(s, &migration_completed,
sizeof(migration_completed), MIGRATION_RECV_REQ);
if ((rc < 0) || (migration_completed != MIGRATION_SPECS_OK)) {
@@ -793,10 +973,6 @@
goto unlock_vm_and_exit;
}
- EPRINTF("Migration not yet implemented");
- error = -1;
- goto unlock_vm_and_exit;
-
vm_destroy(ctx);
exit(0);
@@ -848,6 +1024,14 @@
return (-1);
}
+ rc = migrate_devs(ctx, con_socket, MIGRATION_RECV_REQ);
+ if (rc < 0) {
+ EPRINTF("Could not recv pci devs");
+ close(con_socket);
+ close(s);
+ return (-1);
+ }
+
fprintf(stdout, "%s: Migration completed\r\n", __func__);
migration_completed = MIGRATION_SPECS_OK;
rc = migration_transfer_data(con_socket, &migration_completed,
@@ -861,7 +1045,5 @@
close(con_socket);
close(s);
-
- EPRINTF("Migration not currently implemented");
- return (-1);
+ return (0);
}

File Metadata

Mime Type
text/plain
Expires
Fri, Nov 8, 11:25 PM (10 h, 32 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
14545195
Default Alt Text
D34721.id105514.diff (5 KB)

Event Timeline