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

NFSD: Block DESTROY_CLIENTID only when there are ongoing async COPY operations



Currently __destroy_client() consults the nfs4_client's async_copies
list to determine whether there are ongoing async COPY operations.
However, NFSD now keeps copy state in that list even when the
async copy has completed, to enable OFFLOAD_STATUS to find the
COPY results for a while after the COPY has completed.

DESTROY_CLIENTID should not be blocked if the client's async_copies
list contains state for only completed copy operations.

Reviewed-by: default avatarJeff Layton <jlayton@kernel.org>
Signed-off-by: default avatarChuck Lever <chuck.lever@oracle.com>
parent 5c41f321
Loading
Loading
Loading
Loading
+30 −0
Original line number Diff line number Diff line
@@ -1278,6 +1278,36 @@ nfsd4_clone(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
	return status;
}

/**
 * nfsd4_has_active_async_copies - Check for ongoing copy operations
 * @clp: Client to be checked
 *
 * NFSD maintains state for async COPY operations after they complete,
 * and this state remains in the nfs4_client's async_copies list.
 * Ongoing copies should block the destruction of the nfs4_client, but
 * completed copies should not.
 *
 * Return values:
 *   %true: At least one active async COPY is ongoing
 *   %false: No active async COPY operations were found
 */
bool nfsd4_has_active_async_copies(struct nfs4_client *clp)
{
	struct nfsd4_copy *copy;
	bool result = false;

	spin_lock(&clp->async_lock);
	list_for_each_entry(copy, &clp->async_copies, copies) {
		if (!test_bit(NFSD4_COPY_F_COMPLETED, &copy->cp_flags) &&
		    !test_bit(NFSD4_COPY_F_STOPPED, &copy->cp_flags)) {
			result = true;
			break;
		}
	}
	spin_unlock(&clp->async_lock);
	return result;
}

static void nfs4_put_copy(struct nfsd4_copy *copy)
{
	if (!refcount_dec_and_test(&copy->refcount))
+1 −1
Original line number Diff line number Diff line
@@ -3472,7 +3472,7 @@ static bool client_has_state(struct nfs4_client *clp)
#endif
		|| !list_empty(&clp->cl_delegations)
		|| !list_empty(&clp->cl_sessions)
		|| !list_empty(&clp->async_copies);
		|| nfsd4_has_active_async_copies(clp);
}

static __be32 copy_impl_id(struct nfs4_client *clp,
+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);
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);
extern bool nfs4_has_reclaimed_state(struct xdr_netobj name, struct nfsd_net *nn);