]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
NFSv4/pNFS: Retry the layout return later in case of a timeout or reboot
authorTrond Myklebust <trond.myklebust@hammerspace.com>
Thu, 13 Jun 2024 05:00:52 +0000 (01:00 -0400)
committerAnna Schumaker <Anna.Schumaker@Netapp.com>
Mon, 8 Jul 2024 17:47:26 +0000 (13:47 -0400)
If the layout return failed due to a timeout or reboot, then leave the
layout segments on the list so that the layout return gets replayed
later.
The exception would be if we're freeing the inode.

Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
fs/nfs/nfs4proc.c
fs/nfs/pnfs.c
fs/nfs/pnfs.h

index db585a6a8f0d0fabdbb918597be7e7fa2b29dc83..e5103fa9d4103a98145519d6d6a41a299b316cc5 100644 (file)
@@ -9973,6 +9973,11 @@ static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata)
        if (!nfs41_sequence_process(task, &lrp->res.seq_res))
                return;
 
+       if (task->tk_rpc_status == -ETIMEDOUT) {
+               lrp->rpc_status = -EAGAIN;
+               lrp->res.lrs_present = 0;
+               return;
+       }
        /*
         * Was there an RPC level error? Assume the call succeeded,
         * and that we need to release the layout
@@ -9995,6 +10000,15 @@ static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata)
                fallthrough;
        case 0:
                break;
+       case -NFS4ERR_BADSESSION:
+       case -NFS4ERR_DEADSESSION:
+       case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION:
+               nfs4_schedule_session_recovery(server->nfs_client->cl_session,
+                                              task->tk_status);
+               lrp->res.lrs_present = 0;
+               lrp->rpc_status = -EAGAIN;
+               task->tk_status = 0;
+               break;
        case -NFS4ERR_DELAY:
                if (nfs4_async_handle_error(task, server, NULL, NULL) != -EAGAIN)
                        break;
@@ -10012,8 +10026,13 @@ static void nfs4_layoutreturn_release(void *calldata)
        struct nfs4_layoutreturn *lrp = calldata;
        struct pnfs_layout_hdr *lo = lrp->args.layout;
 
-       pnfs_layoutreturn_free_lsegs(lo, &lrp->args.stateid, &lrp->args.range,
+       if (lrp->rpc_status == 0 || !lrp->inode)
+               pnfs_layoutreturn_free_lsegs(
+                       lo, &lrp->args.stateid, &lrp->args.range,
                        lrp->res.lrs_present ? &lrp->res.stateid : NULL);
+       else
+               pnfs_layoutreturn_retry_later(lo, &lrp->args.stateid,
+                                             &lrp->args.range);
        nfs4_sequence_free_slot(&lrp->res.seq_res);
        if (lrp->ld_private.ops && lrp->ld_private.ops->free)
                lrp->ld_private.ops->free(&lrp->ld_private);
index c8b1be1810e2daeee1fdfbdd4f9e6e464c5145d4..04a52fa3d28cd9aabe86261e4a6ee5938672f303 100644 (file)
@@ -1191,6 +1191,18 @@ pnfs_layoutreturn_retry_later_locked(struct pnfs_layout_hdr *lo,
        }
 }
 
+void pnfs_layoutreturn_retry_later(struct pnfs_layout_hdr *lo,
+                                  const nfs4_stateid *arg_stateid,
+                                  const struct pnfs_layout_range *range)
+{
+       struct inode *inode = lo->plh_inode;
+
+       spin_lock(&inode->i_lock);
+       pnfs_layoutreturn_retry_later_locked(lo, arg_stateid, range);
+       pnfs_clear_layoutreturn_waitbit(lo);
+       spin_unlock(&inode->i_lock);
+}
+
 void pnfs_layoutreturn_free_lsegs(struct pnfs_layout_hdr *lo,
                const nfs4_stateid *arg_stateid,
                const struct pnfs_layout_range *range,
index 8fa0f152ed194e4b0b4c8307f5b4ddefbc09b7bd..cd23a38eac75421f76c071a58fe72e7a64986931 100644 (file)
@@ -328,6 +328,9 @@ struct pnfs_layout_segment *pnfs_update_layout(struct inode *ino,
                                               enum pnfs_iomode iomode,
                                               bool strict_iomode,
                                               gfp_t gfp_flags);
+void pnfs_layoutreturn_retry_later(struct pnfs_layout_hdr *lo,
+                                  const nfs4_stateid *arg_stateid,
+                                  const struct pnfs_layout_range *range);
 void pnfs_layoutreturn_free_lsegs(struct pnfs_layout_hdr *lo,
                const nfs4_stateid *arg_stateid,
                const struct pnfs_layout_range *range,