SUNRPC: Faster detection if gssd is actually running

Recent changes to the NFS security flavour negotiation mean that
we have a stronger dependency on rpc.gssd. If the latter is not
running, because the user failed to start it, then we time out
and mark the container as not having an instance. We then
use that information to time out faster the next time.

If, on the other hand, the rpc.gssd successfully binds to an rpc_pipe,
then we mark the container as having an rpc.gssd instance.

Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>

+18 -1
+12 -1
net/sunrpc/auth_gss/auth_gss.c
··· 52 #include <linux/sunrpc/gss_api.h> 53 #include <asm/uaccess.h> 54 55 static const struct rpc_authops authgss_ops; 56 57 static const struct rpc_credops gss_credops; ··· 561 static inline int 562 gss_create_upcall(struct gss_auth *gss_auth, struct gss_cred *gss_cred) 563 { 564 struct rpc_pipe *pipe; 565 struct rpc_cred *cred = &gss_cred->gc_base; 566 struct gss_upcall_msg *gss_msg; 567 DEFINE_WAIT(wait); 568 int err; 569 ··· 574 __func__, from_kuid(&init_user_ns, cred->cr_uid)); 575 retry: 576 err = 0; 577 gss_msg = gss_setup_upcall(gss_auth->client, gss_auth, cred); 578 if (PTR_ERR(gss_msg) == -EAGAIN) { 579 err = wait_event_interruptible_timeout(pipe_version_waitqueue, 580 - pipe_version >= 0, 15*HZ); 581 if (pipe_version < 0) { 582 warn_gssd(); 583 err = -EACCES; 584 }
··· 52 #include <linux/sunrpc/gss_api.h> 53 #include <asm/uaccess.h> 54 55 + #include "../netns.h" 56 + 57 static const struct rpc_authops authgss_ops; 58 59 static const struct rpc_credops gss_credops; ··· 559 static inline int 560 gss_create_upcall(struct gss_auth *gss_auth, struct gss_cred *gss_cred) 561 { 562 + struct net *net = rpc_net_ns(gss_auth->client); 563 + struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); 564 struct rpc_pipe *pipe; 565 struct rpc_cred *cred = &gss_cred->gc_base; 566 struct gss_upcall_msg *gss_msg; 567 + unsigned long timeout; 568 DEFINE_WAIT(wait); 569 int err; 570 ··· 569 __func__, from_kuid(&init_user_ns, cred->cr_uid)); 570 retry: 571 err = 0; 572 + /* Default timeout is 15s unless we know that gssd is not running */ 573 + timeout = 15 * HZ; 574 + if (!sn->gssd_running) 575 + timeout = HZ >> 2; 576 gss_msg = gss_setup_upcall(gss_auth->client, gss_auth, cred); 577 if (PTR_ERR(gss_msg) == -EAGAIN) { 578 err = wait_event_interruptible_timeout(pipe_version_waitqueue, 579 + pipe_version >= 0, timeout); 580 if (pipe_version < 0) { 581 + if (err == 0) 582 + sn->gssd_running = 0; 583 warn_gssd(); 584 err = -EACCES; 585 }
+2
net/sunrpc/netns.h
··· 29 struct rpc_clnt *gssp_clnt; 30 int use_gss_proxy; 31 struct proc_dir_entry *use_gssp_proc; 32 }; 33 34 extern int sunrpc_net_id;
··· 29 struct rpc_clnt *gssp_clnt; 30 int use_gss_proxy; 31 struct proc_dir_entry *use_gssp_proc; 32 + 33 + unsigned int gssd_running; 34 }; 35 36 extern int sunrpc_net_id;
+4
net/sunrpc/rpc_pipe.c
··· 216 static int 217 rpc_pipe_open(struct inode *inode, struct file *filp) 218 { 219 struct rpc_pipe *pipe; 220 int first_open; 221 int res = -ENXIO; 222 223 mutex_lock(&inode->i_mutex); 224 pipe = RPC_I(inode)->pipe; 225 if (pipe == NULL) 226 goto out; ··· 1072 struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); 1073 1074 mutex_init(&sn->pipefs_sb_lock); 1075 } 1076 1077 /*
··· 216 static int 217 rpc_pipe_open(struct inode *inode, struct file *filp) 218 { 219 + struct net *net = inode->i_sb->s_fs_info; 220 + struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); 221 struct rpc_pipe *pipe; 222 int first_open; 223 int res = -ENXIO; 224 225 mutex_lock(&inode->i_mutex); 226 + sn->gssd_running = 1; 227 pipe = RPC_I(inode)->pipe; 228 if (pipe == NULL) 229 goto out; ··· 1069 struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); 1070 1071 mutex_init(&sn->pipefs_sb_lock); 1072 + sn->gssd_running = 1; 1073 } 1074 1075 /*