Re: [PATCH 1/3] NFSv4.1: Don't loop forever in nfs4_proc_create_session

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi-

This will require some significant human intervention to merge with my code that caches the long-form client ID.

On Apr 20, 2011, at 7:50 PM, Trond Myklebust wrote:

> If a server for some reason keeps sending NFS4ERR_DELAY errors, we can end
> up looping forever inside nfs4_proc_create_session, and so the usual
> mechanisms for detecting if the nfs_client is dead don't work.
> 
> Fix this by ensuring that we loop inside the nfs4_state_manager thread
> instead.
> 
> Signed-off-by: Trond Myklebust <Trond.Myklebust@xxxxxxxxxx>
> ---
> fs/nfs/nfs4_fs.h          |    1 +
> fs/nfs/nfs4proc.c         |   84 ++++++++++++---------------------------------
> fs/nfs/nfs4state.c        |   47 +++++++++++++++++--------
> include/linux/nfs_fs_sb.h |    1 +
> 4 files changed, 56 insertions(+), 77 deletions(-)
> 
> diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
> index e1c261d..c4a6983 100644
> --- a/fs/nfs/nfs4_fs.h
> +++ b/fs/nfs/nfs4_fs.h
> @@ -47,6 +47,7 @@ enum nfs4_client_state {
> 	NFS4CLNT_LAYOUTRECALL,
> 	NFS4CLNT_SESSION_RESET,
> 	NFS4CLNT_RECALL_SLOT,
> +	NFS4CLNT_LEASE_CONFIRM,
> };
> 
> enum nfs4_session_state {
> diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
> index 628e35f..2507f1f 100644
> --- a/fs/nfs/nfs4proc.c
> +++ b/fs/nfs/nfs4proc.c
> @@ -3726,46 +3726,36 @@ int nfs4_proc_setclientid(struct nfs_client *clp, u32 program,
> 		.rpc_cred = cred,
> 	};
> 	__be32 *p;
> -	int loop = 0;
> 	int status;
> 
> 	p = (__be32*)sc_verifier.data;
> 	*p++ = htonl((u32)clp->cl_boot_time.tv_sec);
> 	*p = htonl((u32)clp->cl_boot_time.tv_nsec);
> 
> -	for(;;) {
> -		setclientid.sc_name_len = scnprintf(setclientid.sc_name,
> -				sizeof(setclientid.sc_name), "%s/%s %s %s %u",
> -				clp->cl_ipaddr,
> -				rpc_peeraddr2str(clp->cl_rpcclient,
> -							RPC_DISPLAY_ADDR),
> -				rpc_peeraddr2str(clp->cl_rpcclient,
> -							RPC_DISPLAY_PROTO),
> -				clp->cl_rpcclient->cl_auth->au_ops->au_name,
> -				clp->cl_id_uniquifier);
> -		setclientid.sc_netid_len = scnprintf(setclientid.sc_netid,
> -				sizeof(setclientid.sc_netid),
> -				rpc_peeraddr2str(clp->cl_rpcclient,
> -							RPC_DISPLAY_NETID));
> -		setclientid.sc_uaddr_len = scnprintf(setclientid.sc_uaddr,
> -				sizeof(setclientid.sc_uaddr), "%s.%u.%u",
> -				clp->cl_ipaddr, port >> 8, port & 255);
> -
> -		status = rpc_call_sync(clp->cl_rpcclient, &msg, 0);
> -		if (status != -NFS4ERR_CLID_INUSE)
> -			break;
> -		if (signalled())
> -			break;
> -		if (loop++ & 1)
> -			ssleep(clp->cl_lease_time / HZ + 1);
> -		else
> -			if (++clp->cl_id_uniquifier == 0)
> -				break;
> -	}
> +	setclientid.sc_name_len = scnprintf(setclientid.sc_name,
> +			sizeof(setclientid.sc_name), "%s/%s %s %s %u",
> +			clp->cl_ipaddr,
> +			rpc_peeraddr2str(clp->cl_rpcclient,
> +						RPC_DISPLAY_ADDR),
> +			rpc_peeraddr2str(clp->cl_rpcclient,
> +						RPC_DISPLAY_PROTO),
> +			clp->cl_rpcclient->cl_auth->au_ops->au_name,
> +			clp->cl_id_uniquifier);
> +	setclientid.sc_netid_len = scnprintf(setclientid.sc_netid,
> +			sizeof(setclientid.sc_netid),
> +			rpc_peeraddr2str(clp->cl_rpcclient,
> +						RPC_DISPLAY_NETID));
> +	setclientid.sc_uaddr_len = scnprintf(setclientid.sc_uaddr,
> +			sizeof(setclientid.sc_uaddr), "%s.%u.%u",
> +			clp->cl_ipaddr, port >> 8, port & 255);
> +
> +	status = rpc_call_sync(clp->cl_rpcclient, &msg, 0);
> +	if (status == -NFS4ERR_CLID_INUSE)
> +		ssleep(clp->cl_lease_time / HZ + 1);
> 	return status;
> }
> 
> -static int _nfs4_proc_setclientid_confirm(struct nfs_client *clp,
> +int nfs4_proc_setclientid_confirm(struct nfs_client *clp,
> 		struct nfs4_setclientid_res *arg,
> 		struct rpc_cred *cred)
> {
> @@ -3790,26 +3780,6 @@ static int _nfs4_proc_setclientid_confirm(struct nfs_client *clp,
> 	return status;
> }
> 
> -int nfs4_proc_setclientid_confirm(struct nfs_client *clp,
> -		struct nfs4_setclientid_res *arg,
> -		struct rpc_cred *cred)
> -{
> -	long timeout = 0;
> -	int err;
> -	do {
> -		err = _nfs4_proc_setclientid_confirm(clp, arg, cred);
> -		switch (err) {
> -			case 0:
> -				return err;
> -			case -NFS4ERR_RESOURCE:
> -				/* The IBM lawyers misread another document! */
> -			case -NFS4ERR_DELAY:
> -				err = nfs4_delay(clp->cl_rpcclient, &timeout);
> -		}
> -	} while (err == 0);
> -	return err;
> -}
> -
> struct nfs4_delegreturndata {
> 	struct nfs4_delegreturnargs args;
> 	struct nfs4_delegreturnres res;
> @@ -5222,20 +5192,10 @@ int nfs4_proc_create_session(struct nfs_client *clp)
> 	int status;
> 	unsigned *ptr;
> 	struct nfs4_session *session = clp->cl_session;
> -	long timeout = 0;
> -	int err;
> 
> 	dprintk("--> %s clp=%p session=%p\n", __func__, clp, session);
> 
> -	do {
> -		status = _nfs4_proc_create_session(clp);
> -		if (status == -NFS4ERR_DELAY) {
> -			err = nfs4_delay(clp->cl_rpcclient, &timeout);
> -			if (err)
> -				status = err;
> -		}
> -	} while (status == -NFS4ERR_DELAY);
> -
> +	status = _nfs4_proc_create_session(clp);
> 	if (status)
> 		goto out;
> 
> diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
> index 4dfb34b..9a7f9df 100644
> --- a/fs/nfs/nfs4state.c
> +++ b/fs/nfs/nfs4state.c
> @@ -64,10 +64,15 @@ static LIST_HEAD(nfs4_clientid_list);
> 
> int nfs4_init_clientid(struct nfs_client *clp, struct rpc_cred *cred)
> {
> -	struct nfs4_setclientid_res clid;
> +	struct nfs4_setclientid_res clid = {
> +		.clientid = clp->cl_clientid,
> +		.confirm = clp->cl_confirm,
> +	};
> 	unsigned short port;
> 	int status;
> 
> +	if (test_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state))
> +		goto do_confirm;
> 	port = nfs_callback_tcpport;
> 	if (clp->cl_addr.ss_family == AF_INET6)
> 		port = nfs_callback_tcpport6;
> @@ -75,10 +80,14 @@ int nfs4_init_clientid(struct nfs_client *clp, struct rpc_cred *cred)
> 	status = nfs4_proc_setclientid(clp, NFS4_CALLBACK, port, cred, &clid);
> 	if (status != 0)
> 		goto out;
> +	clp->cl_clientid = clid.clientid;
> +	clp->cl_confirm = clid.confirm;
> +	set_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state);
> +do_confirm:
> 	status = nfs4_proc_setclientid_confirm(clp, &clid, cred);
> 	if (status != 0)
> 		goto out;
> -	clp->cl_clientid = clid.clientid;
> +	clear_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state);
> 	nfs4_schedule_state_renewal(clp);
> out:
> 	return status;
> @@ -230,13 +239,18 @@ int nfs41_init_clientid(struct nfs_client *clp, struct rpc_cred *cred)
> {
> 	int status;
> 
> +	if (test_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state))
> +		goto do_confirm;
> 	nfs4_begin_drain_session(clp);
> 	status = nfs4_proc_exchange_id(clp, cred);
> 	if (status != 0)
> 		goto out;
> +	set_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state);
> +do_confirm:
> 	status = nfs4_proc_create_session(clp);
> 	if (status != 0)
> 		goto out;
> +	clear_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state);
> 	nfs41_setup_state_renewal(clp);
> 	nfs_mark_client_ready(clp, NFS_CS_READY);
> out:
> @@ -1584,20 +1598,23 @@ static int nfs4_recall_slot(struct nfs_client *clp) { return 0; }
>  */
> static void nfs4_set_lease_expired(struct nfs_client *clp, int status)
> {
> -	if (nfs4_has_session(clp)) {
> -		switch (status) {
> -		case -NFS4ERR_DELAY:
> -		case -NFS4ERR_CLID_INUSE:
> -		case -EAGAIN:
> -			break;
> +	switch (status) {
> +	case -NFS4ERR_CLID_INUSE:
> +		clp->cl_id_uniquifier++;
> +	case -NFS4ERR_STALE_CLIENTID:
> +		clear_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state);
> +		break;
> +	case -NFS4ERR_DELAY:
> +	case -EAGAIN:
> +		ssleep(1);
> +		break;
> 
> -		case -EKEYEXPIRED:
> -			nfs4_warn_keyexpired(clp->cl_hostname);
> -		case -NFS4ERR_NOT_SAME: /* FixMe: implement recovery
> -					 * in nfs4_exchange_id */
> -		default:
> -			return;
> -		}
> +	case -EKEYEXPIRED:
> +		nfs4_warn_keyexpired(clp->cl_hostname);
> +	case -NFS4ERR_NOT_SAME: /* FixMe: implement recovery
> +				 * in nfs4_exchange_id */
> +	default:
> +		return;
> 	}
> 	set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
> }
> diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
> index 216cea5..87694ca 100644
> --- a/include/linux/nfs_fs_sb.h
> +++ b/include/linux/nfs_fs_sb.h
> @@ -47,6 +47,7 @@ struct nfs_client {
> 
> #ifdef CONFIG_NFS_V4
> 	u64			cl_clientid;	/* constant */
> +	nfs4_verifier		cl_confirm;	/* Clientid verifier */
> 	unsigned long		cl_state;
> 
> 	spinlock_t		cl_lock;
> -- 
> 1.7.4.4
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

-- 
Chuck Lever
chuck[dot]lever[at]oracle[dot]com




--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Filesystem Development]     [Linux USB Development]     [Linux Media Development]     [Video for Linux]     [Linux NILFS]     [Linux Audio Users]     [Yosemite Info]     [Linux SCSI]

  Powered by Linux