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 <david(a)gibson.dropbear.id.au> --- 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