]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
NFSD: fix management of pending async copies
authorOlga Kornievskaia <okorniev@redhat.com>
Tue, 17 Dec 2024 21:18:12 +0000 (16:18 -0500)
committerChuck Lever <chuck.lever@oracle.com>
Tue, 17 Dec 2024 21:35:53 +0000 (16:35 -0500)
Currently the pending_async_copies count is decremented just
before a struct nfsd4_copy is destroyed. After commit aa0ebd21df9c
("NFSD: Add nfsd4_copy time-to-live") nfsd4_copy structures sticks
around for 10 lease periods after the COPY itself has completed,
the pending_async_copies count stays high for a long time. This
causes NFSD to avoid the use of background copy even though the
actual background copy workload might no longer be running.

In this patch, decrement pending_async_copies once async copy thread
is done processing the copy work.

Fixes: aa0ebd21df9c ("NFSD: Add nfsd4_copy time-to-live")
Signed-off-by: Olga Kornievskaia <okorniev@redhat.com>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
fs/nfsd/nfs4proc.c

index f8a10f90bc7a4b288c20d2733c85f331cc0a8dba..ad44ad49274f035707fa648d12011844b1c79a44 100644 (file)
@@ -1347,7 +1347,6 @@ static void nfs4_put_copy(struct nfsd4_copy *copy)
 {
        if (!refcount_dec_and_test(&copy->refcount))
                return;
-       atomic_dec(&copy->cp_nn->pending_async_copies);
        kfree(copy->cp_src);
        kfree(copy);
 }
@@ -1870,6 +1869,7 @@ do_callback:
        set_bit(NFSD4_COPY_F_COMPLETED, &copy->cp_flags);
        trace_nfsd_copy_async_done(copy);
        nfsd4_send_cb_offload(copy);
+       atomic_dec(&copy->cp_nn->pending_async_copies);
        return 0;
 }
 
@@ -1927,19 +1927,19 @@ nfsd4_copy(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
                /* Arbitrary cap on number of pending async copy operations */
                if (atomic_inc_return(&nn->pending_async_copies) >
                                (int)rqstp->rq_pool->sp_nrthreads)
-                       goto out_err;
+                       goto out_dec_async_copy_err;
                async_copy->cp_src = kmalloc(sizeof(*async_copy->cp_src), GFP_KERNEL);
                if (!async_copy->cp_src)
-                       goto out_err;
+                       goto out_dec_async_copy_err;
                if (!nfs4_init_copy_state(nn, copy))
-                       goto out_err;
+                       goto out_dec_async_copy_err;
                memcpy(&result->cb_stateid, &copy->cp_stateid.cs_stid,
                        sizeof(result->cb_stateid));
                dup_copy_fields(copy, async_copy);
                async_copy->copy_task = kthread_create(nfsd4_do_async_copy,
                                async_copy, "%s", "copy thread");
                if (IS_ERR(async_copy->copy_task))
-                       goto out_err;
+                       goto out_dec_async_copy_err;
                spin_lock(&async_copy->cp_clp->async_lock);
                list_add(&async_copy->copies,
                                &async_copy->cp_clp->async_copies);
@@ -1954,6 +1954,9 @@ out:
        trace_nfsd_copy_done(copy, status);
        release_copy_files(copy);
        return status;
+out_dec_async_copy_err:
+       if (async_copy)
+               atomic_dec(&nn->pending_async_copies);
 out_err:
        if (nfsd4_ssc_is_inter(copy)) {
                /*