Skip to content

Commit

Permalink
nfsd4: keep a reference count on client while in use
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Benny Halevy authored and J. Bruce Fields committed May 13, 2010
1 parent 07cd490 commit d768298
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 4 deletions.
27 changes: 24 additions & 3 deletions fs/nfsd/nfs4state.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -1476,8 +1492,7 @@ nfsd4_sequence(struct svc_rqst *rqstp,
/* 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));
Expand Down Expand Up @@ -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) {
Expand Down
3 changes: 2 additions & 1 deletion fs/nfsd/nfs4xdr.c
Original file line number Diff line number Diff line change
Expand Up @@ -3313,7 +3313,8 @@ nfs4svc_encode_compoundres(struct svc_rqst *rqstp, __be32 *p, struct nfsd4_compo
dprintk("%s: SET SLOT STATE TO AVAILABLE\n", __func__);
cs->slot->sl_inuse = false;
}
nfsd4_put_session(cs->session);
/* Renew the clientid on success and on replay */
release_session_client(cs->session);
}
return 1;
}
Expand Down
1 change: 1 addition & 0 deletions fs/nfsd/state.h
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,7 @@ extern int nfs4_has_reclaimed_state(const char *name, bool use_exchange_id);
extern void nfsd4_recdir_purge_old(void);
extern int nfsd4_create_clid_dir(struct nfs4_client *clp);
extern void nfsd4_remove_clid_dir(struct nfs4_client *clp);
extern void release_session_client(struct nfsd4_session *);

static inline void
nfs4_put_stateowner(struct nfs4_stateowner *so)
Expand Down

0 comments on commit d768298

Please sign in to comment.