diff options
author | Trond Myklebust <trondmy@gmail.com> | 2019-09-20 07:23:45 -0400 |
---|---|---|
committer | Anna Schumaker <Anna.Schumaker@Netapp.com> | 2019-09-20 15:48:35 -0400 |
commit | 30cb3ee299cbf343fe07419e9b0f8dc305979eb6 (patch) | |
tree | c3712b9e919e26632ea3fcaf7cbcd9c1e0eb1f47 /fs | |
parent | 922839570920c024baf740ef45dfa98009f0192e (diff) |
pNFS: Handle NFS4ERR_OLD_STATEID on layoutreturn by bumping the state seqid
If a LAYOUTRETURN receives a reply of NFS4ERR_OLD_STATEID then assume we've
missed an update, and just bump the stateid.
Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/nfs/nfs4proc.c | 2 | ||||
-rw-r--r-- | fs/nfs/pnfs.c | 18 | ||||
-rw-r--r-- | fs/nfs/pnfs.h | 4 |
3 files changed, 17 insertions, 7 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index c0bff7ad0c9f..27964ea0b3b7 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -9063,7 +9063,7 @@ static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata) | |||
9063 | server = NFS_SERVER(lrp->args.inode); | 9063 | server = NFS_SERVER(lrp->args.inode); |
9064 | switch (task->tk_status) { | 9064 | switch (task->tk_status) { |
9065 | case -NFS4ERR_OLD_STATEID: | 9065 | case -NFS4ERR_OLD_STATEID: |
9066 | if (nfs4_layoutreturn_refresh_stateid(&lrp->args.stateid, | 9066 | if (nfs4_layout_refresh_old_stateid(&lrp->args.stateid, |
9067 | &lrp->args.range, | 9067 | &lrp->args.range, |
9068 | lrp->args.inode)) | 9068 | lrp->args.inode)) |
9069 | goto out_restart; | 9069 | goto out_restart; |
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index abc7188f1853..bb80034a7661 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c | |||
@@ -359,9 +359,10 @@ pnfs_clear_lseg_state(struct pnfs_layout_segment *lseg, | |||
359 | } | 359 | } |
360 | 360 | ||
361 | /* | 361 | /* |
362 | * Update the seqid of a layout stateid | 362 | * Update the seqid of a layout stateid after receiving |
363 | * NFS4ERR_OLD_STATEID | ||
363 | */ | 364 | */ |
364 | bool nfs4_layoutreturn_refresh_stateid(nfs4_stateid *dst, | 365 | bool nfs4_layout_refresh_old_stateid(nfs4_stateid *dst, |
365 | struct pnfs_layout_range *dst_range, | 366 | struct pnfs_layout_range *dst_range, |
366 | struct inode *inode) | 367 | struct inode *inode) |
367 | { | 368 | { |
@@ -377,7 +378,15 @@ bool nfs4_layoutreturn_refresh_stateid(nfs4_stateid *dst, | |||
377 | 378 | ||
378 | spin_lock(&inode->i_lock); | 379 | spin_lock(&inode->i_lock); |
379 | lo = NFS_I(inode)->layout; | 380 | lo = NFS_I(inode)->layout; |
380 | if (lo && nfs4_stateid_match_other(dst, &lo->plh_stateid)) { | 381 | if (lo && pnfs_layout_is_valid(lo) && |
382 | nfs4_stateid_match_other(dst, &lo->plh_stateid)) { | ||
383 | /* Is our call using the most recent seqid? If so, bump it */ | ||
384 | if (!nfs4_stateid_is_newer(&lo->plh_stateid, dst)) { | ||
385 | nfs4_stateid_seqid_inc(dst); | ||
386 | ret = true; | ||
387 | goto out; | ||
388 | } | ||
389 | /* Try to update the seqid to the most recent */ | ||
381 | err = pnfs_mark_matching_lsegs_return(lo, &head, &range, 0); | 390 | err = pnfs_mark_matching_lsegs_return(lo, &head, &range, 0); |
382 | if (err != -EBUSY) { | 391 | if (err != -EBUSY) { |
383 | dst->seqid = lo->plh_stateid.seqid; | 392 | dst->seqid = lo->plh_stateid.seqid; |
@@ -385,6 +394,7 @@ bool nfs4_layoutreturn_refresh_stateid(nfs4_stateid *dst, | |||
385 | ret = true; | 394 | ret = true; |
386 | } | 395 | } |
387 | } | 396 | } |
397 | out: | ||
388 | spin_unlock(&inode->i_lock); | 398 | spin_unlock(&inode->i_lock); |
389 | pnfs_free_lseg_list(&head); | 399 | pnfs_free_lseg_list(&head); |
390 | return ret; | 400 | return ret; |
@@ -1475,7 +1485,7 @@ int pnfs_roc_done(struct rpc_task *task, struct inode *inode, | |||
1475 | *ret = -NFS4ERR_NOMATCHING_LAYOUT; | 1485 | *ret = -NFS4ERR_NOMATCHING_LAYOUT; |
1476 | return 0; | 1486 | return 0; |
1477 | case -NFS4ERR_OLD_STATEID: | 1487 | case -NFS4ERR_OLD_STATEID: |
1478 | if (!nfs4_layoutreturn_refresh_stateid(&arg->stateid, | 1488 | if (!nfs4_layout_refresh_old_stateid(&arg->stateid, |
1479 | &arg->range, inode)) | 1489 | &arg->range, inode)) |
1480 | break; | 1490 | break; |
1481 | *ret = -NFS4ERR_NOMATCHING_LAYOUT; | 1491 | *ret = -NFS4ERR_NOMATCHING_LAYOUT; |
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h index 3ef3756d437c..f8a38065c7e4 100644 --- a/fs/nfs/pnfs.h +++ b/fs/nfs/pnfs.h | |||
@@ -261,7 +261,7 @@ int pnfs_destroy_layouts_byfsid(struct nfs_client *clp, | |||
261 | bool is_recall); | 261 | bool is_recall); |
262 | int pnfs_destroy_layouts_byclid(struct nfs_client *clp, | 262 | int pnfs_destroy_layouts_byclid(struct nfs_client *clp, |
263 | bool is_recall); | 263 | bool is_recall); |
264 | bool nfs4_layoutreturn_refresh_stateid(nfs4_stateid *dst, | 264 | bool nfs4_layout_refresh_old_stateid(nfs4_stateid *dst, |
265 | struct pnfs_layout_range *dst_range, | 265 | struct pnfs_layout_range *dst_range, |
266 | struct inode *inode); | 266 | struct inode *inode); |
267 | void pnfs_put_layout_hdr(struct pnfs_layout_hdr *lo); | 267 | void pnfs_put_layout_hdr(struct pnfs_layout_hdr *lo); |
@@ -798,7 +798,7 @@ static inline void nfs4_pnfs_v3_ds_connect_unload(void) | |||
798 | { | 798 | { |
799 | } | 799 | } |
800 | 800 | ||
801 | static inline bool nfs4_layoutreturn_refresh_stateid(nfs4_stateid *dst, | 801 | static inline bool nfs4_layout_refresh_old_stateid(nfs4_stateid *dst, |
802 | struct pnfs_layout_range *dst_range, | 802 | struct pnfs_layout_range *dst_range, |
803 | struct inode *inode) | 803 | struct inode *inode) |
804 | { | 804 | { |