On Mon, 3 Feb 2025 20:26:15 +1100 David Gibson <david(a)gibson.dropbear.id.au> wrote:+/* Stages for version 1 */ +static const struct migrate_stage stages_v1[] = { + { + .name = "flow pre", + .source = flow_migrate_source_pre, + .target = NULL, + }, + DATA_STAGE(flow_first_free), + DATA_STAGE(flowtab), + DATA_STAGE(flow_hashtab), + DATA_STAGE(g_hash_secret),...so this one for g_hash_secret (which is the abomination I wanted to drop) would eventually turn into a function? It looks neat, I'm just not sure if we'll really have "data stages" after I change the approach to only transfer the data we need as you suggested. Is that part of your pending queue by the way, or should I go ahead with it?[...] /** - * struct migrate_data - Data sections for given source version - * @v: Source version this applies to, host order - * @sections: Array of data sections, NULL-terminated + * migrate_cb_t - Callback function to implement one migration stage */ -struct migrate_data { - uint32_t v; - struct iovec *sections; -}; +typedef int (*migrate_cb_t)(struct ctx *c, struct migrate_meta *m, + const struct migrate_stage *stage, int fd);typedef is really annoying, we already have a flow_sidx which kind of made sense, but this has really no advantage over something like: struct migrate_handler { int (*fn)(struct ctx *c, struct migrate_meta *m); }; -- Stefano