NFS41: make close wait for layoutreturn

If we send a layoutreturn asynchronously before close, the close
might reach server first and layoutreturn would fail with BADSTATEID
because there is nothing keeping the layout stateid alive.

Also do not pretend sending layoutreturn if we are not.

Signed-off-by: Peng Tao <tao.peng@primarydata.com>
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
This commit is contained in:
Peng Tao
2015-09-22 11:35:22 +08:00
committed by Trond Myklebust
parent 834e465bba
commit 500d701f33
3 changed files with 49 additions and 10 deletions

View File

@@ -2658,6 +2658,15 @@ out:
return err;
}
static bool
nfs4_wait_on_layoutreturn(struct inode *inode, struct rpc_task *task)
{
if (inode == NULL || !nfs_have_layout(inode))
return false;
return pnfs_wait_on_layoutreturn(inode, task);
}
struct nfs4_closedata {
struct inode *inode;
struct nfs4_state *state;
@@ -2776,6 +2785,11 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data)
goto out_no_action;
}
if (nfs4_wait_on_layoutreturn(inode, task)) {
nfs_release_seqid(calldata->arg.seqid);
goto out_wait;
}
if (calldata->arg.fmode == 0)
task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CLOSE];
if (calldata->roc)
@@ -5321,6 +5335,9 @@ static void nfs4_delegreturn_prepare(struct rpc_task *task, void *data)
d_data = (struct nfs4_delegreturndata *)data;
if (nfs4_wait_on_layoutreturn(d_data->inode, task))
return;
if (d_data->roc)
pnfs_roc_get_barrier(d_data->inode, &d_data->roc_barrier);