pNFS/NFSv4: Improve rejection of out-of-order layouts

If a layoutget ends up being reordered w.r.t. a layoutreturn, e.g. due
to a layoutget-on-open not knowing a priori which file to lock, then we
must assume the layout is no longer being considered valid state by the
server.
Incrementally improve our ability to reject such states by using the
cached old stateid in conjunction with the plh_barrier to try to
identify them.

Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>

+16 -6
+16 -6
fs/nfs/pnfs.c
··· 1000 1000 { 1001 1001 u32 seqid = be32_to_cpu(stateid->seqid); 1002 1002 1003 - return !pnfs_seqid_is_newer(seqid, lo->plh_barrier); 1003 + return !pnfs_seqid_is_newer(seqid, lo->plh_barrier) && lo->plh_barrier; 1004 1004 } 1005 1005 1006 1006 /* lget is set to 1 if called from inside send_layoutget call chain */ ··· 1912 1912 wake_up_var(&lo->plh_outstanding); 1913 1913 } 1914 1914 1915 + static bool pnfs_is_first_layoutget(struct pnfs_layout_hdr *lo) 1916 + { 1917 + return test_bit(NFS_LAYOUT_FIRST_LAYOUTGET, &lo->plh_flags); 1918 + } 1919 + 1915 1920 static void pnfs_clear_first_layoutget(struct pnfs_layout_hdr *lo) 1916 1921 { 1917 1922 unsigned long *bitlock = &lo->plh_flags; ··· 2391 2386 goto out_forget; 2392 2387 } 2393 2388 2394 - if (!pnfs_layout_is_valid(lo)) { 2395 - /* We have a completely new layout */ 2396 - pnfs_set_layout_stateid(lo, &res->stateid, lgp->cred, true); 2397 - } else if (nfs4_stateid_match_other(&lo->plh_stateid, &res->stateid)) { 2389 + if (nfs4_stateid_match_other(&lo->plh_stateid, &res->stateid)) { 2398 2390 /* existing state ID, make sure the sequence number matches. */ 2399 2391 if (pnfs_layout_stateid_blocked(lo, &res->stateid)) { 2392 + if (!pnfs_layout_is_valid(lo) && 2393 + pnfs_is_first_layoutget(lo)) 2394 + lo->plh_barrier = 0; 2400 2395 dprintk("%s forget reply due to sequence\n", __func__); 2401 2396 goto out_forget; 2402 2397 } 2403 2398 pnfs_set_layout_stateid(lo, &res->stateid, lgp->cred, false); 2404 - } else { 2399 + } else if (pnfs_layout_is_valid(lo)) { 2405 2400 /* 2406 2401 * We got an entirely new state ID. Mark all segments for the 2407 2402 * inode invalid, and retry the layoutget ··· 2414 2409 pnfs_mark_matching_lsegs_return(lo, &lo->plh_return_segs, 2415 2410 &range, 0); 2416 2411 goto out_forget; 2412 + } else { 2413 + /* We have a completely new layout */ 2414 + if (!pnfs_is_first_layoutget(lo)) 2415 + goto out_forget; 2416 + pnfs_set_layout_stateid(lo, &res->stateid, lgp->cred, true); 2417 2417 } 2418 2418 2419 2419 pnfs_get_lseg(lseg);