From 23918b03060f6e572168fdde1798a905679d2e06 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Thu, 20 Nov 2008 16:06:21 -0500 Subject: SUNRPC: Fix a performance regression in the RPC authentication code Fix a regression reported by Max Kellermann whereby kernel profiling showed that his clients were spending 45% of their time in rpcauth_lookup_credcache. It turns out that although his processes had identical uid/gid/groups, generic_match() was failing to detect this, because the task->group_info pointers were not shared. This again lead to the creation of a huge number of identical credentials at the RPC layer. The regression is fixed by comparing the contents of task->group_info if the actual pointers are not identical. Signed-off-by: Trond Myklebust Signed-off-by: Linus Torvalds --- net/sunrpc/auth_generic.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) (limited to 'net/sunrpc') diff --git a/net/sunrpc/auth_generic.c b/net/sunrpc/auth_generic.c index 744b79fdcb1..4028502f052 100644 --- a/net/sunrpc/auth_generic.c +++ b/net/sunrpc/auth_generic.c @@ -133,13 +133,29 @@ static int generic_match(struct auth_cred *acred, struct rpc_cred *cred, int flags) { struct generic_cred *gcred = container_of(cred, struct generic_cred, gc_base); + int i; if (gcred->acred.uid != acred->uid || gcred->acred.gid != acred->gid || - gcred->acred.group_info != acred->group_info || gcred->acred.machine_cred != acred->machine_cred) - return 0; + goto out_nomatch; + + /* Optimisation in the case where pointers are identical... */ + if (gcred->acred.group_info == acred->group_info) + goto out_match; + + /* Slow path... */ + if (gcred->acred.group_info->ngroups != acred->group_info->ngroups) + goto out_nomatch; + for (i = 0; i < gcred->acred.group_info->ngroups; i++) { + if (GROUP_AT(gcred->acred.group_info, i) != + GROUP_AT(acred->group_info, i)) + goto out_nomatch; + } +out_match: return 1; +out_nomatch: + return 0; } void __init rpc_init_generic_auth(void) -- cgit v1.2.3 From 2da2c21d7508d34bc6d600df665d84871b65d2b9 Mon Sep 17 00:00:00 2001 From: Tom Tucker Date: Sun, 23 Nov 2008 09:58:08 -0600 Subject: Add a reference to sunrpc in svc_addsock The svc_addsock function adds transport instances without taking a reference on the sunrpc.ko module, however, the generic transport destruction code drops a reference when a transport instance is destroyed. Add a try_module_get call to the svc_addsock function for transport instances added by this function. Signed-off-by: Tom Tucker Signed-off-by: J. Bruce Fields Tested-by: Jeff Moyer --- net/sunrpc/svcsock.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'net/sunrpc') diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index 95293f549e9..a1951dcc577 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c @@ -1183,7 +1183,11 @@ int svc_addsock(struct svc_serv *serv, else if (so->state > SS_UNCONNECTED) err = -EISCONN; else { - svsk = svc_setup_socket(serv, so, &err, SVC_SOCK_DEFAULTS); + if (!try_module_get(THIS_MODULE)) + err = -ENOENT; + else + svsk = svc_setup_socket(serv, so, &err, + SVC_SOCK_DEFAULTS); if (svsk) { struct sockaddr_storage addr; struct sockaddr *sin = (struct sockaddr *)&addr; @@ -1196,7 +1200,8 @@ int svc_addsock(struct svc_serv *serv, spin_unlock_bh(&serv->sv_lock); svc_xprt_received(&svsk->sk_xprt); err = 0; - } + } else + module_put(THIS_MODULE); } if (err) { sockfd_put(so); -- cgit v1.2.3