nfsd4: keep a reference count on client while in use

Get a refcount on the client on SEQUENCE,
Release the refcount and renew the client when all respective compounds completed.
Do not expire the client by the laundromat while in use.
If the client was expired via another path, free it when the compounds
complete and the refcount reaches 0.

Note that unhash_client_locked must call list_del_init on cl_lru as
it may be called twice for the same client (once from nfs4_laundromat
and then from expire_client)

Signed-off-by: Benny Halevy <bhalevy@panasas.com>
Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
This commit is contained in:
Benny Halevy 2010-05-12 00:13:54 +03:00 committed by J. Bruce Fields
parent 07cd4909a6
commit d76829889a
3 changed files with 27 additions and 4 deletions

View file

@ -701,6 +701,22 @@ free_client(struct nfs4_client *clp)
kfree(clp);
}
void
release_session_client(struct nfsd4_session *session)
{
struct nfs4_client *clp = session->se_client;
if (!atomic_dec_and_lock(&clp->cl_refcount, &client_lock))
return;
if (is_client_expired(clp)) {
free_client(clp);
session->se_client = NULL;
} else
renew_client_locked(clp);
spin_unlock(&client_lock);
nfsd4_put_session(session);
}
/* must be called under the client_lock */
static inline void
unhash_client_locked(struct nfs4_client *clp)
@ -1476,8 +1492,7 @@ out:
/* Hold a session reference until done processing the compound. */
if (cstate->session) {
nfsd4_get_session(cstate->session);
/* Renew the clientid on success and on replay */
renew_client_locked(session->se_client);
atomic_inc(&session->se_client->cl_refcount);
}
spin_unlock(&client_lock);
dprintk("%s: return %d\n", __func__, ntohl(status));
@ -2598,7 +2613,13 @@ nfs4_laundromat(void)
clientid_val = t;
break;
}
list_move(&clp->cl_lru, &reaplist);
if (atomic_read(&clp->cl_refcount)) {
dprintk("NFSD: client in use (clientid %08x)\n",
clp->cl_clientid.cl_id);
continue;
}
unhash_client_locked(clp);
list_add(&clp->cl_lru, &reaplist);
}
spin_unlock(&client_lock);
list_for_each_safe(pos, next, &reaplist) {