pnfs: avoid using stale stateids after layoutreturn
authorChristoph Hellwig <hch@lst.de>
Thu, 21 Aug 2014 16:09:22 +0000 (11:09 -0500)
committerTrond Myklebust <trond.myklebust@primarydata.com>
Wed, 10 Sep 2014 19:47:01 +0000 (12:47 -0700)
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>
fs/nfs/pnfs.c
fs/nfs/pnfs.h

index ff7fabe3352914f8e0f8d9d66a2028500abdb2c0..57b5728e0b8ee8924e85675c7b1b5903614ef3c9 100644 (file)
@@ -738,7 +738,8 @@ pnfs_choose_layoutget_stateid(nfs4_stateid *dst, struct pnfs_layout_hdr *lo,
                status = -EAGAIN;
        } else if (!nfs4_valid_open_stateid(open_state)) {
                status = -EBADF;
-       } else if (list_empty(&lo->plh_segs)) {
+       } else if (list_empty(&lo->plh_segs) ||
+                  test_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags)) {
                int seq;
 
                do {
@@ -860,6 +861,8 @@ _pnfs_return_layout(struct inode *ino)
                dprintk("NFS: %s no layout segments to return\n", __func__);
                goto out;
        }
+
+       set_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags);
        lo->plh_block_lgets++;
        spin_unlock(&ino->i_lock);
        pnfs_free_lseg_list(&tmp_list);
@@ -1380,6 +1383,8 @@ pnfs_layout_process(struct nfs4_layoutget *lgp)
                lo->plh_barrier = be32_to_cpu(res->stateid.seqid);
        }
 
+       clear_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags);
+
        pnfs_get_lseg(lseg);
        pnfs_layout_insert_lseg(lo, lseg);
 
index 79c63114ce775484f50efc6f3888b1f8649773d9..1dd8a5e96c9f8b8c751de20ed754bef28bff3a28 100644 (file)
@@ -65,6 +65,7 @@ enum {
        NFS_LAYOUT_BULK_RECALL,         /* bulk recall affecting layout */
        NFS_LAYOUT_ROC,                 /* some lseg had roc bit set */
        NFS_LAYOUT_RETURN,              /* Return this layout ASAP */
+       NFS_LAYOUT_INVALID_STID,        /* layout stateid id is invalid */
 };
 
 enum layoutdriver_policy_flags {