public inbox for passt-dev@passt.top
 help / color / mirror / code / Atom feed
From: David Gibson <david@gibson.dropbear.id.au>
To: passt-dev@passt.top, Stefano Brivio <sbrivio@redhat.com>
Cc: David Gibson <david@gibson.dropbear.id.au>
Subject: [PATCH 1/2] migrate: Merge protocol version information into one table
Date: Fri, 31 Jan 2025 15:52:14 +1100	[thread overview]
Message-ID: <20250131045215.1368543-2-david@gibson.dropbear.id.au> (raw)
In-Reply-To: <20250131045215.1368543-1-david@gibson.dropbear.id.au>

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@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);
-- 
@@ -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


  reply	other threads:[~2025-01-31  4:52 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-01-31  4:52 [PATCH 0/2] Fancier version handling for migration David Gibson
2025-01-31  4:52 ` David Gibson [this message]
2025-01-31  5:53   ` [PATCH 1/2] migrate: Merge protocol version information into one table Stefano Brivio
2025-01-31  6:17     ` David Gibson
2025-01-31  4:52 ` [PATCH 2/2] migrate: More sophisticated versioning David Gibson
2025-01-31  5:53   ` Stefano Brivio
2025-01-31  6:21     ` David Gibson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250131045215.1368543-2-david@gibson.dropbear.id.au \
    --to=david@gibson.dropbear.id.au \
    --cc=passt-dev@passt.top \
    --cc=sbrivio@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://passt.top/passt

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for IMAP folder(s).