aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2012-10-01 20:25:48 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2012-10-02 11:34:29 -0400
commitee314c2a35ee7ea7ffa72e2aca83b041138f3358 (patch)
treeeda86a9d173d4e7113bdf5b62924b08c2d9cf5d5 /fs/nfs
parent6f018efac14eb267d3ba0aa4294594b556147dba (diff)
NFSv4.1: Handle BAD_STATEID and EXPIRED errors in layoutget
If the layoutget call returns a stateid error, we want to invalidate the layout stateid, and/or recover the open stateid. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs')
-rw-r--r--fs/nfs/nfs4proc.c34
1 files changed, 26 insertions, 8 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index e10d66f5be0a..1e0faf9fa078 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -6272,26 +6272,44 @@ nfs4_layoutget_prepare(struct rpc_task *task, void *calldata)
6272static void nfs4_layoutget_done(struct rpc_task *task, void *calldata) 6272static void nfs4_layoutget_done(struct rpc_task *task, void *calldata)
6273{ 6273{
6274 struct nfs4_layoutget *lgp = calldata; 6274 struct nfs4_layoutget *lgp = calldata;
6275 struct nfs_server *server = NFS_SERVER(lgp->args.inode); 6275 struct inode *inode = lgp->args.inode;
6276 struct nfs_server *server = NFS_SERVER(inode);
6277 struct pnfs_layout_hdr *lo;
6278 struct nfs4_state *state = NULL;
6276 6279
6277 dprintk("--> %s\n", __func__); 6280 dprintk("--> %s\n", __func__);
6278 6281
6279 if (!nfs4_sequence_done(task, &lgp->res.seq_res)) 6282 if (!nfs4_sequence_done(task, &lgp->res.seq_res))
6280 return; 6283 goto out;
6281 6284
6282 switch (task->tk_status) { 6285 switch (task->tk_status) {
6283 case 0: 6286 case 0:
6284 break; 6287 goto out;
6285 case -NFS4ERR_LAYOUTTRYLATER: 6288 case -NFS4ERR_LAYOUTTRYLATER:
6286 case -NFS4ERR_RECALLCONFLICT: 6289 case -NFS4ERR_RECALLCONFLICT:
6287 task->tk_status = -NFS4ERR_DELAY; 6290 task->tk_status = -NFS4ERR_DELAY;
6288 /* Fall through */ 6291 break;
6289 default: 6292 case -NFS4ERR_EXPIRED:
6290 if (nfs4_async_handle_error(task, server, NULL) == -EAGAIN) { 6293 case -NFS4ERR_BAD_STATEID:
6291 rpc_restart_call_prepare(task); 6294 spin_lock(&inode->i_lock);
6292 return; 6295 lo = NFS_I(inode)->layout;
6296 if (!lo || list_empty(&lo->plh_segs)) {
6297 spin_unlock(&inode->i_lock);
6298 /* If the open stateid was bad, then recover it. */
6299 state = lgp->args.ctx->state;
6300 } else {
6301 LIST_HEAD(head);
6302
6303 pnfs_mark_matching_lsegs_invalid(lo, &head, NULL);
6304 spin_unlock(&inode->i_lock);
6305 /* Mark the bad layout state as invalid, then
6306 * retry using the open stateid. */
6307 pnfs_free_lseg_list(&head);
6293 } 6308 }
6294 } 6309 }
6310 if (nfs4_async_handle_error(task, server, state) == -EAGAIN)
6311 rpc_restart_call_prepare(task);
6312out:
6295 dprintk("<-- %s\n", __func__); 6313 dprintk("<-- %s\n", __func__);
6296} 6314}
6297 6315