@@ -1708,7 +1708,7 @@ void nfsd4_revoke_states(struct net *net, struct super_block *sb)
unsigned int idhashval;
unsigned short sc_types;
- sc_types = NFS4_LOCK_STID;
+ sc_types = NFS4_OPEN_STID | NFS4_LOCK_STID;
spin_lock(&nn->client_lock);
for (idhashval = 0; idhashval < CLIENT_HASH_MASK; idhashval++) {
@@ -1723,6 +1723,18 @@ void nfsd4_revoke_states(struct net *net, struct super_block *sb)
spin_unlock(&nn->client_lock);
switch (stid->sc_type) {
+ case NFS4_OPEN_STID:
+ stp = openlockstateid(stid);
+ mutex_lock_nested(&stp->st_mutex,
+ OPEN_STATEID_MUTEX);
+ if (stid->sc_type == NFS4_OPEN_STID) {
+ release_all_access(stp);
+ stid->sc_type =
+ NFS4_ADMIN_REVOKED_STID;
+ atomic_inc(&clp->cl_admin_revoked);
+ }
+ mutex_unlock(&stp->st_mutex);
+ break;
case NFS4_LOCK_STID:
stp = openlockstateid(stid);
mutex_lock_nested(&stp->st_mutex,
@@ -4681,10 +4693,18 @@ nfsd4_find_existing_open(struct nfs4_file *fp, struct nfsd4_open *open)
static void nfsd_drop_revoked_stid(struct nfs4_stid *s)
{
struct nfs4_client *cl = s->sc_client;
+ LIST_HEAD(reaplist);
struct nfs4_ol_stateid *stp;
bool unhashed;
switch (s->sc_type) {
+ case NFS4_ADMIN_REVOKED_STID:
+ stp = openlockstateid(s);
+ if (unhash_open_stateid(stp, &reaplist))
+ put_ol_stateid_locked(stp, &reaplist);
+ spin_unlock(&cl->cl_lock);
+ free_ol_stateid_reaplist(&reaplist);
+ break;
case NFS4_ADMIN_REVOKED_LOCK_STID:
stp = openlockstateid(s);
unhashed = unhash_lock_stateid(stp);
Revoking state through 'unlock_filesystem' now revokes any open states found. When the stateids are then freed by the client, the revoked stateids will be cleaned up correctly. Possibly the related lock states should be revoked too, but a subsequent patch will do that for all lock state on the superblock. Signed-off-by: NeilBrown <neilb@suse.de> --- fs/nfsd/nfs4state.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-)