On Mon, Sep 13, 2021 at 03:12:51PM +0800, Herbert Xu wrote: > When complex algorithms that depend on other algorithms are built > into the kernel, the order of registration must be done such that > the underlying algorithms are ready before the ones on top are > registered. As otherwise they would fail during the self-test > which is required during registration. > > In the past we have used subsystem initialisation ordering to > guarantee this. The number of such precedence levels are limited > and they may cause ripple effects in other subsystems. > > This patch solves this problem by delaying all self-tests during > boot-up for built-in algorithms. They will be tested either when > something else in the kernel requests for them, or when we have > finished registering all built-in algorithms, whichever comes > earlier. Are there any specific examples that you could give? > int crypto_register_alg(struct crypto_alg *alg) > { > struct crypto_larval *larval; > + bool tested; > int err; > > alg->cra_flags &= ~CRYPTO_ALG_DEAD; > @@ -421,12 +402,15 @@ int crypto_register_alg(struct crypto_alg *alg) > > down_write(&crypto_alg_sem); > larval = __crypto_register_alg(alg); > + tested = static_key_enabled(&crypto_boot_test_finished); > + larval->tested = tested; 'tested' is set before the algorithm has actually been tested, and it sounds like the same as CRYPTO_ALG_TESTED which already exists. Maybe it should be called something else, like 'test_started'? > +static void __init crypto_start_tests(void) > +{ > + for (;;) { > + struct crypto_larval *larval = NULL; > + struct crypto_alg *q; > + > + down_write(&crypto_alg_sem); > + > + list_for_each_entry(q, &crypto_alg_list, cra_list) { > + struct crypto_larval *l; > + > + if (!crypto_is_larval(q)) > + continue; > + > + l = (void *)q; > + > + if (!crypto_is_test_larval(l)) > + continue; > + > + if (l->tested) > + continue; > + > + l->tested = true; > + larval = l; > + break; > + } > + > + up_write(&crypto_alg_sem); > + > + if (!larval) > + break; > + > + crypto_wait_for_test(larval); > + } Is there a way to continue iterating from the previous algorithm, so that this doesn't take quadratic time? > + > + static_branch_enable(&crypto_boot_test_finished); > +} > + > static int __init crypto_algapi_init(void) > { > crypto_init_proc(); > + crypto_start_tests(); A comment explaining why the tests aren't run until late_initcall would be helpful. People shouldn't have to dig through commit messages to understand the code. Also, did you check whether there is anything that relies on the crypto API being available before or during late_initcall? That wouldn't work with this new approach, right? - Eric