aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
author\"J. Bruce Fields\ <bfields@citi.umich.edu>2008-12-23 16:10:52 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2008-12-23 16:10:52 -0500
commit79a3f20b641f9f93787ada49d1d7cfa98ee5a11e (patch)
tree2f7d9f49b18388eb61400e383a9c5c4b070f1915 /net
parentcf81939d6fcdf381fcb069d780c29eceb516bccd (diff)
rpc: use count of pipe openers to wait for first open
Introduce a global variable pipe_version which will eventually be used to keep track of which version of the upcall gssd is using. For now, though, it only keeps track of whether any pipe is open or not; it is negative if not, zero if one is opened. We use this to wait for the first gssd to open a pipe. (Minor digression: note this waits only for the very first open of any pipe, not for the first open of a pipe for a given auth; thus we still need the RPC_PIPE_WAIT_FOR_OPEN behavior to wait for gssd to open new pipes that pop up on subsequent mounts.) Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'net')
-rw-r--r--net/sunrpc/auth_gss/auth_gss.c64
1 files changed, 61 insertions, 3 deletions
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index 51aa27d32b5a..e451d104a434 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -75,7 +75,12 @@ struct gss_auth {
75 struct dentry *dentry; 75 struct dentry *dentry;
76}; 76};
77 77
78/* pipe_version >= 0 if and only if someone has a pipe open. */
79static int pipe_version = -1;
78static atomic_t pipe_users = ATOMIC_INIT(0); 80static atomic_t pipe_users = ATOMIC_INIT(0);
81static DEFINE_SPINLOCK(pipe_version_lock);
82static struct rpc_wait_queue pipe_version_rpc_waitqueue;
83static DECLARE_WAIT_QUEUE_HEAD(pipe_version_waitqueue);
79 84
80static void gss_free_ctx(struct gss_cl_ctx *); 85static void gss_free_ctx(struct gss_cl_ctx *);
81static struct rpc_pipe_ops gss_upcall_ops; 86static struct rpc_pipe_ops gss_upcall_ops;
@@ -234,12 +239,34 @@ struct gss_upcall_msg {
234 struct gss_cl_ctx *ctx; 239 struct gss_cl_ctx *ctx;
235}; 240};
236 241
242static int get_pipe_version(void)
243{
244 int ret;
245
246 spin_lock(&pipe_version_lock);
247 if (pipe_version >= 0) {
248 atomic_inc(&pipe_users);
249 ret = 0;
250 } else
251 ret = -EAGAIN;
252 spin_unlock(&pipe_version_lock);
253 return ret;
254}
255
256static void put_pipe_version(void)
257{
258 if (atomic_dec_and_lock(&pipe_users, &pipe_version_lock)) {
259 pipe_version = -1;
260 spin_unlock(&pipe_version_lock);
261 }
262}
263
237static void 264static void
238gss_release_msg(struct gss_upcall_msg *gss_msg) 265gss_release_msg(struct gss_upcall_msg *gss_msg)
239{ 266{
240 if (!atomic_dec_and_test(&gss_msg->count)) 267 if (!atomic_dec_and_test(&gss_msg->count))
241 return; 268 return;
242 atomic_dec(&pipe_users); 269 put_pipe_version();
243 BUG_ON(!list_empty(&gss_msg->list)); 270 BUG_ON(!list_empty(&gss_msg->list));
244 if (gss_msg->ctx != NULL) 271 if (gss_msg->ctx != NULL)
245 gss_put_ctx(gss_msg->ctx); 272 gss_put_ctx(gss_msg->ctx);
@@ -330,11 +357,16 @@ static inline struct gss_upcall_msg *
330gss_alloc_msg(struct gss_auth *gss_auth, uid_t uid) 357gss_alloc_msg(struct gss_auth *gss_auth, uid_t uid)
331{ 358{
332 struct gss_upcall_msg *gss_msg; 359 struct gss_upcall_msg *gss_msg;
360 int vers;
333 361
334 gss_msg = kzalloc(sizeof(*gss_msg), GFP_NOFS); 362 gss_msg = kzalloc(sizeof(*gss_msg), GFP_NOFS);
335 if (gss_msg == NULL) 363 if (gss_msg == NULL)
336 return ERR_PTR(-ENOMEM); 364 return ERR_PTR(-ENOMEM);
337 atomic_inc(&pipe_users); 365 vers = get_pipe_version();
366 if (vers < 0) {
367 kfree(gss_msg);
368 return ERR_PTR(vers);
369 }
338 INIT_LIST_HEAD(&gss_msg->list); 370 INIT_LIST_HEAD(&gss_msg->list);
339 rpc_init_wait_queue(&gss_msg->rpc_waitqueue, "RPCSEC_GSS upcall waitq"); 371 rpc_init_wait_queue(&gss_msg->rpc_waitqueue, "RPCSEC_GSS upcall waitq");
340 init_waitqueue_head(&gss_msg->waitqueue); 372 init_waitqueue_head(&gss_msg->waitqueue);
@@ -400,6 +432,14 @@ gss_refresh_upcall(struct rpc_task *task)
400 dprintk("RPC: %5u gss_refresh_upcall for uid %u\n", task->tk_pid, 432 dprintk("RPC: %5u gss_refresh_upcall for uid %u\n", task->tk_pid,
401 cred->cr_uid); 433 cred->cr_uid);
402 gss_msg = gss_setup_upcall(task->tk_client, gss_auth, cred); 434 gss_msg = gss_setup_upcall(task->tk_client, gss_auth, cred);
435 if (IS_ERR(gss_msg) == -EAGAIN) {
436 /* XXX: warning on the first, under the assumption we
437 * shouldn't normally hit this case on a refresh. */
438 warn_gssd();
439 task->tk_timeout = 15*HZ;
440 rpc_sleep_on(&pipe_version_rpc_waitqueue, task, NULL);
441 return 0;
442 }
403 if (IS_ERR(gss_msg)) { 443 if (IS_ERR(gss_msg)) {
404 err = PTR_ERR(gss_msg); 444 err = PTR_ERR(gss_msg);
405 goto out; 445 goto out;
@@ -437,7 +477,17 @@ gss_create_upcall(struct gss_auth *gss_auth, struct gss_cred *gss_cred)
437 int err = 0; 477 int err = 0;
438 478
439 dprintk("RPC: gss_upcall for uid %u\n", cred->cr_uid); 479 dprintk("RPC: gss_upcall for uid %u\n", cred->cr_uid);
480retry:
440 gss_msg = gss_setup_upcall(gss_auth->client, gss_auth, cred); 481 gss_msg = gss_setup_upcall(gss_auth->client, gss_auth, cred);
482 if (PTR_ERR(gss_msg) == -EAGAIN) {
483 err = wait_event_interruptible_timeout(pipe_version_waitqueue,
484 pipe_version >= 0, 15*HZ);
485 if (err)
486 goto out;
487 if (pipe_version < 0)
488 warn_gssd();
489 goto retry;
490 }
441 if (IS_ERR(gss_msg)) { 491 if (IS_ERR(gss_msg)) {
442 err = PTR_ERR(gss_msg); 492 err = PTR_ERR(gss_msg);
443 goto out; 493 goto out;
@@ -562,7 +612,14 @@ out:
562static int 612static int
563gss_pipe_open(struct inode *inode) 613gss_pipe_open(struct inode *inode)
564{ 614{
615 spin_lock(&pipe_version_lock);
616 if (pipe_version < 0) {
617 pipe_version = 0;
618 rpc_wake_up(&pipe_version_rpc_waitqueue);
619 wake_up(&pipe_version_waitqueue);
620 }
565 atomic_inc(&pipe_users); 621 atomic_inc(&pipe_users);
622 spin_unlock(&pipe_version_lock);
566 return 0; 623 return 0;
567} 624}
568 625
@@ -586,7 +643,7 @@ gss_pipe_release(struct inode *inode)
586 } 643 }
587 spin_unlock(&inode->i_lock); 644 spin_unlock(&inode->i_lock);
588 645
589 atomic_dec(&pipe_users); 646 put_pipe_version();
590} 647}
591 648
592static void 649static void
@@ -1379,6 +1436,7 @@ static int __init init_rpcsec_gss(void)
1379 err = gss_svc_init(); 1436 err = gss_svc_init();
1380 if (err) 1437 if (err)
1381 goto out_unregister; 1438 goto out_unregister;
1439 rpc_init_wait_queue(&pipe_version_rpc_waitqueue, "gss pipe version");
1382 return 0; 1440 return 0;
1383out_unregister: 1441out_unregister:
1384 rpcauth_unregister(&authgss_ops); 1442 rpcauth_unregister(&authgss_ops);