Skip to content

Commit bbbff6d

Browse files
Trond Myklebustamschuma-ntap
authored andcommitted
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: Trond Myklebust <[email protected]> Reviewed-by: Jeff Layton <[email protected]> Signed-off-by: Anna Schumaker <[email protected]>
1 parent 50379c9 commit bbbff6d

File tree

3 files changed

+35
-1
lines changed

3 files changed

+35
-1
lines changed

fs/nfs/nfs4proc.c

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9973,6 +9973,11 @@ static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata)
99739973
if (!nfs41_sequence_process(task, &lrp->res.seq_res))
99749974
return;
99759975

9976+
if (task->tk_rpc_status == -ETIMEDOUT) {
9977+
lrp->rpc_status = -EAGAIN;
9978+
lrp->res.lrs_present = 0;
9979+
return;
9980+
}
99769981
/*
99779982
* Was there an RPC level error? Assume the call succeeded,
99789983
* and that we need to release the layout
@@ -9995,6 +10000,15 @@ static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata)
999510000
fallthrough;
999610001
case 0:
999710002
break;
10003+
case -NFS4ERR_BADSESSION:
10004+
case -NFS4ERR_DEADSESSION:
10005+
case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION:
10006+
nfs4_schedule_session_recovery(server->nfs_client->cl_session,
10007+
task->tk_status);
10008+
lrp->res.lrs_present = 0;
10009+
lrp->rpc_status = -EAGAIN;
10010+
task->tk_status = 0;
10011+
break;
999810012
case -NFS4ERR_DELAY:
999910013
if (nfs4_async_handle_error(task, server, NULL, NULL) != -EAGAIN)
1000010014
break;
@@ -10012,8 +10026,13 @@ static void nfs4_layoutreturn_release(void *calldata)
1001210026
struct nfs4_layoutreturn *lrp = calldata;
1001310027
struct pnfs_layout_hdr *lo = lrp->args.layout;
1001410028

10015-
pnfs_layoutreturn_free_lsegs(lo, &lrp->args.stateid, &lrp->args.range,
10029+
if (lrp->rpc_status == 0 || !lrp->inode)
10030+
pnfs_layoutreturn_free_lsegs(
10031+
lo, &lrp->args.stateid, &lrp->args.range,
1001610032
lrp->res.lrs_present ? &lrp->res.stateid : NULL);
10033+
else
10034+
pnfs_layoutreturn_retry_later(lo, &lrp->args.stateid,
10035+
&lrp->args.range);
1001710036
nfs4_sequence_free_slot(&lrp->res.seq_res);
1001810037
if (lrp->ld_private.ops && lrp->ld_private.ops->free)
1001910038
lrp->ld_private.ops->free(&lrp->ld_private);

fs/nfs/pnfs.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1191,6 +1191,18 @@ pnfs_layoutreturn_retry_later_locked(struct pnfs_layout_hdr *lo,
11911191
}
11921192
}
11931193

1194+
void pnfs_layoutreturn_retry_later(struct pnfs_layout_hdr *lo,
1195+
const nfs4_stateid *arg_stateid,
1196+
const struct pnfs_layout_range *range)
1197+
{
1198+
struct inode *inode = lo->plh_inode;
1199+
1200+
spin_lock(&inode->i_lock);
1201+
pnfs_layoutreturn_retry_later_locked(lo, arg_stateid, range);
1202+
pnfs_clear_layoutreturn_waitbit(lo);
1203+
spin_unlock(&inode->i_lock);
1204+
}
1205+
11941206
void pnfs_layoutreturn_free_lsegs(struct pnfs_layout_hdr *lo,
11951207
const nfs4_stateid *arg_stateid,
11961208
const struct pnfs_layout_range *range,

fs/nfs/pnfs.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,9 @@ struct pnfs_layout_segment *pnfs_update_layout(struct inode *ino,
328328
enum pnfs_iomode iomode,
329329
bool strict_iomode,
330330
gfp_t gfp_flags);
331+
void pnfs_layoutreturn_retry_later(struct pnfs_layout_hdr *lo,
332+
const nfs4_stateid *arg_stateid,
333+
const struct pnfs_layout_range *range);
331334
void pnfs_layoutreturn_free_lsegs(struct pnfs_layout_hdr *lo,
332335
const nfs4_stateid *arg_stateid,
333336
const struct pnfs_layout_range *range,

0 commit comments

Comments
 (0)