Skip to content

Commit

Permalink
nfsd4: shut down more of delegation earlier
Browse files Browse the repository at this point in the history
Once we've unhashed the delegation, it's only hanging around for the
benefit of an oustanding recall, which only needs the encoded
filehandle, stateid, and dl_retries counter.  No point keeping the file
around any longer, or keeping it hashed.

This also fixes a race: calls to idr_remove should really be serialized
by the caller, but the nfs4_put_delegation call from the callback code
isn't taking the state lock.

(Better might be to cancel the callback before destroying the
delegation, and remove any need for reference counting--but I don't see
an easy way to cancel an rpc call.)

Signed-off-by: J. Bruce Fields <bfields@redhat.com>
  • Loading branch information
J. Bruce Fields committed Apr 4, 2013
1 parent 8be2d23 commit 68a3396
Showing 1 changed file with 7 additions and 6 deletions.
13 changes: 7 additions & 6 deletions fs/nfsd/nfs4state.c
Original file line number Diff line number Diff line change
Expand Up @@ -417,21 +417,18 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_ol_stateid *stp, struct sv
return dp;
}

static void free_stid(struct nfs4_stid *s, struct kmem_cache *slab)
static void remove_stid(struct nfs4_stid *s)
{
struct idr *stateids = &s->sc_client->cl_stateids;

idr_remove(stateids, s->sc_stateid.si_opaque.so_id);
kmem_cache_free(slab, s);
}

void
nfs4_put_delegation(struct nfs4_delegation *dp)
{
if (atomic_dec_and_test(&dp->dl_count)) {
dprintk("NFSD: freeing dp %p\n",dp);
put_nfs4_file(dp->dl_file);
free_stid(&dp->dl_stid, deleg_slab);
kmem_cache_free(deleg_slab, dp);
num_delegations--;
}
}
Expand Down Expand Up @@ -462,6 +459,9 @@ unhash_delegation(struct nfs4_delegation *dp)
list_del_init(&dp->dl_recall_lru);
spin_unlock(&recall_lock);
nfs4_put_deleg_lease(dp->dl_file);
put_nfs4_file(dp->dl_file);
dp->dl_file = NULL;
remove_stid(&dp->dl_stid);
nfs4_put_delegation(dp);
}

Expand Down Expand Up @@ -605,7 +605,8 @@ static void close_generic_stateid(struct nfs4_ol_stateid *stp)

static void free_generic_stateid(struct nfs4_ol_stateid *stp)
{
free_stid(&stp->st_stid, stateid_slab);
remove_stid(&stp->st_stid);
kmem_cache_free(stateid_slab, stp);
}

static void release_lock_stateid(struct nfs4_ol_stateid *stp)
Expand Down

0 comments on commit 68a3396

Please sign in to comment.