Skip to content

Commit 68ef3bc

Browse files
jtlaytonJ. Bruce Fields
authored andcommitted
nfsd: remove blocked locks on client teardown
We had some reports of panics in nfsd4_lm_notify, and that showed a nfs4_lockowner that had outlived its so_client. Ensure that we walk any leftover lockowners after tearing down all of the stateids, and remove any blocked locks that they hold. With this change, we also don't need to walk the nbl_lru on nfsd_net shutdown, as that will happen naturally when we tear down the clients. Fixes: 76d348f (nfsd: have nfsd4_lock use blocking locks for v4.1+ locks) Reported-by: Frank Sorenson <[email protected]> Signed-off-by: Jeff Layton <[email protected]> Cc: [email protected] # 4.9 Signed-off-by: J. Bruce Fields <[email protected]>
1 parent 91ab883 commit 68ef3bc

File tree

1 file changed

+43
-19
lines changed

1 file changed

+43
-19
lines changed

fs/nfsd/nfs4state.c

Lines changed: 43 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,35 @@ free_blocked_lock(struct nfsd4_blocked_lock *nbl)
268268
kfree(nbl);
269269
}
270270

271+
static void
272+
remove_blocked_locks(struct nfs4_lockowner *lo)
273+
{
274+
struct nfs4_client *clp = lo->lo_owner.so_client;
275+
struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
276+
struct nfsd4_blocked_lock *nbl;
277+
LIST_HEAD(reaplist);
278+
279+
/* Dequeue all blocked locks */
280+
spin_lock(&nn->blocked_locks_lock);
281+
while (!list_empty(&lo->lo_blocked)) {
282+
nbl = list_first_entry(&lo->lo_blocked,
283+
struct nfsd4_blocked_lock,
284+
nbl_list);
285+
list_del_init(&nbl->nbl_list);
286+
list_move(&nbl->nbl_lru, &reaplist);
287+
}
288+
spin_unlock(&nn->blocked_locks_lock);
289+
290+
/* Now free them */
291+
while (!list_empty(&reaplist)) {
292+
nbl = list_first_entry(&reaplist, struct nfsd4_blocked_lock,
293+
nbl_lru);
294+
list_del_init(&nbl->nbl_lru);
295+
posix_unblock_lock(&nbl->nbl_lock);
296+
free_blocked_lock(nbl);
297+
}
298+
}
299+
271300
static int
272301
nfsd4_cb_notify_lock_done(struct nfsd4_callback *cb, struct rpc_task *task)
273302
{
@@ -1866,6 +1895,7 @@ static __be32 mark_client_expired_locked(struct nfs4_client *clp)
18661895
static void
18671896
__destroy_client(struct nfs4_client *clp)
18681897
{
1898+
int i;
18691899
struct nfs4_openowner *oo;
18701900
struct nfs4_delegation *dp;
18711901
struct list_head reaplist;
@@ -1895,6 +1925,16 @@ __destroy_client(struct nfs4_client *clp)
18951925
nfs4_get_stateowner(&oo->oo_owner);
18961926
release_openowner(oo);
18971927
}
1928+
for (i = 0; i < OWNER_HASH_SIZE; i++) {
1929+
struct nfs4_stateowner *so, *tmp;
1930+
1931+
list_for_each_entry_safe(so, tmp, &clp->cl_ownerstr_hashtbl[i],
1932+
so_strhash) {
1933+
/* Should be no openowners at this point */
1934+
WARN_ON_ONCE(so->so_is_open_owner);
1935+
remove_blocked_locks(lockowner(so));
1936+
}
1937+
}
18981938
nfsd4_return_all_client_layouts(clp);
18991939
nfsd4_shutdown_callback(clp);
19001940
if (clp->cl_cb_conn.cb_xprt)
@@ -6355,6 +6395,7 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp,
63556395
}
63566396
spin_unlock(&clp->cl_lock);
63576397
free_ol_stateid_reaplist(&reaplist);
6398+
remove_blocked_locks(lo);
63586399
nfs4_put_stateowner(&lo->lo_owner);
63596400

63606401
return status;
@@ -7140,6 +7181,8 @@ nfs4_state_destroy_net(struct net *net)
71407181
}
71417182
}
71427183

7184+
WARN_ON(!list_empty(&nn->blocked_locks_lru));
7185+
71437186
for (i = 0; i < CLIENT_HASH_SIZE; i++) {
71447187
while (!list_empty(&nn->unconf_id_hashtbl[i])) {
71457188
clp = list_entry(nn->unconf_id_hashtbl[i].next, struct nfs4_client, cl_idhash);
@@ -7206,7 +7249,6 @@ nfs4_state_shutdown_net(struct net *net)
72067249
struct nfs4_delegation *dp = NULL;
72077250
struct list_head *pos, *next, reaplist;
72087251
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
7209-
struct nfsd4_blocked_lock *nbl;
72107252

72117253
cancel_delayed_work_sync(&nn->laundromat_work);
72127254
locks_end_grace(&nn->nfsd4_manager);
@@ -7227,24 +7269,6 @@ nfs4_state_shutdown_net(struct net *net)
72277269
nfs4_put_stid(&dp->dl_stid);
72287270
}
72297271

7230-
BUG_ON(!list_empty(&reaplist));
7231-
spin_lock(&nn->blocked_locks_lock);
7232-
while (!list_empty(&nn->blocked_locks_lru)) {
7233-
nbl = list_first_entry(&nn->blocked_locks_lru,
7234-
struct nfsd4_blocked_lock, nbl_lru);
7235-
list_move(&nbl->nbl_lru, &reaplist);
7236-
list_del_init(&nbl->nbl_list);
7237-
}
7238-
spin_unlock(&nn->blocked_locks_lock);
7239-
7240-
while (!list_empty(&reaplist)) {
7241-
nbl = list_first_entry(&reaplist,
7242-
struct nfsd4_blocked_lock, nbl_lru);
7243-
list_del_init(&nbl->nbl_lru);
7244-
posix_unblock_lock(&nbl->nbl_lock);
7245-
free_blocked_lock(nbl);
7246-
}
7247-
72487272
nfsd4_client_tracking_exit(net);
72497273
nfs4_state_destroy_net(net);
72507274
}

0 commit comments

Comments
 (0)