]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
NFSD: Add a laundromat reaper for async copy state
authorChuck Lever <chuck.lever@oracle.com>
Thu, 31 Oct 2024 13:40:07 +0000 (09:40 -0400)
committerChuck Lever <chuck.lever@oracle.com>
Tue, 19 Nov 2024 01:23:11 +0000 (20:23 -0500)
RFC 7862 Section 4.8 states:

> A copy offload stateid will be valid until either (A) the client
> or server restarts or (B) the client returns the resource by
> issuing an OFFLOAD_CANCEL operation or the client replies to a
> CB_OFFLOAD operation.

Instead of releasing async copy state when the CB_OFFLOAD callback
completes, now let it live until the next laundromat run after the
callback completes.

Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
fs/nfsd/nfs4proc.c
fs/nfsd/nfs4state.c
fs/nfsd/state.h
fs/nfsd/xdr4.h

index 67349eca55b114ac49d312885434b1163c863d38..dfc118bf9aa5d33ccf690cacafdcb7c0621c9441 100644 (file)
@@ -1308,6 +1308,39 @@ bool nfsd4_has_active_async_copies(struct nfs4_client *clp)
        return result;
 }
 
+/**
+ * nfsd4_async_copy_reaper - Purge completed copies
+ * @nn: Network namespace with possible active copy information
+ */
+void nfsd4_async_copy_reaper(struct nfsd_net *nn)
+{
+       struct nfs4_client *clp;
+       struct nfsd4_copy *copy;
+       LIST_HEAD(reaplist);
+
+       spin_lock(&nn->client_lock);
+       list_for_each_entry(clp, &nn->client_lru, cl_lru) {
+               struct list_head *pos, *next;
+
+               spin_lock(&clp->async_lock);
+               list_for_each_safe(pos, next, &clp->async_copies) {
+                       copy = list_entry(pos, struct nfsd4_copy, copies);
+                       if (test_bit(NFSD4_COPY_F_OFFLOAD_DONE, &copy->cp_flags)) {
+                               list_del_init(&copy->copies);
+                               list_add(&copy->copies, &reaplist);
+                       }
+               }
+               spin_unlock(&clp->async_lock);
+       }
+       spin_unlock(&nn->client_lock);
+
+       while (!list_empty(&reaplist)) {
+               copy = list_first_entry(&reaplist, struct nfsd4_copy, copies);
+               list_del_init(&copy->copies);
+               cleanup_async_copy(copy);
+       }
+}
+
 static void nfs4_put_copy(struct nfsd4_copy *copy)
 {
        if (!refcount_dec_and_test(&copy->refcount))
@@ -1637,7 +1670,7 @@ static void nfsd4_cb_offload_release(struct nfsd4_callback *cb)
        struct nfsd4_copy *copy =
                container_of(cbo, struct nfsd4_copy, cp_cb_offload);
 
-       cleanup_async_copy(copy);
+       set_bit(NFSD4_COPY_F_OFFLOAD_DONE, &copy->cp_flags);
 }
 
 static int nfsd4_cb_offload_done(struct nfsd4_callback *cb,
index b8bedc6a157f49d384bf10c4b57bd11036105e9a..10aa7732e9146f3093d6c48e8e9a998b7e10ef73 100644 (file)
@@ -6574,6 +6574,7 @@ nfs4_laundromat(struct nfsd_net *nn)
                        _free_cpntf_state_locked(nn, cps);
        }
        spin_unlock(&nn->s2s_cp_lock);
+       nfsd4_async_copy_reaper(nn);
        nfs4_get_client_reaplist(nn, &reaplist, &lt);
        nfs4_process_client_reaplist(&reaplist);
 
index 4dd7ed7ae052492aaaa78694aeeb3f095dcfc80e..dcbebd53e5f409d0b661c5464a779afa80e9dc62 100644 (file)
@@ -738,6 +738,7 @@ extern void nfsd4_init_cb(struct nfsd4_callback *cb, struct nfs4_client *clp,
 extern bool nfsd4_run_cb(struct nfsd4_callback *cb);
 extern void nfsd4_shutdown_callback(struct nfs4_client *);
 extern void nfsd4_shutdown_copy(struct nfs4_client *clp);
+void nfsd4_async_copy_reaper(struct nfsd_net *nn);
 bool nfsd4_has_active_async_copies(struct nfs4_client *clp);
 extern struct nfs4_client_reclaim *nfs4_client_to_reclaim(struct xdr_netobj name,
                                struct xdr_netobj princhash, struct nfsd_net *nn);
index 550f7e064f2ba94bee06a40a2e1e2b84126fc8fa..5951360f6d0393ce886e2594a7b6ce94f53a31a6 100644 (file)
@@ -695,6 +695,7 @@ struct nfsd4_copy {
 #define NFSD4_COPY_F_SYNCHRONOUS       (2)
 #define NFSD4_COPY_F_COMMITTED         (3)
 #define NFSD4_COPY_F_COMPLETED         (4)
+#define NFSD4_COPY_F_OFFLOAD_DONE      (5)
 
        /* response */
        __be32                  nfserr;