Commit bbbff6d5 authored by Trond Myklebust's avatar Trond Myklebust Committed by Anna Schumaker

NFSv4/pNFS: Retry the layout return later in case of a timeout or reboot

If the layout return failed due to a timeout or reboot, then leave the
layout segments on the list so that the layout return gets replayed
later.
The exception would be if we're freeing the inode.
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@hammerspace.com>
Reviewed-by: default avatarJeff Layton <jlayton@kernel.org>
Signed-off-by: default avatarAnna Schumaker <Anna.Schumaker@Netapp.com>
parent 50379c9f
...@@ -9973,6 +9973,11 @@ static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata) ...@@ -9973,6 +9973,11 @@ static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata)
if (!nfs41_sequence_process(task, &lrp->res.seq_res)) if (!nfs41_sequence_process(task, &lrp->res.seq_res))
return; return;
if (task->tk_rpc_status == -ETIMEDOUT) {
lrp->rpc_status = -EAGAIN;
lrp->res.lrs_present = 0;
return;
}
/* /*
* Was there an RPC level error? Assume the call succeeded, * Was there an RPC level error? Assume the call succeeded,
* and that we need to release the layout * and that we need to release the layout
...@@ -9995,6 +10000,15 @@ static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata) ...@@ -9995,6 +10000,15 @@ static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata)
fallthrough; fallthrough;
case 0: case 0:
break; break;
case -NFS4ERR_BADSESSION:
case -NFS4ERR_DEADSESSION:
case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION:
nfs4_schedule_session_recovery(server->nfs_client->cl_session,
task->tk_status);
lrp->res.lrs_present = 0;
lrp->rpc_status = -EAGAIN;
task->tk_status = 0;
break;
case -NFS4ERR_DELAY: case -NFS4ERR_DELAY:
if (nfs4_async_handle_error(task, server, NULL, NULL) != -EAGAIN) if (nfs4_async_handle_error(task, server, NULL, NULL) != -EAGAIN)
break; break;
...@@ -10012,8 +10026,13 @@ static void nfs4_layoutreturn_release(void *calldata) ...@@ -10012,8 +10026,13 @@ static void nfs4_layoutreturn_release(void *calldata)
struct nfs4_layoutreturn *lrp = calldata; struct nfs4_layoutreturn *lrp = calldata;
struct pnfs_layout_hdr *lo = lrp->args.layout; struct pnfs_layout_hdr *lo = lrp->args.layout;
pnfs_layoutreturn_free_lsegs(lo, &lrp->args.stateid, &lrp->args.range, if (lrp->rpc_status == 0 || !lrp->inode)
pnfs_layoutreturn_free_lsegs(
lo, &lrp->args.stateid, &lrp->args.range,
lrp->res.lrs_present ? &lrp->res.stateid : NULL); lrp->res.lrs_present ? &lrp->res.stateid : NULL);
else
pnfs_layoutreturn_retry_later(lo, &lrp->args.stateid,
&lrp->args.range);
nfs4_sequence_free_slot(&lrp->res.seq_res); nfs4_sequence_free_slot(&lrp->res.seq_res);
if (lrp->ld_private.ops && lrp->ld_private.ops->free) if (lrp->ld_private.ops && lrp->ld_private.ops->free)
lrp->ld_private.ops->free(&lrp->ld_private); lrp->ld_private.ops->free(&lrp->ld_private);
......
...@@ -1191,6 +1191,18 @@ pnfs_layoutreturn_retry_later_locked(struct pnfs_layout_hdr *lo, ...@@ -1191,6 +1191,18 @@ pnfs_layoutreturn_retry_later_locked(struct pnfs_layout_hdr *lo,
} }
} }
void pnfs_layoutreturn_retry_later(struct pnfs_layout_hdr *lo,
const nfs4_stateid *arg_stateid,
const struct pnfs_layout_range *range)
{
struct inode *inode = lo->plh_inode;
spin_lock(&inode->i_lock);
pnfs_layoutreturn_retry_later_locked(lo, arg_stateid, range);
pnfs_clear_layoutreturn_waitbit(lo);
spin_unlock(&inode->i_lock);
}
void pnfs_layoutreturn_free_lsegs(struct pnfs_layout_hdr *lo, void pnfs_layoutreturn_free_lsegs(struct pnfs_layout_hdr *lo,
const nfs4_stateid *arg_stateid, const nfs4_stateid *arg_stateid,
const struct pnfs_layout_range *range, const struct pnfs_layout_range *range,
......
...@@ -328,6 +328,9 @@ struct pnfs_layout_segment *pnfs_update_layout(struct inode *ino, ...@@ -328,6 +328,9 @@ struct pnfs_layout_segment *pnfs_update_layout(struct inode *ino,
enum pnfs_iomode iomode, enum pnfs_iomode iomode,
bool strict_iomode, bool strict_iomode,
gfp_t gfp_flags); gfp_t gfp_flags);
void pnfs_layoutreturn_retry_later(struct pnfs_layout_hdr *lo,
const nfs4_stateid *arg_stateid,
const struct pnfs_layout_range *range);
void pnfs_layoutreturn_free_lsegs(struct pnfs_layout_hdr *lo, void pnfs_layoutreturn_free_lsegs(struct pnfs_layout_hdr *lo,
const nfs4_stateid *arg_stateid, const nfs4_stateid *arg_stateid,
const struct pnfs_layout_range *range, const struct pnfs_layout_range *range,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment