Skip to content

Commit

Permalink
NFSD: Block DESTROY_CLIENTID only when there are ongoing async COPY o…
Browse files Browse the repository at this point in the history
…perations

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>
  • Loading branch information
Chuck Lever committed Nov 19, 2024
1 parent 5c41f32 commit b44ffa4
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 1 deletion.
30 changes: 30 additions & 0 deletions fs/nfsd/nfs4proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
2 changes: 1 addition & 1 deletion fs/nfsd/nfs4state.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
1 change: 1 addition & 0 deletions fs/nfsd/state.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit b44ffa4

Please sign in to comment.