@@ -441,24 +441,29 @@ static void unhash_stid(struct nfs4_stid *s)
dp->dl_stid.sc_type = NFS4_DELEG_STID;
}
-/* Called under the state lock. */
static void
-unhash_delegation(struct nfs4_delegation *dp)
+unhash_delegation_locked(struct nfs4_delegation *dp)
{
- spin_lock(&recall_lock);
list_del_init(&dp->dl_perclnt);
list_del_init(&dp->dl_perfile);
list_del_init(&dp->dl_recall_lru);
dp->dl_stid.sc_type = 0;
nfs4_put_deleg_lease(dp->dl_file);
- spin_unlock(&recall_lock);
}
-
+static void
+unhash_delegation(struct nfs4_delegation *dp)
+{
+ spin_lock(&recall_lock);
+ unhash_delegation_locked(dp);
+ spin_unlock(&recall_lock);
+}
static void destroy_revoked_delegation(struct nfs4_delegation *dp)
{
+ spin_lock(&recall_lock);
list_del_init(&dp->dl_recall_lru);
+ spin_unlock(&recall_lock);
nfs4_put_delegation(dp);
}
@@ -475,9 +480,11 @@ static void revoke_delegation(struct nfs4_delegation *dp)
if (clp->cl_minorversion == 0)
destroy_delegation(dp);
else {
- unhash_delegation(dp);
+ spin_lock(&recall_lock);
+ unhash_delegation_locked(dp);
dp->dl_stid.sc_type = NFS4_REVOKED_DELEG_STID;
list_add(&dp->dl_recall_lru, &clp->cl_revoked);
+ spin_unlock(&recall_lock);
}
}
@@ -2729,6 +2736,7 @@ static void nfsd_break_one_deleg(struct nfs4_delegation *dp)
struct nfs4_client *clp = dp->dl_stid.sc_client;
struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
+ lockdep_assert_held(&recall_lock);
/* We're assuming the state code never drops its reference
* without first removing the lease. Since we're in this lease
* callback (and since the lease code is serialized by the kernel
Signed-off-by: Benny Halevy <bhalevy@primarydata.com> --- fs/nfsd/nfs4state.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-)