Page MenuHomeFreeBSD

D34721.1789201052.diff
No OneTemporary

Size
6 KB
Referenced Files
None
Subscribers
None

D34721.1789201052.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
@@ -618,6 +618,176 @@
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(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)) {
+ EPRINTF("Unknown transfer request option");
+ return (EINVAL);
+ }
+
+ 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(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) {
+ EPRINTF("Could not get info about %s dev", dev);
+ return (rc);
+ }
+
+ 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) {
+ EPRINTF("Could not transfer msg for %s dev", dev);
+ return (rc);
+ }
+
+ if (req == MIGRATION_RECV_REQ) {
+ if (msg.type != MESSAGE_TYPE_DEV) {
+ EPRINTF("Wrong message type for device.");
+ return (EINVAL);
+ }
+
+ 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) {
+ EPRINTF("Could not transfer %s dev", dev);
+ return (rc);
+ }
+
+ 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(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 (rc);
+ }
+ }
+
+ return (0);
+}
+
+static int
+migrate_devs(int socket, enum migration_transfer_req req)
+{
+ int i, num_items;
+ int 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 = ENOMEM;
+ 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);
+
+ error = migration_transfer_data(socket, &num_items, sizeof(num_items), req);
+ if (error != 0) {
+ EPRINTF("Could not send number of devices to destination");
+ goto end;
+ }
+
+ for (i = 0; i < num_items; i++) {
+ error = migrate_transfer_dev(socket, snapshot_devs[i].dev_name,
+ buffer, SNAPSHOT_BUFFER_SIZE, req);
+
+ if (error != 0) {
+ DPRINTF("Could not send %s", snapshot_devs[i].dev_name);
+ goto end;
+ }
+ }
+ } else if (req == MIGRATION_RECV_REQ) {
+ /* receive the number of devices that will be migrated */
+ error = migration_transfer_data(socket, &num_items, sizeof(num_items), MIGRATION_RECV_REQ);
+ if (error != 0) {
+ EPRINTF("Could not recv number of devices from source");
+ goto end;
+ }
+
+ for (i = 0; i < num_items; i++) {
+ error = migrate_transfer_dev(socket, NULL, buffer, SNAPSHOT_BUFFER_SIZE, req);
+ if (error != 0) {
+ EPRINTF("Could not recv device");
+ goto end;
+ }
+ }
+ }
+
+end:
+ if (buffer != NULL)
+ free(buffer);
+
+ return (error);
+}
+
static inline int
migrate_connections(struct migrate_req req, int *socket_fd,
enum migration_transfer_req type)
@@ -781,6 +951,13 @@
goto unlock_vm_and_exit;
}
+ rc = migrate_devs(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)) {
@@ -789,10 +966,6 @@
goto unlock_vm_and_exit;
}
- EPRINTF("Rest of migration not yet implemented");
- error = EOPNOTSUPP;
- goto unlock_vm_and_exit;
-
vm_destroy(ctx);
exit(0);
@@ -863,7 +1036,14 @@
return (rc);
}
- // fprintf(stdout, "%s: Migration completed\n", __func__);
+ rc = migrate_devs(s, MIGRATION_RECV_REQ);
+ if (rc != 0) {
+ EPRINTF("Could not recv pci devs");
+ close(s);
+ return (rc);
+ }
+
+ fprintf(stdout, "%s: Migration completed\n", __func__);
migration_completed = MIGRATION_SPECS_OK;
rc = migration_transfer_data(s, &migration_completed,
@@ -875,8 +1055,7 @@
}
close(s);
- EPRINTF("Rest of migration not currently implemented");
- return (EOPNOTSUPP);
+ return (0);
}
#ifdef WITH_CASPER
diff --git a/usr.sbin/bhyve/snapshot.h b/usr.sbin/bhyve/snapshot.h
--- a/usr.sbin/bhyve/snapshot.h
+++ b/usr.sbin/bhyve/snapshot.h
@@ -83,6 +83,7 @@
enum snapshot_req req; /* request type */
};
+const struct vm_snapshot_dev_info *get_snapshot_devs(int *ndevs);
const struct vm_snapshot_kern_info *get_snapshot_kern_structs(int *ndevs);
void destroy_restore_state(struct restore_state *rstate);
diff --git a/usr.sbin/bhyve/snapshot.c b/usr.sbin/bhyve/snapshot.c
--- a/usr.sbin/bhyve/snapshot.c
+++ b/usr.sbin/bhyve/snapshot.c
@@ -163,6 +163,15 @@
{ "vrtc", STRUCT_VRTC },
};
+const struct vm_snapshot_dev_info *
+get_snapshot_devs(int *ndevs)
+{
+ if (ndevs != NULL)
+ *ndevs = nitems(snapshot_devs);
+
+ return (snapshot_devs);
+}
+
const struct vm_snapshot_kern_info *
get_snapshot_kern_structs(int *ndevs)
{
diff --git a/usr.sbin/bhyve/virtio.c b/usr.sbin/bhyve/virtio.c
--- a/usr.sbin/bhyve/virtio.c
+++ b/usr.sbin/bhyve/virtio.c
@@ -869,7 +869,6 @@
SNAPSHOT_VAR_CMP_OR_LEAVE(vc->vc_nvq, meta, ret, done);
SNAPSHOT_VAR_CMP_OR_LEAVE(vc->vc_cfgsize, meta, ret, done);
- SNAPSHOT_VAR_CMP_OR_LEAVE(vc->vc_hv_caps, meta, ret, done);
done:
return (ret);

File Metadata

Mime Type
text/plain
Expires
Sat, Sep 12, 8:17 AM (20 h, 5 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29569840
Default Alt Text
D34721.1789201052.diff (6 KB)

Event Timeline