aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--samples/client.c32
-rw-r--r--samples/server.c131
2 files changed, 53 insertions, 110 deletions
diff --git a/samples/client.c b/samples/client.c
index fc662fd..f32a060 100644
--- a/samples/client.c
+++ b/samples/client.c
@@ -754,9 +754,6 @@ do_migrate(int sock, int migr_reg_index, size_t nr_iters,
strerror(-ret));
}
- /* We do expect some migration data. */
- assert(pending_bytes > 0);
-
for (i = 0; i < nr_iters && pending_bytes > 0; i++) {
/* XXX read data_offset and data_size */
@@ -827,17 +824,18 @@ fake_guest(void *arg)
err(EXIT_FAILURE, "failed to open /dev/urandom");
}
- MD5_Init(&md5_ctx);
do {
ret = fread(buf, fake_guest_data->bar1_size, 1, fp);
if (ret != 1) {
errx(EXIT_FAILURE, "short read %d", ret);
}
- ret = access_region(fake_guest_data->sock, 1, true, 0, buf, sizeof buf);
+ ret = access_region(fake_guest_data->sock, 1, true, 0, buf,
+ fake_guest_data->bar1_size);
if (ret != 0) {
err(EXIT_FAILURE, "fake guest failed to write garbage to BAR1");
}
+ MD5_Init(&md5_ctx);
MD5_Update(&md5_ctx, buf, fake_guest_data->bar1_size);
__sync_synchronize();
} while (!fake_guest_data->done);
@@ -897,12 +895,6 @@ migrate_from(int sock, int migr_reg_index, size_t *nr_iters,
}
_nr_iters = do_migrate(sock, migr_reg_index, 3, *migr_iters);
- if (_nr_iters != 3) {
- errx(EXIT_FAILURE,
- "expected 3 iterations instead of %ld while in pre-copy state\n",
- _nr_iters);
- }
-
printf("stopping fake guest thread\n");
fake_guest_data.done = true;
__sync_synchronize();
@@ -913,11 +905,6 @@ migrate_from(int sock, int migr_reg_index, size_t *nr_iters,
}
_nr_iters += do_migrate(sock, migr_reg_index, 1, (*migr_iters) + _nr_iters);
- if (_nr_iters != 4) {
- errx(EXIT_FAILURE,
- "expected 4 iterations instead of %ld while in pre-copy state\n",
- _nr_iters);
- }
printf("setting device state to stop-and-copy\n");
@@ -931,9 +918,9 @@ migrate_from(int sock, int migr_reg_index, size_t *nr_iters,
}
_nr_iters += do_migrate(sock, migr_reg_index, 1, (*migr_iters) + _nr_iters);
- if (_nr_iters != 5) {
+ if (_nr_iters != 2) {
errx(EXIT_FAILURE,
- "expected 5 iterations instead of %ld while in stop-and-copy state\n",
+ "expected 2 iterations instead of %ld while in stop-and-copy state\n",
_nr_iters);
}
@@ -1074,9 +1061,9 @@ migrate_to(char *old_sock_path, int *server_max_fds,
MD5_Update(&md5_ctx, buf, bar1_size);
MD5_Final(dst_md5sum, &md5_ctx);
- if (strcmp((char*)src_md5sum, (char*)dst_md5sum) != 0) {
+ if (strncmp((char*)src_md5sum, (char*)dst_md5sum, MD5_DIGEST_LENGTH) != 0) {
int i;
- fprintf(stderr, "md5 sum mismatch: ");
+ fprintf(stderr, "md5sum mismatch: ");
for (i = 0; i < MD5_DIGEST_LENGTH; i++) {
fprintf(stderr, "%02x", src_md5sum[i]);
}
@@ -1085,6 +1072,7 @@ migrate_to(char *old_sock_path, int *server_max_fds,
fprintf(stderr, "%02x", dst_md5sum[i]);
}
fprintf(stderr, "\n");
+ abort();
}
return sock;
@@ -1299,8 +1287,8 @@ int main(int argc, char *argv[])
*/
sleep(1);
- migrate_from(sock, migr_reg_index, &nr_iters, &migr_iters, md5sum,
- bar1_size);
+ nr_iters = migrate_from(sock, migr_reg_index, &nr_iters, &migr_iters,
+ md5sum, bar1_size);
/*
* Normally the client would now send the device state to the destination
diff --git a/samples/server.c b/samples/server.c
index 82b22ff..35452c3 100644
--- a/samples/server.c
+++ b/samples/server.c
@@ -63,13 +63,6 @@ struct server_data {
struct dma_regions regions[NR_DMA_REGIONS];
struct {
__u64 pending_bytes;
-
- /*
- * TODO must be maximum size of migration data read, we'll use that to
- * create the migration region.
- */
- size_t migr_data_len;
-
vfu_migr_state_t state;
} migration;
};
@@ -137,22 +130,10 @@ bar1_access(vfu_ctx_t *vfu_ctx, char * const buf,
}
if (is_write) {
- /*
- * FIXME this doesn't work for the following reason:
- * The amount of migration data the server generates during the pre-copy
- * and stop-and-copy phases is larger than the size of BAR1, however
- * during the resuming state, the server blindly appends to BAR1,
- * since it cannot know that a particular piece of migration data has
- * to be written to a specific offset. To fix this we have to include
- * offset and length, along with the actual data, when reading migration
- * data.
- */
-#if 0
if (server_data->migration.state == VFU_MIGR_STATE_PRE_COPY) {
/* dirty the whole thing */
server_data->migration.pending_bytes = server_data->bar1_size;
}
-#endif
memcpy(server_data->bar1 + offset, buf, count);
} else {
memcpy(buf, server_data->bar1, count);
@@ -285,7 +266,7 @@ migration_device_state_transition(vfu_ctx_t *vfu_ctx, vfu_migr_state_t state)
switch (state) {
case VFU_MIGR_STATE_STOP_AND_COPY:
- server_data->migration.pending_bytes = sizeof(time_t); /* FIXME BAR0 region size */
+ server_data->migration.pending_bytes = server_data->bar1_size + sizeof(time_t); /* FIXME BAR0 region size */
break;
case VFU_MIGR_STATE_PRE_COPY:
/* TODO must be less than size of data region in migration region */
@@ -322,15 +303,10 @@ migration_prepare_data(vfu_ctx_t *vfu_ctx, __u64 *offset, __u64 *size)
{
struct server_data *server_data = vfu_get_private(vfu_ctx);
- if (server_data->migration.state == VFU_MIGR_STATE_PRE_COPY) {
- assert(server_data->bar1_size >= server_data->migration.pending_bytes);
- *offset = server_data->bar1_size - server_data->migration.pending_bytes;
- } else if (server_data->migration.state == VFU_MIGR_STATE_STOP_AND_COPY) {
- *offset = 0;
- } else {
- assert(false); /* FIXME fail gracefully */
+ *offset = 0;
+ if (size != NULL) {
+ *size = server_data->migration.pending_bytes;
}
- *size = server_data->migration.pending_bytes;
return 0;
}
@@ -338,49 +314,35 @@ static ssize_t
migration_read_data(vfu_ctx_t *vfu_ctx, void *buf, __u64 size, __u64 offset)
{
struct server_data *server_data = vfu_get_private(vfu_ctx);
- uint8_t *p;
- size_t bar_size;
- /* FIXME need to validate data range */
- vfu_log(vfu_ctx, LOG_DEBUG, "read migration data %#llx-%#llx, %#llx remaining",
- offset, offset + size - 1, server_data->migration.pending_bytes);
-
- assert(size <= server_data->migration.pending_bytes);
+ if (server_data->migration.state != VFU_MIGR_STATE_PRE_COPY &&
+ server_data->migration.state != VFU_MIGR_STATE_STOP_AND_COPY)
+ {
+ return size;
+ }
/*
- * If in pre-copy state we copy BAR1, if in stop-and-copy state we copy
- * BAR0. This behavior is purely an artifact of this server implementation
- * simply to make it as simple as possible. Note that the client might go
- * from state running to stop-and-copy, completely skipping the pre-copy
- * state. This is legitimate but we don't support it for now.
+ * For ease of implementation we expect the client to read all migration
+ * data in one go; partial reads are not supported. This is allowed by VFIO
+ * however we don't yet support it. Similarly, when resuming, partial
+ * writes are supported by VFIO, however we don't in this sample.
*
- * FIXME implement transitioning from the running state straight to the
- * stop-and-copy state.
+ * If in pre-copy state we copy BAR1, if in stop-and-copy state we copy
+ * both BAR1 and BAR0. Since we always copy BAR1 in the stop-and-copy state,
+ * copying BAR1 in the pre-copy state is pointless. Fixing this requires
+ * more complex state tracking which exceeds the scope of this sample.
*/
- if (server_data->migration.state == VFU_MIGR_STATE_PRE_COPY) {
- p = server_data->bar1;
- bar_size = server_data->bar1_size;
- } else if (server_data->migration.state == VFU_MIGR_STATE_STOP_AND_COPY) {
- p = (uint8_t*)&server_data->bar0;
- bar_size = sizeof server_data->bar0;
- } else {
- /*
- * Reading from the migration region in any other state is undefined
- * (I think).
- */
- assert(false);
- return 0;
- }
- if (offset > bar_size) {
- errno = EINVAL;
- return -1;
+ if (offset != 0 || size != server_data->migration.pending_bytes) {
+ return -EINVAL;
}
- if (offset + size > bar_size) {
- size = bar_size - offset;
+
+ memcpy(buf, server_data->bar1, server_data->bar1_size);
+ if (server_data->migration.state == VFU_MIGR_STATE_STOP_AND_COPY) {
+ memcpy(buf + server_data->bar1_size, &server_data->bar0,
+ sizeof server_data->bar0);
}
- memcpy(buf, p + offset, size);
- server_data->migration.pending_bytes -= size;
+ server_data->migration.pending_bytes = 0;
return size;
}
@@ -389,36 +351,30 @@ static ssize_t
migration_write_data(vfu_ctx_t *vfu_ctx, void *data, __u64 size, __u64 offset)
{
struct server_data *server_data = vfu_get_private(vfu_ctx);
+ char *buf = data;
+ int ret;
assert(server_data != NULL);
assert(data != NULL);
- /*
- * During pre-copy state we save BAR1 and during stop-and-copy state we
- * save BAR0.
- */
- vfu_log(vfu_ctx, LOG_DEBUG,
- "apply device migration data %#llx-%#llx",
- offset, offset + size - 1);
-
- if (offset < server_data->bar1_size) {
- __u64 _size = MIN(size, server_data->bar1_size - offset);
- memcpy(server_data->bar1 + offset, data, _size);
- offset += _size;
- size -= _size;
+ if (offset != 0 || size < server_data->bar1_size) {
+ vfu_log(vfu_ctx, LOG_DEBUG, "XXX bad migration data write %#llx-%#llx",
+ offset, offset + size - 1);
+ return -EINVAL;
}
- if (offset >= server_data->bar1_size && size > 0) {
- int ret;
-
- /* FIXME should be able to write any valid subrange */
- assert(offset - server_data->bar1_size == 0);
- assert(size == sizeof server_data->bar0);
-
- ret = bar0_access(vfu_ctx, data, sizeof server_data->bar0, 0, true);
-
- assert(ret == (int)size); /* FIXME */
+ memcpy(server_data->bar1, buf, server_data->bar1_size);
+ buf += server_data->bar1_size;
+ size -= server_data->bar1_size;
+ if (size == 0) {
+ return 0;
+ }
+ if (size != sizeof server_data->bar0) {
+ return -EINVAL;
}
+ memcpy(&server_data->bar0, buf, sizeof server_data->bar0);
+ ret = bar0_access(vfu_ctx, buf, sizeof server_data->bar0, 0, true);
+ assert(ret == (int)size); /* FIXME */
return 0;
}
@@ -446,7 +402,6 @@ int main(int argc, char *argv[])
size_t bar1_size = 0x3000;
struct server_data server_data = {
.migration = {
- .migr_data_len = bar1_size + sizeof(time_t),
.state = VFU_MIGR_STATE_RUNNING
}
};
@@ -542,7 +497,7 @@ int main(int argc, char *argv[])
}
vfu_migration_t migration = {
- .size = server_data.migration.migr_data_len,
+ .size = bar1_size + sizeof(time_t),
.mmap_areas = mmap_areas,
.nr_mmap_areas = 2,
.callbacks = {