Commit 1c13bf9f authored by NeilBrown's avatar NeilBrown Committed by Chuck Lever
Browse files

nfsd: allow lock state ids to be revoked and then freed



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: default avatarJeff Layton <jlayton@kernel.org>
Signed-off-by: default avatarNeilBrown <neilb@suse.de>
Signed-off-by: default avatarChuck Lever <chuck.lever@oracle.com>
parent d688d858
Loading
Loading
Loading
Loading
+39 −1
Original line number Diff line number Diff line
@@ -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++) {
@@ -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);
@@ -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);
	}