Skip to content

Commit

Permalink
nfsd: allow lock state ids to be revoked and then freed
Browse files Browse the repository at this point in the history
Revoking state through 'unlock_filesystem' now revokes any lock states
found.  When the stateids are then freed by the client, the revoked
stateids will be cleaned up correctly.

Reviewed-by: Jeff Layton <[email protected]>
Signed-off-by: NeilBrown <[email protected]>
Signed-off-by: Chuck Lever <[email protected]>
  • Loading branch information
neilbrown authored and chucklever committed Mar 1, 2024
1 parent d688d85 commit 1c13bf9
Showing 1 changed file with 39 additions and 1 deletion.
40 changes: 39 additions & 1 deletion fs/nfsd/nfs4state.c
Original file line number Diff line number Diff line change
Expand Up @@ -1717,7 +1717,7 @@ void nfsd4_revoke_states(struct net *net, struct super_block *sb)
unsigned int idhashval;
unsigned int sc_types;

sc_types = 0;
sc_types = SC_TYPE_LOCK;

spin_lock(&nn->client_lock);
for (idhashval = 0; idhashval < CLIENT_HASH_MASK; idhashval++) {
Expand All @@ -1728,8 +1728,36 @@ void nfsd4_revoke_states(struct net *net, struct super_block *sb)
struct nfs4_stid *stid = find_one_sb_stid(clp, sb,
sc_types);
if (stid) {
struct nfs4_ol_stateid *stp;

spin_unlock(&nn->client_lock);
switch (stid->sc_type) {
case SC_TYPE_LOCK:
stp = openlockstateid(stid);
mutex_lock_nested(&stp->st_mutex,
LOCK_STATEID_MUTEX);
spin_lock(&clp->cl_lock);
if (stid->sc_status == 0) {
struct nfs4_lockowner *lo =
lockowner(stp->st_stateowner);
struct nfsd_file *nf;

stid->sc_status |=
SC_STATUS_ADMIN_REVOKED;
atomic_inc(&clp->cl_admin_revoked);
spin_unlock(&clp->cl_lock);
nf = find_any_file(stp->st_stid.sc_file);
if (nf) {
get_file(nf->nf_file);
filp_close(nf->nf_file,
(fl_owner_t)lo);
nfsd_file_put(nf);
}
release_all_access(stp);
} else
spin_unlock(&clp->cl_lock);
mutex_unlock(&stp->st_mutex);
break;
}
nfs4_put_stid(stid);
spin_lock(&nn->client_lock);
Expand Down Expand Up @@ -4630,8 +4658,18 @@ static void nfsd4_drop_revoked_stid(struct nfs4_stid *s)
__releases(&s->sc_client->cl_lock)
{
struct nfs4_client *cl = s->sc_client;
LIST_HEAD(reaplist);
struct nfs4_ol_stateid *stp;
bool unhashed;

switch (s->sc_type) {
case SC_TYPE_LOCK:
stp = openlockstateid(s);
unhashed = unhash_lock_stateid(stp);
spin_unlock(&cl->cl_lock);
if (unhashed)
nfs4_put_stid(s);
break;
default:
spin_unlock(&cl->cl_lock);
}
Expand Down

0 comments on commit 1c13bf9

Please sign in to comment.