Re: [PATCH Version 2 1/1] NFSv4 reduce attribute requests for open reclaim

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

 



On Tue, 2012-10-02 at 11:34 -0400, andros@xxxxxxxxxx wrote:
> From: Andy Adamson <andros@xxxxxxxxxx>
> 
> We currently make no distinction in attribute requests between normal OPENs
> and OPEN with CLAIM_PREVIOUS.  This offers more possibility of failures in
> the GETATTR response which foils OPEN reclaim attempts.
> 
> Reduce the requested attributes to the bare minimum needed to update the
> reclaim open stateid and split nfs4_opendata_to_nfs4_state processing
> accordingly.
> 
> Signed-off-by: Andy Adamson <andros@xxxxxxxxxx>
> ---
> 
> Version 2:
> As per Tronds suggestion, use nfs_refresh_inode instead of nfs_update_inode.
> 
>  fs/nfs/nfs4proc.c |  108 ++++++++++++++++++++++++++++++++++++++++-------------
>  fs/nfs/nfs4xdr.c  |    2 +-
>  2 files changed, 83 insertions(+), 27 deletions(-)
> 
> diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
> index 50e79c9..0437703 100644
> --- a/fs/nfs/nfs4proc.c
> +++ b/fs/nfs/nfs4proc.c
> @@ -152,6 +152,12 @@ static const u32 nfs4_pnfs_open_bitmap[3] = {
>  	FATTR4_WORD2_MDSTHRESHOLD
>  };
>  
> +static const u32 nfs4_open_noattr_bitmap[3] = {
> +	FATTR4_WORD0_TYPE
> +	| FATTR4_WORD0_CHANGE
> +	| FATTR4_WORD0_FILEID,
> +};
> +
>  const u32 nfs4_statfs_bitmap[2] = {
>  	FATTR4_WORD0_FILES_AVAIL
>  	| FATTR4_WORD0_FILES_FREE
> @@ -1120,11 +1126,74 @@ out_return_state:
>  	return state;
>  }
>  
> -static struct nfs4_state *nfs4_opendata_to_nfs4_state(struct nfs4_opendata *data)
> +static void
> +nfs4_opendata_check_deleg(struct nfs4_opendata *data, struct nfs4_state *state)
> +{
> +	struct nfs_client *clp = NFS_SERVER(state->inode)->nfs_client;
> +	struct nfs_delegation *delegation;
> +	int delegation_flags = 0;
> +
> +	rcu_read_lock();
> +	delegation = rcu_dereference(NFS_I(state->inode)->delegation);
> +	if (delegation)
> +		delegation_flags = delegation->flags;
> +	rcu_read_unlock();
> +	if (data->o_arg.claim == NFS4_OPEN_CLAIM_DELEGATE_CUR) {
> +		pr_err_ratelimited("NFS: Broken NFSv4 server %s is "
> +				   "returning a delegation for "
> +				   "OPEN(CLAIM_DELEGATE_CUR)\n",
> +				   clp->cl_hostname);
> +	} else if ((delegation_flags & 1UL<<NFS_DELEGATION_NEED_RECLAIM) == 0)
> +		nfs_inode_set_delegation(state->inode,
> +					 data->owner->so_cred,
> +					 &data->o_res);
> +	else
> +		nfs_inode_reclaim_delegation(state->inode,
> +					     data->owner->so_cred,
> +					     &data->o_res);
> +}
> +
> +/*
> + * Check the inode attributes against the CLAIM_PREVIOUS returned attributes
> + * and update the nfs4_state.
> + */
> +static struct nfs4_state *
> +_nfs4_opendata_reclaim_to_nfs4_state(struct nfs4_opendata *data)
> +{
> +	struct inode *inode = data->state->inode;
> +	struct nfs4_state *state = data->state;
> +	int ret = -ESTALE;
> +
> +	if (!data->rpc_done || !(data->f_attr.valid & NFS_ATTR_FATTR) ||

Isn't the test for NFS_ATTR_FATTR redundant if we pass any one of the
below?

> +	    !(data->f_attr.valid & NFS_ATTR_FATTR_TYPE) ||
> +	    !(data->f_attr.valid & NFS_ATTR_FATTR_CHANGE) ||
> +	    !(data->f_attr.valid & NFS_ATTR_FATTR_FILEID))
> +		goto err;

If !data->rpc_done, we don't really want to return ESTALE.

> +
> +	ret = -ENOMEM;
> +	state = nfs4_get_open_state(inode, data->owner);
> +	if (state == NULL)
> +		goto err;
> +
> +	ret = nfs_refresh_inode(inode, &data->f_attr);
> +	if (ret)
> +		goto err;
> +	if (data->o_res.delegation_type != 0)
> +		nfs4_opendata_check_deleg(data, state);
> +	update_open_stateid(state, &data->o_res.stateid, NULL,
> +			    data->o_arg.fmode);
> +
> +	return state;
> +err:
> +	return ERR_PTR(ret);
> +
> +}
> +
> +static struct nfs4_state *
> +_nfs4_opendata_to_nfs4_state(struct nfs4_opendata *data)
>  {
>  	struct inode *inode;
>  	struct nfs4_state *state = NULL;
> -	struct nfs_delegation *delegation;
>  	int ret;
>  
>  	if (!data->rpc_done) {
> @@ -1143,30 +1212,8 @@ static struct nfs4_state *nfs4_opendata_to_nfs4_state(struct nfs4_opendata *data
>  	state = nfs4_get_open_state(inode, data->owner);
>  	if (state == NULL)
>  		goto err_put_inode;
> -	if (data->o_res.delegation_type != 0) {
> -		struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
> -		int delegation_flags = 0;
> -
> -		rcu_read_lock();
> -		delegation = rcu_dereference(NFS_I(inode)->delegation);
> -		if (delegation)
> -			delegation_flags = delegation->flags;
> -		rcu_read_unlock();
> -		if (data->o_arg.claim == NFS4_OPEN_CLAIM_DELEGATE_CUR) {
> -			pr_err_ratelimited("NFS: Broken NFSv4 server %s is "
> -					"returning a delegation for "
> -					"OPEN(CLAIM_DELEGATE_CUR)\n",
> -					clp->cl_hostname);
> -		} else if ((delegation_flags & 1UL<<NFS_DELEGATION_NEED_RECLAIM) == 0)
> -			nfs_inode_set_delegation(state->inode,
> -					data->owner->so_cred,
> -					&data->o_res);
> -		else
> -			nfs_inode_reclaim_delegation(state->inode,
> -					data->owner->so_cred,
> -					&data->o_res);
> -	}
> -
> +	if (data->o_res.delegation_type != 0)
> +		nfs4_opendata_check_deleg(data, state);
>  	update_open_stateid(state, &data->o_res.stateid, NULL,
>  			data->o_arg.fmode);
>  	iput(inode);
> @@ -1178,6 +1225,14 @@ err:
>  	return ERR_PTR(ret);
>  }
>  
> +static struct nfs4_state *
> +nfs4_opendata_to_nfs4_state(struct nfs4_opendata *data)
> +{
> +	if (data->o_arg.claim == NFS4_OPEN_CLAIM_PREVIOUS)
> +		return _nfs4_opendata_reclaim_to_nfs4_state(data);
> +	return _nfs4_opendata_to_nfs4_state(data);
> +}
> +
>  static struct nfs_open_context *nfs4_state_find_open_context(struct nfs4_state *state)
>  {
>  	struct nfs_inode *nfsi = NFS_I(state->inode);
> @@ -1499,6 +1554,7 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata)
>  	data->o_arg.clientid = sp->so_server->nfs_client->cl_clientid;
>  	if (data->o_arg.claim == NFS4_OPEN_CLAIM_PREVIOUS) {
>  		task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_NOATTR];
> +		data->o_arg.open_bitmap = &nfs4_open_noattr_bitmap[0];
>  		nfs_copy_fh(&data->o_res.fh, data->o_arg.fh);
>  	}
>  	data->timestamp = jiffies;
> diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
> index 657483c..ba5b195 100644
> --- a/fs/nfs/nfs4xdr.c
> +++ b/fs/nfs/nfs4xdr.c
> @@ -2262,7 +2262,7 @@ static void nfs4_xdr_enc_open_noattr(struct rpc_rqst *req,
>  	encode_putfh(xdr, args->fh, &hdr);
>  	encode_open(xdr, args, &hdr);
>  	encode_access(xdr, args->access, &hdr);
> -	encode_getfattr(xdr, args->bitmask, &hdr);
> +	encode_getfattr_open(xdr, args->bitmask, args->open_bitmap, &hdr);
>  	encode_nops(&hdr);
>  }
>  

-- 
Trond Myklebust
Linux NFS client maintainer

NetApp
Trond.Myklebust@xxxxxxxxxx
www.netapp.com
��.n��������+%������w��{.n�����{��w���jg��������ݢj����G�������j:+v���w�m������w�������h�����٥



[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