Commit ac0514f4 authored by Chuck Lever's avatar Chuck Lever
Browse files

NFSD: Add a laundromat reaper for async copy state



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: default avatarJeff Layton <jlayton@kernel.org>
Signed-off-by: default avatarChuck Lever <chuck.lever@oracle.com>
parent b44ffa4c
Loading
Loading
Loading
Loading
+34 −1
Original line number Diff line number Diff line
@@ -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,
+1 −0
Original line number Diff line number Diff line
@@ -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);

+1 −0
Original line number Diff line number Diff line
@@ -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);
+1 −0
Original line number Diff line number Diff line
@@ -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;