diff --git a/backport-drbdadm-aggregate-multiple-config-to-test.patch b/backport-drbdadm-aggregate-multiple-config-to-test.patch new file mode 100644 index 0000000000000000000000000000000000000000..c8d72978a6ffecb22c41d7a67e061a3076745272 --- /dev/null +++ b/backport-drbdadm-aggregate-multiple-config-to-test.patch @@ -0,0 +1,294 @@ +From b13fb45cfd84d16334d48711dba292197c985c8d Mon Sep 17 00:00:00 2001 +From: Lars Ellenberg +Date: Tue, 13 May 2025 19:10:00 +0200 +Subject: [PATCH 087/200] drbdadm: aggregate multiple --config-to-test + +Its counterpart --config-to-exclude is already aggregating. + +This should allow to "plausibility check" multiple changes to multiple config +files with one invocation. +--- + user/v9/drbdadm_main.c | 70 +++++++++++++++++++++++++++++++++++------- + 1 file changed, 59 insertions(+), 11 deletions(-) + +diff --git a/user/v9/drbdadm_main.c b/user/v9/drbdadm_main.c +index ea26ce85..b2dc77b1 100644 +--- a/user/v9/drbdadm_main.c ++++ b/user/v9/drbdadm_main.c +@@ -146,9 +146,63 @@ const char *hostname; + int line = 1; + int fline; + ++/* for --config-to-test ++ */ ++struct ad_hoc_string_table { ++ const char **entries; ++ size_t N_used; ++ size_t N_allocated; ++} config_to_test_table; ++ ++static void ad_hoc_string_table_add(struct ad_hoc_string_table *tab, const char *val) ++{ ++ const unsigned int step = 64; ++ assert(tab); ++ ++ if (tab->N_used >= tab->N_allocated) { ++ // reallocarray(); ... but we still want to build on rhel7 :-| ++ tab->entries = realloc(tab->entries, ++ (tab->N_allocated + step) * sizeof(*(tab->entries))); ++ if (!tab->entries) { ++ log_err("out of memory: %m\n"); ++ exit(20); ++ } ++ tab->N_allocated += step; ++ } ++ tab->entries[tab->N_used++] = val; ++} ++ ++static void config_to_test_add(const char *arg) ++{ ++ char *path; ++ ++ path = realpath(arg, NULL); ++ if (!path) ++ path = strdup(arg); ++ if (!path) { ++ log_err("out of memory: %m\n"); ++ exit(20); ++ } ++ ad_hoc_string_table_add(&config_to_test_table, path); ++} ++ ++static void config_to_test_include(const char *path) ++{ ++ FILE *f; ++ ++ // fprintf(stderr, "config-to-test: %s\n", path); ++ f = fopen(path, "r"); ++ if (!f) { ++ log_err("Can not open '%s'.\n", path); ++ exit(E_EXEC_ERROR); ++ } ++ include_file(f, path); ++} ++ ++ + const char *config_file = NULL; + const char *config_save = NULL; +-const char *config_test = NULL; ++ + struct resources config = STAILQ_HEAD_INITIALIZER(config); + struct d_resource *common = NULL; + struct ifreq *ifreq_list = NULL; +@@ -3223,7 +3277,7 @@ int parse_options(int argc, char **argv, struct adm_cmd **cmd, char ***resource_ + config_file = tmp; + break; + case 't': +- config_test = optarg; ++ config_to_test_add(optarg); + break; + case 'E': + /* Remember as absolute name */ +@@ -3543,7 +3597,7 @@ int main(int argc, char **argv) + if (rv) + return rv; + +- if (config_test && !cmd->test_config) { ++ if (config_to_test_table.N_used && !cmd->test_config) { + log_err("The --config-to-test (-t) option is only allowed " + "with the dump and sh-nop commands\n"); + exit(E_USAGE); +@@ -3588,14 +3642,8 @@ int main(int argc, char **argv) + my_parse(); + fclose(yyin); + +- if (config_test) { +- FILE *f = fopen(config_test, "r"); +- if (!f) { +- log_err("Can not open '%s'.\n", config_test); +- exit(E_EXEC_ERROR); +- } +- include_file(f, config_test); +- } ++ for (i = 0; i < config_to_test_table.N_used; i++) ++ config_to_test_include(config_to_test_table.entries[i]); + + if (!config_valid) + exit(E_CONFIG_INVALID); +-- +2.33.1.windows.1 + +From 6407c4242223d03bc2df7141d61bca3fb5b4803d Mon Sep 17 00:00:00 2001 +From: Lars Ellenberg +Date: Thu, 15 May 2025 16:38:02 +0200 +Subject: [PATCH 088/200] drbdadm: reset ctx in ctx_by_* functions + +Source code pattern is: + r = ctx_by_name(&ctx, "id", ...); + if (!ctx.res) + log error + if (r) + exit 1 + +If you specify a number of resources on the command line, +and the first one is defined, we forgot to log the error, +but still do the exit 1. + +We need to reset ctx with each call to ctx_by_...(). + +This also changes the logic: +we no longer exit on the first "non-existing" resource, but log the error, +accumulate the "exit 1", then still continue with all other resource names +that are listed on the command line. +--- + user/v84/drbdadm_main.c | 4 +--- + user/v9/drbdadm_main.c | 15 +++++++++++++-- + 2 files changed, 14 insertions(+), 5 deletions(-) + +diff --git a/user/v84/drbdadm_main.c b/user/v84/drbdadm_main.c +index 865cf6ca..36b8cd9d 100644 +--- a/user/v84/drbdadm_main.c ++++ b/user/v84/drbdadm_main.c +@@ -2335,9 +2335,7 @@ int ctx_by_name(struct cfg_ctx *ctx, const char *id) + char *vol_id = strchr(name, '/'); + unsigned vol_nr = ~0U; + +- ctx->res = NULL; +- ctx->vol = NULL; +- ++ *ctx = (struct cfg_ctx){ NULL, }; + if (vol_id) { + *vol_id++ = '\0'; + vol_nr = m_strtoll(vol_id, 0); +diff --git a/user/v9/drbdadm_main.c b/user/v9/drbdadm_main.c +index b2dc77b1..37ebfac8 100644 +--- a/user/v9/drbdadm_main.c ++++ b/user/v9/drbdadm_main.c +@@ -2390,6 +2390,7 @@ int ctx_by_minor(struct cfg_ctx *ctx, const char *id) + struct d_volume *vol; + unsigned int mm; + ++ *ctx = (struct cfg_ctx){ NULL, }; + mm = minor_by_id(id); + if (mm == -1U) + return -ENOENT; +@@ -2462,6 +2463,7 @@ int ctx_by_name(struct cfg_ctx *ctx, const char *id, checks check) + unsigned vol_nr = ~0U; + int connections_found = 0; + ++ *ctx = (struct cfg_ctx){ NULL, }; + res_name = input; + vol_id = strrchr(input, '/'); + if (vol_id) { +@@ -3749,10 +3751,19 @@ int main(int argc, char **argv) + } + if (!ctx.res) { + log_err("'%s' not defined in your config (for this host).\n", resource_names[i]); +- exit(E_USAGE); ++ /* Maybe we have more luck with the next argument? ++ * Record an "exit 1" if we still have 0. */ ++ if (rv == 0) ++ rv = 1; ++ continue; + } +- if (r) ++ if (r) { ++ /* if ctx.res == NULL, we reported above already; ++ * if ctx.res != NULL AND r != 0 ... that's unexpected. */ ++ if (ctx.res != NULL) ++ log_err("'%s' unexpected ctx_by_* result r=%d\n", resource_names[i], r); + exit(E_USAGE); ++ } + if (!cmd->vol_id_required && !cmd->iterate_volumes && ctx.vol != NULL && !cmd->vol_id_optional) { + if (ctx.vol->implicit) + ctx.vol = NULL; +-- +2.33.1.windows.1 + +From 6407c4242223d03bc2df7141d61bca3fb5b4803d Mon Sep 17 00:00:00 2001 +From: Lars Ellenberg +Date: Thu, 15 May 2025 16:38:02 +0200 +Subject: [PATCH 088/200] drbdadm: reset ctx in ctx_by_* functions + +Source code pattern is: + r = ctx_by_name(&ctx, "id", ...); + if (!ctx.res) + log error + if (r) + exit 1 + +If you specify a number of resources on the command line, +and the first one is defined, we forgot to log the error, +but still do the exit 1. + +We need to reset ctx with each call to ctx_by_...(). + +This also changes the logic: +we no longer exit on the first "non-existing" resource, but log the error, +accumulate the "exit 1", then still continue with all other resource names +that are listed on the command line. +--- + user/v84/drbdadm_main.c | 4 +--- + user/v9/drbdadm_main.c | 15 +++++++++++++-- + 2 files changed, 14 insertions(+), 5 deletions(-) + +diff --git a/user/v84/drbdadm_main.c b/user/v84/drbdadm_main.c +index 865cf6ca..36b8cd9d 100644 +--- a/user/v84/drbdadm_main.c ++++ b/user/v84/drbdadm_main.c +@@ -2335,9 +2335,7 @@ int ctx_by_name(struct cfg_ctx *ctx, const char *id) + char *vol_id = strchr(name, '/'); + unsigned vol_nr = ~0U; + +- ctx->res = NULL; +- ctx->vol = NULL; +- ++ *ctx = (struct cfg_ctx){ NULL, }; + if (vol_id) { + *vol_id++ = '\0'; + vol_nr = m_strtoll(vol_id, 0); +diff --git a/user/v9/drbdadm_main.c b/user/v9/drbdadm_main.c +index b2dc77b1..37ebfac8 100644 +--- a/user/v9/drbdadm_main.c ++++ b/user/v9/drbdadm_main.c +@@ -2390,6 +2390,7 @@ int ctx_by_minor(struct cfg_ctx *ctx, const char *id) + struct d_volume *vol; + unsigned int mm; + ++ *ctx = (struct cfg_ctx){ NULL, }; + mm = minor_by_id(id); + if (mm == -1U) + return -ENOENT; +@@ -2462,6 +2463,7 @@ int ctx_by_name(struct cfg_ctx *ctx, const char *id, checks check) + unsigned vol_nr = ~0U; + int connections_found = 0; + ++ *ctx = (struct cfg_ctx){ NULL, }; + res_name = input; + vol_id = strrchr(input, '/'); + if (vol_id) { +@@ -3749,10 +3751,19 @@ int main(int argc, char **argv) + } + if (!ctx.res) { + log_err("'%s' not defined in your config (for this host).\n", resource_names[i]); +- exit(E_USAGE); ++ /* Maybe we have more luck with the next argument? ++ * Record an "exit 1" if we still have 0. */ ++ if (rv == 0) ++ rv = 1; ++ continue; + } +- if (r) ++ if (r) { ++ /* if ctx.res == NULL, we reported above already; ++ * if ctx.res != NULL AND r != 0 ... that's unexpected. */ ++ if (ctx.res != NULL) ++ log_err("'%s' unexpected ctx_by_* result r=%d\n", resource_names[i], r); + exit(E_USAGE); ++ } + if (!cmd->vol_id_required && !cmd->iterate_volumes && ctx.vol != NULL && !cmd->vol_id_optional) { + if (ctx.vol->implicit) + ctx.vol = NULL; +-- +2.33.1.windows.1 + diff --git a/drbd.spec b/drbd.spec index 47ebe506619c02588e04231ef7ec4a605b0575f4..f76413435b4d49186dd38f08bfc0a28f6caa8244 100644 --- a/drbd.spec +++ b/drbd.spec @@ -1,7 +1,7 @@ Name: drbd Summary: DRBD user-land tools and scripts Version: 9.31.0 -Release: 7 +Release: 8 Source0: http://www.linbit.com/downloads/%{name}/utils/%{name}-utils-%{version}.tar.gz Patch0: drbd-utils-9.12.2-disable_xsltproc_network_read.patch Patch1: drbd-utils-9.15.0-make_configure-workaround.patch @@ -11,6 +11,7 @@ Patch4: backport-build-rpm-don-t-try-to-rm-drbdmon.8.gz-in-preun.patch Patch5: backport-drbdmeta-it-is-initialize-bitmap-not-i-b-mode.patch Patch6: backport-drbdadm-don-t-attempt-to-parse-a-directory-as-config.patch Patch7: backport-drbdadm-add-const-qualifier-to-char-for-file-names.patch +Patch8: backport-drbdadm-aggregate-multiple-config-to-test.patch License: GPL-2.0-or-later ExclusiveOS: linux @@ -202,6 +203,10 @@ management utility. %systemd_preun drbd.service %changelog +* Thu Dec 04 2025 liupei - 9.31.0-8 +- drbdadm: aggregate multiple --config-to-test +- drbdadm: reset ctx in ctx_by_* functions + * Tue Dec 02 2025 liupei - 9.31.0-7 - drbdadm: add const qualifier to char* for file names - drbdadm: drop trailing '.' from error message