pNFS: Force a retry of LAYOUTGET if the stateid doesn't match our cache
authorTrond Myklebust <trond.myklebust@primarydata.com>
Wed, 23 Nov 2016 17:36:04 +0000 (12:36 -0500)
committerTrond Myklebust <trond.myklebust@primarydata.com>
Thu, 1 Dec 2016 22:21:40 +0000 (17:21 -0500)
If the server sends us a completely new stateid, and the client thinks
it already holds a layout, then force a retry of the LAYOUTGET after
invalidating the existing layout in order to avoid corruption due to
races.

Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
fs/nfs/pnfs.c

index d4e06b7459f4c74f7f2049891c20734c5b1954e3..9b7e88b7edfce815fecd2b36aa2d81c956936211 100644 (file)
@@ -1844,7 +1844,10 @@ pnfs_layout_process(struct nfs4_layoutget *lgp)
                goto out_forget;
        }
 
-       if (nfs4_stateid_match_other(&lo->plh_stateid, &res->stateid)) {
+       if (!pnfs_layout_is_valid(lo)) {
+               /* We have a completely new layout */
+               pnfs_set_layout_stateid(lo, &res->stateid, true);
+       } else if (nfs4_stateid_match_other(&lo->plh_stateid, &res->stateid)) {
                /* existing state ID, make sure the sequence number matches. */
                if (pnfs_layout_stateid_blocked(lo, &res->stateid)) {
                        dprintk("%s forget reply due to sequence\n", __func__);
@@ -1854,12 +1857,10 @@ pnfs_layout_process(struct nfs4_layoutget *lgp)
        } else {
                /*
                 * We got an entirely new state ID.  Mark all segments for the
-                * inode invalid, and don't bother validating the stateid
-                * sequence number.
+                * inode invalid, and retry the layoutget
                 */
                pnfs_mark_layout_stateid_invalid(lo, &free_me);
-
-               pnfs_set_layout_stateid(lo, &res->stateid, true);
+               goto out_forget;
        }
 
        pnfs_get_lseg(lseg);