NFSv4/pnfs: Fix layoutget behaviour after invalidation
authorTrond Myklebust <trond.myklebust@hammerspace.com>
Fri, 2 Jul 2021 23:48:41 +0000 (19:48 -0400)
committerTrond Myklebust <trond.myklebust@hammerspace.com>
Thu, 8 Jul 2021 18:03:26 +0000 (14:03 -0400)
If the layout gets invalidated, we should wait for any outstanding
layoutget requests for that layout to complete, and we should resend
them only after re-establishing the layout stateid.

Fixes: d29b468da4f9 ("pNFS/NFSv4: Improve rejection of out-of-order layouts")
Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
fs/nfs/pnfs.c

index ffe02e4..be960e4 100644 (file)
@@ -2014,7 +2014,7 @@ lookup_again:
         * If the layout segment list is empty, but there are outstanding
         * layoutget calls, then they might be subject to a layoutrecall.
         */
-       if (list_empty(&lo->plh_segs) &&
+       if ((list_empty(&lo->plh_segs) || !pnfs_layout_is_valid(lo)) &&
            atomic_read(&lo->plh_outstanding) != 0) {
                spin_unlock(&ino->i_lock);
                lseg = ERR_PTR(wait_var_event_killable(&lo->plh_outstanding,
@@ -2390,11 +2390,13 @@ pnfs_layout_process(struct nfs4_layoutget *lgp)
                goto out_forget;
        }
 
+       if (!pnfs_layout_is_valid(lo) && !pnfs_is_first_layoutget(lo))
+               goto out_forget;
+
        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)) {
-                       if (!pnfs_layout_is_valid(lo) &&
-                           pnfs_is_first_layoutget(lo))
+                       if (!pnfs_layout_is_valid(lo))
                                lo->plh_barrier = 0;
                        dprintk("%s forget reply due to sequence\n", __func__);
                        goto out_forget;
@@ -2413,8 +2415,6 @@ pnfs_layout_process(struct nfs4_layoutget *lgp)
                goto out_forget;
        } else {
                /* We have a completely new layout */
-               if (!pnfs_is_first_layoutget(lo))
-                       goto out_forget;
                pnfs_set_layout_stateid(lo, &res->stateid, lgp->cred, true);
        }