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: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
This commit is contained in:
Chuck Lever 2024-10-31 09:40:06 -04:00
parent 5c41f32147
commit b44ffa4c4f
3 changed files with 32 additions and 1 deletions

View File

@ -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))

View File

@ -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,

View 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);
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);