gss_mech_get_by_OID() calls request_module() before it looks at the list of registered mechanisms, so every lookup forks a modprobe, even when the mechanism is already registered or built in. gss_mech_get_by_name() and gss_mech_get_by_pseudoflavor() only load the module when the lookup fails. The read handler of /proc/net/rpc/gss_krb5_enctypes uses this lookup, so every read() of that file runs modprobe, two per cat. The file is present in every /proc//net/rpc and /proc//task//net/rpc directory, and LTP read_all gives each read one second. On a slow board in KernelCI its workers stall on this file and the test times out. Look up the mechanism first and call request_module() only when it is not found, as the other two lookup functions do. Reported-by: kernelci.org bot Closes: https://d.kernelci.org/test/maestro:6af225865b429d354e253b9b Fixes: f783288f0cf4 ("SUNRPC: Load GSS kernel module by OID") Signed-off-by: Sasha Levin --- net/sunrpc/auth_gss/gss_mech_switch.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/net/sunrpc/auth_gss/gss_mech_switch.c b/net/sunrpc/auth_gss/gss_mech_switch.c index 78eab245f94a7..d8b6ff9505399 100644 --- a/net/sunrpc/auth_gss/gss_mech_switch.c +++ b/net/sunrpc/auth_gss/gss_mech_switch.c @@ -157,14 +157,9 @@ struct gss_api_mech * gss_mech_get_by_name(const char *name) return gm; } -struct gss_api_mech *gss_mech_get_by_OID(struct rpcsec_gss_oid *obj) +static struct gss_api_mech *_gss_mech_get_by_OID(struct rpcsec_gss_oid *obj) { struct gss_api_mech *pos, *gm = NULL; - char buf[32]; - - if (sprint_oid(obj->data, obj->len, buf, sizeof(buf)) < 0) - return NULL; - request_module("rpc-auth-gss-%s", buf); rcu_read_lock(); list_for_each_entry_rcu(pos, ®istered_mechs, gm_list) { @@ -177,6 +172,22 @@ struct gss_api_mech *gss_mech_get_by_OID(struct rpcsec_gss_oid *obj) } } rcu_read_unlock(); + return gm; +} + +struct gss_api_mech *gss_mech_get_by_OID(struct rpcsec_gss_oid *obj) +{ + struct gss_api_mech *gm; + char buf[32]; + + if (sprint_oid(obj->data, obj->len, buf, sizeof(buf)) < 0) + return NULL; + + gm = _gss_mech_get_by_OID(obj); + if (!gm) { + request_module("rpc-auth-gss-%s", buf); + gm = _gss_mech_get_by_OID(obj); + } if (!gm) trace_rpcgss_oid_to_mech(buf); return gm; -- 2.53.0