aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/pnfs.c
diff options
context:
space:
mode:
authorTrond Myklebust <trondmy@gmail.com>2018-07-29 22:39:15 -0400
committerAnna Schumaker <Anna.Schumaker@Netapp.com>2018-08-08 16:50:01 -0400
commitc16467dc03db5e2532484026a25b0eef80012ea1 (patch)
treeeed5b981f465ef9d187db1eb1c22a1bc90cd8d6c /fs/nfs/pnfs.c
parentxprtrdma: Fix disconnect regression (diff)
downloadlinux-dev-c16467dc03db5e2532484026a25b0eef80012ea1.tar.xz
linux-dev-c16467dc03db5e2532484026a25b0eef80012ea1.zip
pnfs: Fix handling of NFS4ERR_OLD_STATEID replies to layoutreturn
If the server tells us that out layoutreturn raced with another layout update, then we must ensure that the new layout segments are not in use before we resend with an updated layout stateid. Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com> Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
Diffstat (limited to 'fs/nfs/pnfs.c')
-rw-r--r--fs/nfs/pnfs.c17
1 files changed, 14 insertions, 3 deletions
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index 7fdac8b504dd..7020f726275c 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -361,18 +361,29 @@ pnfs_clear_lseg_state(struct pnfs_layout_segment *lseg,
/*
* Update the seqid of a layout stateid
*/
-bool nfs4_refresh_layout_stateid(nfs4_stateid *dst, struct inode *inode)
+bool nfs4_layoutreturn_refresh_stateid(nfs4_stateid *dst, struct inode *inode)
{
struct pnfs_layout_hdr *lo;
+ struct pnfs_layout_range range = {
+ .iomode = IOMODE_ANY,
+ .offset = 0,
+ .length = NFS4_MAX_UINT64,
+ };
bool ret = false;
+ LIST_HEAD(head);
+ int err;
spin_lock(&inode->i_lock);
lo = NFS_I(inode)->layout;
if (lo && nfs4_stateid_match_other(dst, &lo->plh_stateid)) {
- dst->seqid = lo->plh_stateid.seqid;
- ret = true;
+ err = pnfs_mark_matching_lsegs_return(lo, &head, &range, 0);
+ if (err != -EBUSY) {
+ dst->seqid = lo->plh_stateid.seqid;
+ ret = true;
+ }
}
spin_unlock(&inode->i_lock);
+ pnfs_free_lseg_list(&head);
return ret;
}