MINOR: ssl: Factorize ckch instance rebuild process

The ckch instances for a given ckch_store have to be rebuilt when a
certificate is updated during runtime (via cli or lua). The code was
duplicated in lua so factorizing the actual loop avoids future errors
if the code changes. The new 'ckch_store_rebuild_instances' will have a
dedicated 0 return code if it needs to be called again (because of the
yielding logic since ckch instance rebuild might take some time).
This commit is contained in:
Remi Tricot-Le Breton 2026-05-06 14:16:40 +02:00 committed by William Lallemand
parent efe6c97488
commit 53ecb81781
3 changed files with 75 additions and 52 deletions

View File

@ -50,6 +50,8 @@ void ckch_store_replace(struct ckch_store *old_ckchs, struct ckch_store *new_ckc
int ckch_store_load_files(struct ckch_conf *f, struct ckch_store *c, int cli, const char *file, int linenum, char **err);
int ckch_store_create(char *path, char **err);
int ckch_store_load_payload(char *path, char *payload, char **err);
int ckch_store_rebuild_instances(struct ckch_store *old_ckchs, struct ckch_store *new_ckchs,
struct ckch_inst **ckchi, int max, int *count, char **err);
/* ckch_conf functions */

View File

@ -13686,40 +13686,25 @@ __LJMP static int hlua_ckch_commit_yield(lua_State *L, int status, lua_KContext
{
struct ckch_inst **lua_ckchi = lua_touserdata(L, -1);
struct ckch_store **lua_ckchs = lua_touserdata(L, -2);
struct ckch_inst *ckchi = *lua_ckchi;
struct ckch_store *old_ckchs = lua_ckchs[0];
struct ckch_store *new_ckchs = lua_ckchs[1];
struct hlua *hlua;
char *err = NULL;
int y = 1;
int retval = 0;
hlua = hlua_gethlua(L);
/* get the first ckchi to copy */
if (ckchi == NULL)
ckchi = LIST_ELEM(old_ckchs->ckch_inst.n, typeof(ckchi), by_ckchs);
/* walk through the old ckch_inst and creates new ckch_inst using the updated ckchs */
list_for_each_entry_from(ckchi, &old_ckchs->ckch_inst, by_ckchs) {
struct ckch_inst *new_inst;
retval = ckch_store_rebuild_instances(old_ckchs, new_ckchs, lua_ckchi,
hlua ? 10 : -1, &y, &err);
/* it takes a lot of CPU to creates SSL_CTXs, so we yield every 10 CKCH instances
* during runtime
*/
if (hlua && (y % 10) == 0) {
*lua_ckchi = ckchi;
task_wakeup(hlua->task, TASK_WOKEN_MSG);
MAY_LJMP(hlua_yieldk(L, 0, 0, hlua_ckch_commit_yield, TICK_ETERNITY, 0));
}
if (ckch_inst_rebuild(new_ckchs, ckchi, &new_inst, &err))
goto error;
/* link the new ckch_inst to the duplicate */
LIST_APPEND(&new_ckchs->ckch_inst, &new_inst->by_ckchs);
y++;
if (retval < 0)
goto error;
else if (retval == 0) {
/* yield */
task_wakeup(hlua->task, TASK_WOKEN_MSG);
MAY_LJMP(hlua_yieldk(L, 0, 0, hlua_ckch_commit_yield, TICK_ETERNITY, 0));
}
/* The generation is finished, we can insert everything */

View File

@ -2900,6 +2900,51 @@ void ckch_store_replace(struct ckch_store *old_ckchs, struct ckch_store *new_ckc
}
/*
* Rebuild all the ckch instances from <old_ckchs> into <new_ckchs>, using
* <ckchi> as the first instance to manage (in case of reentry), and process at
* most <max> instances at a time. <count> will be the actual amount of
* instances rebuilt.
* Return -1 in case of error, 1 if all the instances were rebuilt, 0 if <max>
* instances were built and the function should be called again.
*/
int ckch_store_rebuild_instances(struct ckch_store *old_ckchs, struct ckch_store *new_ckchs,
struct ckch_inst **ckchi, int max, int *count, char **err)
{
if (!count)
return -1;
*count = 0;
/* we didn't start yet, set it to the first elem */
if (*ckchi == NULL)
*ckchi = LIST_ELEM(old_ckchs->ckch_inst.n, struct ckch_inst*, by_ckchs);
/* walk through the old ckch_inst and creates new ckch_inst using the updated ckchs */
list_for_each_entry_from((*ckchi), &old_ckchs->ckch_inst, by_ckchs) {
struct ckch_inst *new_inst;
/* it takes a lot of CPU to creates SSL_CTXs, so we yield every <max> CKCH instances */
if (max > 0 && *count >= max) {
/* yield */
return 0;
}
if (ckch_inst_rebuild(new_ckchs, *ckchi, &new_inst, err)) {
/* error */
return -1;
}
/* link the new ckch_inst to the duplicate */
LIST_APPEND(&new_ckchs->ckch_inst, &new_inst->by_ckchs);
(*count)++;
}
return 1;
}
/*
* This function tries to create the new ckch_inst and their SNIs
*
@ -2910,7 +2955,7 @@ static int cli_io_handler_commit_cert(struct appctx *appctx)
struct commit_cert_ctx *ctx = appctx->svcctx;
int y = 0;
struct ckch_store *old_ckchs, *new_ckchs = NULL;
struct ckch_inst *ckchi;
int retval = 0;
usermsgs_clr("CLI");
while (1) {
@ -2935,39 +2980,30 @@ static int cli_io_handler_commit_cert(struct appctx *appctx)
old_ckchs = ctx->old_ckchs;
new_ckchs = ctx->new_ckchs;
/* get the next ckchi to regenerate */
ckchi = ctx->next_ckchi;
/* we didn't start yet, set it to the first elem */
if (ckchi == NULL)
ckchi = LIST_ELEM(old_ckchs->ckch_inst.n, typeof(ckchi), by_ckchs);
/* Rebuild at most 10 ckch instances before yielding */
retval = ckch_store_rebuild_instances(old_ckchs, new_ckchs, &ctx->next_ckchi,
10, &y, &ctx->err);
/* walk through the old ckch_inst and creates new ckch_inst using the updated ckchs */
list_for_each_entry_from(ckchi, &old_ckchs->ckch_inst, by_ckchs) {
struct ckch_inst *new_inst;
if (retval < 0) {
ctx->state = CERT_ST_ERROR;
goto error;
} else {
while (y != 0) {
/* display one dot per new instance */
if (applet_putstr(appctx, ".") == -1)
/* We might not display the proper number of
* dots but the instances were actually rebuilt. */
goto yield;
--y;
}
/* save the next ckchi to compute in case of yield */
ctx->next_ckchi = ckchi;
/* it takes a lot of CPU to creates SSL_CTXs, so we yield every 10 CKCH instances */
if (y >= 10) {
if (retval == 0) {
/* yield */
applet_have_more_data(appctx); /* let's come back later */
goto yield;
}
/* display one dot per new instance */
if (applet_putstr(appctx, ".") == -1)
goto yield;
ctx->err = NULL;
if (ckch_inst_rebuild(new_ckchs, ckchi, &new_inst, &ctx->err)) {
ctx->state = CERT_ST_ERROR;
goto error;
}
/* link the new ckch_inst to the duplicate */
LIST_APPEND(&new_ckchs->ckch_inst, &new_inst->by_ckchs);
y++;
}
ctx->state = CERT_ST_INSERT;
__fallthrough;
case CERT_ST_INSERT: