aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2014-08-21 12:09:22 -0400
committerTrond Myklebust <trond.myklebust@primarydata.com>2014-09-10 15:47:01 -0400
commit47abadefad213bb7de9592d2e09a8bd282ddc3de (patch)
tree654dab2b331441f3a823a33ad1912578459f6cd9
parentdefb8460881cbf0a5890bc7a63b42c0cfbed721d (diff)
pnfs: avoid using stale stateids after layoutreturn
After we issued a layoutreturn operations the may free the layout stateid and will thus cause bad stateid error when the client uses it again. We currently try to avoid this case by chosing the open stateid if not lsegs are present for this inode. But various places can hold refererence on lsegs and thus cause the list not to be empty shortly after a layout return. Add an explicit flag to mark the current layout stateid invalid and force usage of the openstateid after we did a full file layoutreturn. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
-rw-r--r--fs/nfs/pnfs.c7
-rw-r--r--fs/nfs/pnfs.h1
2 files changed, 7 insertions, 1 deletions
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index ff7fabe33529..57b5728e0b8e 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -738,7 +738,8 @@ pnfs_choose_layoutget_stateid(nfs4_stateid *dst, struct pnfs_layout_hdr *lo,
738 status = -EAGAIN; 738 status = -EAGAIN;
739 } else if (!nfs4_valid_open_stateid(open_state)) { 739 } else if (!nfs4_valid_open_stateid(open_state)) {
740 status = -EBADF; 740 status = -EBADF;
741 } else if (list_empty(&lo->plh_segs)) { 741 } else if (list_empty(&lo->plh_segs) ||
742 test_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags)) {
742 int seq; 743 int seq;
743 744
744 do { 745 do {
@@ -860,6 +861,8 @@ _pnfs_return_layout(struct inode *ino)
860 dprintk("NFS: %s no layout segments to return\n", __func__); 861 dprintk("NFS: %s no layout segments to return\n", __func__);
861 goto out; 862 goto out;
862 } 863 }
864
865 set_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags);
863 lo->plh_block_lgets++; 866 lo->plh_block_lgets++;
864 spin_unlock(&ino->i_lock); 867 spin_unlock(&ino->i_lock);
865 pnfs_free_lseg_list(&tmp_list); 868 pnfs_free_lseg_list(&tmp_list);
@@ -1380,6 +1383,8 @@ pnfs_layout_process(struct nfs4_layoutget *lgp)
1380 lo->plh_barrier = be32_to_cpu(res->stateid.seqid); 1383 lo->plh_barrier = be32_to_cpu(res->stateid.seqid);
1381 } 1384 }
1382 1385
1386 clear_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags);
1387
1383 pnfs_get_lseg(lseg); 1388 pnfs_get_lseg(lseg);
1384 pnfs_layout_insert_lseg(lo, lseg); 1389 pnfs_layout_insert_lseg(lo, lseg);
1385 1390
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h
index 79c63114ce77..1dd8a5e96c9f 100644
--- a/fs/nfs/pnfs.h
+++ b/fs/nfs/pnfs.h
@@ -65,6 +65,7 @@ enum {
65 NFS_LAYOUT_BULK_RECALL, /* bulk recall affecting layout */ 65 NFS_LAYOUT_BULK_RECALL, /* bulk recall affecting layout */
66 NFS_LAYOUT_ROC, /* some lseg had roc bit set */ 66 NFS_LAYOUT_ROC, /* some lseg had roc bit set */
67 NFS_LAYOUT_RETURN, /* Return this layout ASAP */ 67 NFS_LAYOUT_RETURN, /* Return this layout ASAP */
68 NFS_LAYOUT_INVALID_STID, /* layout stateid id is invalid */
68}; 69};
69 70
70enum layoutdriver_policy_flags { 71enum layoutdriver_policy_flags {