diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2012-10-01 20:25:48 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2012-10-02 11:34:29 -0400 |
commit | ee314c2a35ee7ea7ffa72e2aca83b041138f3358 (patch) | |
tree | eda86a9d173d4e7113bdf5b62924b08c2d9cf5d5 /fs/nfs | |
parent | 6f018efac14eb267d3ba0aa4294594b556147dba (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.c | 34 |
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) | |||
6272 | static void nfs4_layoutget_done(struct rpc_task *task, void *calldata) | 6272 | static 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); | ||
6312 | out: | ||
6295 | dprintk("<-- %s\n", __func__); | 6313 | dprintk("<-- %s\n", __func__); |
6296 | } | 6314 | } |
6297 | 6315 | ||