Skip to content

Commit 62a8642

Browse files
committed
NFSD: Fix nfsd4_shutdown_copy()
nfsd4_shutdown_copy() is just this: while ((copy = nfsd4_get_copy(clp)) != NULL) nfsd4_stop_copy(copy); nfsd4_get_copy() bumps @copy's reference count, preventing nfsd4_stop_copy() from releasing @copy. A while loop like this usually works by removing the first element of the list, but neither nfsd4_get_copy() nor nfsd4_stop_copy() alters the async_copies list. Best I can tell, then, is that nfsd4_shutdown_copy() continues to loop until other threads manage to remove all the items from this list. The spinning loop blocks shutdown until these items are gone. Possibly the reason we haven't seen this issue in the field is because client_has_state() prevents __destroy_client() from calling nfsd4_shutdown_copy() if there are any items on this list. In a subsequent patch I plan to remove that restriction. Fixes: e0639dc ("NFSD introduce async copy feature") Reviewed-by: Jeff Layton <jlayton@kernel.org> Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
1 parent a4452e6 commit 62a8642

File tree

1 file changed

+5
-2
lines changed

1 file changed

+5
-2
lines changed

fs/nfsd/nfs4proc.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1293,7 +1293,7 @@ static void nfsd4_stop_copy(struct nfsd4_copy *copy)
12931293
nfs4_put_copy(copy);
12941294
}
12951295

1296-
static struct nfsd4_copy *nfsd4_get_copy(struct nfs4_client *clp)
1296+
static struct nfsd4_copy *nfsd4_unhash_copy(struct nfs4_client *clp)
12971297
{
12981298
struct nfsd4_copy *copy = NULL;
12991299

@@ -1302,6 +1302,9 @@ static struct nfsd4_copy *nfsd4_get_copy(struct nfs4_client *clp)
13021302
copy = list_first_entry(&clp->async_copies, struct nfsd4_copy,
13031303
copies);
13041304
refcount_inc(&copy->refcount);
1305+
copy->cp_clp = NULL;
1306+
if (!list_empty(&copy->copies))
1307+
list_del_init(&copy->copies);
13051308
}
13061309
spin_unlock(&clp->async_lock);
13071310
return copy;
@@ -1311,7 +1314,7 @@ void nfsd4_shutdown_copy(struct nfs4_client *clp)
13111314
{
13121315
struct nfsd4_copy *copy;
13131316

1314-
while ((copy = nfsd4_get_copy(clp)) != NULL)
1317+
while ((copy = nfsd4_unhash_copy(clp)) != NULL)
13151318
nfsd4_stop_copy(copy);
13161319
}
13171320
#ifdef CONFIG_NFSD_V4_2_INTER_SSC

0 commit comments

Comments
 (0)