]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
NFS/pnfs: Fix the error path in pnfs_layoutreturn_retry_later_locked()
authorTrond Myklebust <trond.myklebust@hammerspace.com>
Sat, 10 May 2025 15:05:36 +0000 (11:05 -0400)
committerTrond Myklebust <trond.myklebust@hammerspace.com>
Fri, 16 May 2025 20:31:35 +0000 (22:31 +0200)
If there isn't a valid layout, or the layout stateid has changed, the
cleanup after a layout return should clear out the old data.

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

index fc7c5fb101980614b9b94609d8f0b88dfbdb6799..3adb7d0dbec7ac645545395322b48849cd3b190e 100644 (file)
@@ -1254,21 +1254,15 @@ static void pnfs_clear_layoutcommit(struct inode *inode,
 static void
 pnfs_layoutreturn_retry_later_locked(struct pnfs_layout_hdr *lo,
                                     const nfs4_stateid *arg_stateid,
-                                    const struct pnfs_layout_range *range)
+                                    const struct pnfs_layout_range *range,
+                                    struct list_head *freeme)
 {
-       const struct pnfs_layout_segment *lseg;
-       u32 seq = be32_to_cpu(arg_stateid->seqid);
-
        if (pnfs_layout_is_valid(lo) &&
-           nfs4_stateid_match_other(&lo->plh_stateid, arg_stateid)) {
-               list_for_each_entry(lseg, &lo->plh_return_segs, pls_list) {
-                       if (pnfs_seqid_is_newer(lseg->pls_seq, seq) ||
-                           !pnfs_should_free_range(&lseg->pls_range, range))
-                               continue;
-                       pnfs_set_plh_return_info(lo, range->iomode, seq);
-                       break;
-               }
-       }
+           nfs4_stateid_match_other(&lo->plh_stateid, arg_stateid))
+               pnfs_reset_return_info(lo);
+       else
+               pnfs_mark_layout_stateid_invalid(lo, freeme);
+       pnfs_clear_layoutreturn_waitbit(lo);
 }
 
 void pnfs_layoutreturn_retry_later(struct pnfs_layout_hdr *lo,
@@ -1276,11 +1270,12 @@ void pnfs_layoutreturn_retry_later(struct pnfs_layout_hdr *lo,
                                   const struct pnfs_layout_range *range)
 {
        struct inode *inode = lo->plh_inode;
+       LIST_HEAD(freeme);
 
        spin_lock(&inode->i_lock);
-       pnfs_layoutreturn_retry_later_locked(lo, arg_stateid, range);
-       pnfs_clear_layoutreturn_waitbit(lo);
+       pnfs_layoutreturn_retry_later_locked(lo, arg_stateid, range, &freeme);
        spin_unlock(&inode->i_lock);
+       pnfs_free_lseg_list(&freeme);
 }
 
 void pnfs_layoutreturn_free_lsegs(struct pnfs_layout_hdr *lo,
@@ -1716,6 +1711,7 @@ void pnfs_roc_release(struct nfs4_layoutreturn_args *args,
        struct inode *inode = args->inode;
        const nfs4_stateid *res_stateid = NULL;
        struct nfs4_xdr_opaque_data *ld_private = args->ld_private;
+       LIST_HEAD(freeme);
 
        switch (ret) {
        case -NFS4ERR_BADSESSION:
@@ -1724,9 +1720,9 @@ void pnfs_roc_release(struct nfs4_layoutreturn_args *args,
        case -NFS4ERR_NOMATCHING_LAYOUT:
                spin_lock(&inode->i_lock);
                pnfs_layoutreturn_retry_later_locked(lo, &args->stateid,
-                                                    &args->range);
-               pnfs_clear_layoutreturn_waitbit(lo);
+                                                    &args->range, &freeme);
                spin_unlock(&inode->i_lock);
+               pnfs_free_lseg_list(&freeme);
                break;
        case 0:
                if (res->lrs_present)