Currently information on protocol version specific things is split between
struct migrate_data, which lists the memory blocks to save and restore and
struct migrate_target_handlers which gives the per-version (target) pre and
post handlers to run.
In addition, despite having already looked up the version in the
migrate_data table at the top-level, we look it up again in
migrate_target_state() and do a similar lookup in target_handlers in
migrate_target_{pre,post}().
Combine the per-version information into a single struct migrate_version,
look it up once at the top level, then pass that through to the other
functions within migrate_meta.
Signed-off-by: David Gibson
---
migrate.c | 68 ++++++++++++++++++++-----------------------------------
migrate.h | 55 +++++++++++++++++++++-----------------------
2 files changed, 51 insertions(+), 72 deletions(-)
diff --git a/migrate.c b/migrate.c
index 4279d1f8..f9e967cf 100644
--- a/migrate.c
+++ b/migrate.c
@@ -42,19 +42,6 @@ static union migrate_header header = {
.voidp_size = htonl_constant(sizeof(void *)),
};
-/* Data sections for version 1 */
-static struct iovec sections_v1[] = {
- { &header, sizeof(header) },
-};
-
-/* Set of data versions */
-static struct migrate_data data_versions[] = {
- {
- 1, sections_v1,
- },
- { 0 },
-};
-
/* Handlers to call in source before sending data */
struct migrate_handler handlers_source_pre[] = {
{ flow_migrate_source_pre },
@@ -76,12 +63,18 @@ struct migrate_handler handlers_target_post_v1[] = {
{ 0 },
};
-/* Versioned sets of migration handlers */
-struct migrate_target_handlers target_handlers[] = {
+/* Data sections for version 1 */
+static struct iovec sections_v1[] = {
+ { &header, sizeof(header) },
+};
+
+/* Supported protocol versions */
+static const struct migrate_version versions[] = {
{
- 1,
- handlers_target_pre_v1,
- handlers_target_post_v1,
+ .v = 1,
+ .pre = handlers_target_pre_v1,
+ .sections = sections_v1,
+ .post = handlers_target_post_v1,
},
{ 0 },
};
@@ -116,17 +109,12 @@ static int migrate_source_pre(struct ctx *c, struct migrate_meta *m)
*/
static int migrate_source_state(int fd, const struct migrate_meta *m)
{
- static struct migrate_data *d;
int count, rc;
- (void)m;
-
- for (d = data_versions; d->v != MIGRATE_VERSION; d++);
-
- for (count = 0; d->sections[count].iov_len; count++);
+ for (count = 0; m->v->sections[count].iov_len; count++);
debug("Writing %u migration sections", count - 1 /* minus header */);
- rc = write_remainder(fd, d->sections, count, 0);
+ rc = write_remainder(fd, m->v->sections, count, 0);
if (rc < 0)
return errno;
@@ -160,6 +148,9 @@ static int migrate_source(struct ctx *c, int fd)
struct migrate_meta m;
int rc;
+ m.version = MIGRATE_VERSION;
+ for (m.v = versions; m.v->v != m.version; m.v++);
+
if ((rc = migrate_source_pre(c, &m))) {
err("Source pre-migration failed: %s, abort", strerror_(rc));
return rc;
@@ -185,19 +176,19 @@ static int migrate_source(struct ctx *c, int fd)
*/
static int migrate_target_read_header(int fd, struct migrate_meta *m)
{
- static struct migrate_data *d;
union migrate_header h;
if (read_all_buf(fd, &h, sizeof(h)))
return errno;
+ m->version = ntohl(h.version);
+
debug("Source magic: 0x%016" PRIx64 ", sizeof(void *): %u, version: %u",
- h.magic, ntohl(h.voidp_size), ntohl(h.version));
+ h.magic, ntohl(h.voidp_size), m->version);
- for (d = data_versions; d->v != ntohl(h.version) && d->v; d++);
- if (!d->v)
+ for (m->v = versions; m->v->v != m->version; m->v++);
+ if (!m->v->v)
return ENOTSUP;
- m->v = d->v;
if (h.magic == MIGRATE_MAGIC)
m->bswap = false;
@@ -235,12 +226,9 @@ static int migrate_target_read_header(int fd, struct migrate_meta *m)
*/
static int migrate_target_pre(struct ctx *c, struct migrate_meta *m)
{
- struct migrate_target_handlers *th;
struct migrate_handler *h;
- for (th = target_handlers; th->v != m->v && th->v; th++);
-
- for (h = th->pre; h->fn; h++) {
+ for (h = m->v->pre; h->fn; h++) {
int rc;
if ((rc = h->fn(c, m)))
@@ -261,16 +249,13 @@ static int migrate_target_pre(struct ctx *c, struct migrate_meta *m)
*/
static int migrate_target_state(int fd, const struct migrate_meta *m)
{
- static struct migrate_data *d;
unsigned cnt;
int rc;
- for (d = data_versions; d->v != m->v && d->v; d++);
-
- for (cnt = 0; d->sections[cnt + 1 /* skip header */].iov_len; cnt++);
+ for (cnt = 0; m->v->sections[cnt + 1 /* skip header */].iov_len; cnt++);
debug("Reading %u migration sections", cnt);
- rc = read_remainder(fd, d->sections + 1, cnt, 0);
+ rc = read_remainder(fd, m->v->sections + 1, cnt, 0);
if (rc < 0)
return errno;
@@ -284,12 +269,9 @@ static int migrate_target_state(int fd, const struct migrate_meta *m)
*/
static void migrate_target_post(struct ctx *c, struct migrate_meta *m)
{
- struct migrate_target_handlers *th;
struct migrate_handler *h;
- for (th = target_handlers; th->v != m->v && th->v; th++);
-
- for (h = th->post; h->fn; h++)
+ for (h = m->v->post; h->fn; h++)
h->fn(c, m);
}
diff --git a/migrate.h b/migrate.h
index 3432940d..b532bde0 100644
--- a/migrate.h
+++ b/migrate.h
@@ -6,24 +6,6 @@
#ifndef MIGRATE_H
#define MIGRATE_H
-/**
- * struct migrate_meta - Migration metadata
- * @v: Chosen migration data version, host order
- * @bswap: Source has opposite endianness
- * @peer_64b: Source uses 64-bit void *
- * @time_64b: Source uses 64-bit time_t
- * @flow_size: Size of union flow in source
- * @flow_sidx_size: Size of struct flow_sidx in source
- */
-struct migrate_meta {
- uint32_t v;
- bool bswap;
- bool source_64b;
- bool time_64b;
- size_t flow_size;
- size_t flow_sidx_size;
-};
-
/**
* union migrate_header - Migration header from source
* @magic: 0xB1BB1D1B0BB1D1B0, host order
@@ -46,15 +28,7 @@ union migrate_header {
uint8_t unused[65536];
};
-/**
- * struct migrate_data - Data sections for given source version
- * @v: Source version this applies to, host order
- * @sections: Array of data sections, NULL-terminated
- */
-struct migrate_data {
- uint32_t v;
- struct iovec *sections;
-};
+struct migrate_meta;
/**
* struct migrate_handler - Function to handle a specific data section
@@ -65,17 +39,40 @@ struct migrate_handler {
};
/**
- * struct migrate_target_handlers - Versioned sets of migration target handlers
+ * struct migrate_version - Handlers and data sections for a protocol version
* @v: Source version this applies to, host order
* @pre: Set of functions to execute in target before data copy
+ * @sections: Array of data sections, NULL-terminated
* @post: Set of functions to execute in target after data copy
*/
-struct migrate_target_handlers {
+struct migrate_version {
uint32_t v;
struct migrate_handler *pre;
+ struct iovec *sections;
struct migrate_handler *post;
};
+/**
+ * struct migrate_meta - Migration metadata
+ * @version: Version number, host order
+ * @v: Version information
+ * @bswap: Source has opposite endianness
+ * @peer_64b: Source uses 64-bit void *
+ * @time_64b: Source uses 64-bit time_t
+ * @flow_size: Size of union flow in source
+ * @flow_sidx_size: Size of struct flow_sidx in source
+ */
+struct migrate_meta {
+ uint32_t version;
+ const struct migrate_version *v;
+ bool bswap;
+ bool source_64b;
+ bool time_64b;
+ size_t flow_size;
+ size_t flow_sidx_size;
+};
+
+
void migrate_init(struct ctx *c);
void migrate_close(struct ctx *c);
void migrate_request(struct ctx *c, int fd, bool target);
--
2.48.1