Skip to content

Commit 06efa66

Browse files
neilbrownchucklever
authored andcommitted
nfsd: allow delegation state ids to be revoked and then freed
Revoking state through 'unlock_filesystem' now revokes any delegation states found. When the stateids are then freed by the client, the revoked stateids will be cleaned up correctly. As there is already support for revoking delegations, we build on that for admin-revoking. Reviewed-by: Jeff Layton <jlayton@kernel.org> Signed-off-by: NeilBrown <neilb@suse.de> Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
1 parent 39657c7 commit 06efa66

1 file changed

Lines changed: 25 additions & 3 deletions

File tree

fs/nfsd/nfs4state.c

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1335,9 +1335,12 @@ unhash_delegation_locked(struct nfs4_delegation *dp, unsigned short statusmask)
13351335
if (!delegation_hashed(dp))
13361336
return false;
13371337

1338-
if (dp->dl_stid.sc_client->cl_minorversion == 0)
1338+
if (statusmask == SC_STATUS_REVOKED &&
1339+
dp->dl_stid.sc_client->cl_minorversion == 0)
13391340
statusmask = SC_STATUS_CLOSED;
13401341
dp->dl_stid.sc_status |= statusmask;
1342+
if (statusmask & SC_STATUS_ADMIN_REVOKED)
1343+
atomic_inc(&dp->dl_stid.sc_client->cl_admin_revoked);
13411344

13421345
/* Ensure that deleg break won't try to requeue it */
13431346
++dp->dl_time;
@@ -1368,7 +1371,8 @@ static void revoke_delegation(struct nfs4_delegation *dp)
13681371

13691372
trace_nfsd_stid_revoke(&dp->dl_stid);
13701373

1371-
if (dp->dl_stid.sc_status & SC_STATUS_REVOKED) {
1374+
if (dp->dl_stid.sc_status &
1375+
(SC_STATUS_REVOKED | SC_STATUS_ADMIN_REVOKED)) {
13721376
spin_lock(&clp->cl_lock);
13731377
refcount_inc(&dp->dl_stid.sc_count);
13741378
list_add(&dp->dl_recall_lru, &clp->cl_revoked);
@@ -1717,7 +1721,7 @@ void nfsd4_revoke_states(struct net *net, struct super_block *sb)
17171721
unsigned int idhashval;
17181722
unsigned int sc_types;
17191723

1720-
sc_types = SC_TYPE_OPEN | SC_TYPE_LOCK;
1724+
sc_types = SC_TYPE_OPEN | SC_TYPE_LOCK | SC_TYPE_DELEG;
17211725

17221726
spin_lock(&nn->client_lock);
17231727
for (idhashval = 0; idhashval < CLIENT_HASH_MASK; idhashval++) {
@@ -1729,6 +1733,7 @@ void nfsd4_revoke_states(struct net *net, struct super_block *sb)
17291733
sc_types);
17301734
if (stid) {
17311735
struct nfs4_ol_stateid *stp;
1736+
struct nfs4_delegation *dp;
17321737

17331738
spin_unlock(&nn->client_lock);
17341739
switch (stid->sc_type) {
@@ -1774,6 +1779,16 @@ void nfsd4_revoke_states(struct net *net, struct super_block *sb)
17741779
spin_unlock(&clp->cl_lock);
17751780
mutex_unlock(&stp->st_mutex);
17761781
break;
1782+
case SC_TYPE_DELEG:
1783+
dp = delegstateid(stid);
1784+
spin_lock(&state_lock);
1785+
if (!unhash_delegation_locked(
1786+
dp, SC_STATUS_ADMIN_REVOKED))
1787+
dp = NULL;
1788+
spin_unlock(&state_lock);
1789+
if (dp)
1790+
revoke_delegation(dp);
1791+
break;
17771792
}
17781793
nfs4_put_stid(stid);
17791794
spin_lock(&nn->client_lock);
@@ -4676,6 +4691,7 @@ static void nfsd4_drop_revoked_stid(struct nfs4_stid *s)
46764691
struct nfs4_client *cl = s->sc_client;
46774692
LIST_HEAD(reaplist);
46784693
struct nfs4_ol_stateid *stp;
4694+
struct nfs4_delegation *dp;
46794695
bool unhashed;
46804696

46814697
switch (s->sc_type) {
@@ -4693,6 +4709,12 @@ static void nfsd4_drop_revoked_stid(struct nfs4_stid *s)
46934709
if (unhashed)
46944710
nfs4_put_stid(s);
46954711
break;
4712+
case SC_TYPE_DELEG:
4713+
dp = delegstateid(s);
4714+
list_del_init(&dp->dl_recall_lru);
4715+
spin_unlock(&cl->cl_lock);
4716+
nfs4_put_stid(s);
4717+
break;
46964718
default:
46974719
spin_unlock(&cl->cl_lock);
46984720
}

0 commit comments

Comments
 (0)