diff --git a/include/haproxy/ssl_ckch.h b/include/haproxy/ssl_ckch.h index 051927dda..414c7a3ea 100644 --- a/include/haproxy/ssl_ckch.h +++ b/include/haproxy/ssl_ckch.h @@ -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 */ diff --git a/src/hlua.c b/src/hlua.c index 97c290ec5..cde144ab2 100644 --- a/src/hlua.c +++ b/src/hlua.c @@ -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 */ diff --git a/src/ssl_ckch.c b/src/ssl_ckch.c index 85676ec71..2651469af 100644 --- a/src/ssl_ckch.c +++ b/src/ssl_ckch.c @@ -2900,6 +2900,51 @@ void ckch_store_replace(struct ckch_store *old_ckchs, struct ckch_store *new_ckc } +/* + * Rebuild all the ckch instances from into , using + * as the first instance to manage (in case of reentry), and process at + * most instances at a time. will be the actual amount of + * instances rebuilt. + * Return -1 in case of error, 1 if all the instances were rebuilt, 0 if + * 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 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: