aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2013-07-10 15:33:01 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2013-07-10 15:58:55 -0400
commiteeee245268c951262b861bc1be4e9dc812352499 (patch)
tree055c5d4ea0406bbb5457052ee85148b5f9746cf7
parent4f8568cb5290295c384d5c1328c52790e33a8a0d (diff)
SUNRPC: Fix a deadlock in rpc_client_register()
Commit 384816051ca9125cd54750e59c780c2a2655fa4f (SUNRPC: fix races on PipeFS MOUNT notifications) introduces a regression when we call rpc_setup_pipedir() with RPCSEC_GSS as the auth flavour. By calling rpcauth_create() while holding the sn->pipefs_sb_lock, we end up deadlocking in gss_pipes_dentries_create_net(). Fix is to register the client and release the mutex before calling rpcauth_create(). Reported-by: Weston Andros Adamson <dros@netapp.com> Tested-by: Weston Andros Adamson <dros@netapp.com> Cc: Stanislav Kinsbursky <skinsbursky@parallels.com> Cc: <stable@vger.kernel.org> # : 3848160: SUNRPC: fix races on PipeFS MOUNT Cc: <stable@vger.kernel.org> # : e73f4cc: SUNRPC: split client creation Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r--net/sunrpc/clnt.c16
1 files changed, 9 insertions, 7 deletions
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index f0339ae9bf37..aa401560777b 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -290,7 +290,7 @@ static int rpc_client_register(const struct rpc_create_args *args,
290 struct rpc_auth *auth; 290 struct rpc_auth *auth;
291 struct net *net = rpc_net_ns(clnt); 291 struct net *net = rpc_net_ns(clnt);
292 struct super_block *pipefs_sb; 292 struct super_block *pipefs_sb;
293 int err = 0; 293 int err;
294 294
295 pipefs_sb = rpc_get_sb_net(net); 295 pipefs_sb = rpc_get_sb_net(net);
296 if (pipefs_sb) { 296 if (pipefs_sb) {
@@ -299,6 +299,10 @@ static int rpc_client_register(const struct rpc_create_args *args,
299 goto out; 299 goto out;
300 } 300 }
301 301
302 rpc_register_client(clnt);
303 if (pipefs_sb)
304 rpc_put_sb_net(net);
305
302 auth = rpcauth_create(args->authflavor, clnt); 306 auth = rpcauth_create(args->authflavor, clnt);
303 if (IS_ERR(auth)) { 307 if (IS_ERR(auth)) {
304 dprintk("RPC: Couldn't create auth handle (flavor %u)\n", 308 dprintk("RPC: Couldn't create auth handle (flavor %u)\n",
@@ -306,16 +310,14 @@ static int rpc_client_register(const struct rpc_create_args *args,
306 err = PTR_ERR(auth); 310 err = PTR_ERR(auth);
307 goto err_auth; 311 goto err_auth;
308 } 312 }
309 313 return 0;
310 rpc_register_client(clnt); 314err_auth:
315 pipefs_sb = rpc_get_sb_net(net);
316 __rpc_clnt_remove_pipedir(clnt);
311out: 317out:
312 if (pipefs_sb) 318 if (pipefs_sb)
313 rpc_put_sb_net(net); 319 rpc_put_sb_net(net);
314 return err; 320 return err;
315
316err_auth:
317 __rpc_clnt_remove_pipedir(clnt);
318 goto out;
319} 321}
320 322
321static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, struct rpc_xprt *xprt) 323static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, struct rpc_xprt *xprt)