Commit d76829889ac4250a18cfcc1a606bb256bb9c570c

Authored by Benny Halevy
Committed by J. Bruce Fields
1 parent 07cd4909a6

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>

Showing 3 changed files with 27 additions and 4 deletions Side-by-side Diff

... ... @@ -701,6 +701,22 @@
701 701 kfree(clp);
702 702 }
703 703  
  704 +void
  705 +release_session_client(struct nfsd4_session *session)
  706 +{
  707 + struct nfs4_client *clp = session->se_client;
  708 +
  709 + if (!atomic_dec_and_lock(&clp->cl_refcount, &client_lock))
  710 + return;
  711 + if (is_client_expired(clp)) {
  712 + free_client(clp);
  713 + session->se_client = NULL;
  714 + } else
  715 + renew_client_locked(clp);
  716 + spin_unlock(&client_lock);
  717 + nfsd4_put_session(session);
  718 +}
  719 +
704 720 /* must be called under the client_lock */
705 721 static inline void
706 722 unhash_client_locked(struct nfs4_client *clp)
... ... @@ -1476,8 +1492,7 @@
1476 1492 /* Hold a session reference until done processing the compound. */
1477 1493 if (cstate->session) {
1478 1494 nfsd4_get_session(cstate->session);
1479   - /* Renew the clientid on success and on replay */
1480   - renew_client_locked(session->se_client);
  1495 + atomic_inc(&session->se_client->cl_refcount);
1481 1496 }
1482 1497 spin_unlock(&client_lock);
1483 1498 dprintk("%s: return %d\n", __func__, ntohl(status));
... ... @@ -2598,7 +2613,13 @@
2598 2613 clientid_val = t;
2599 2614 break;
2600 2615 }
2601   - list_move(&clp->cl_lru, &reaplist);
  2616 + if (atomic_read(&clp->cl_refcount)) {
  2617 + dprintk("NFSD: client in use (clientid %08x)\n",
  2618 + clp->cl_clientid.cl_id);
  2619 + continue;
  2620 + }
  2621 + unhash_client_locked(clp);
  2622 + list_add(&clp->cl_lru, &reaplist);
2602 2623 }
2603 2624 spin_unlock(&client_lock);
2604 2625 list_for_each_safe(pos, next, &reaplist) {
... ... @@ -3313,7 +3313,8 @@
3313 3313 dprintk("%s: SET SLOT STATE TO AVAILABLE\n", __func__);
3314 3314 cs->slot->sl_inuse = false;
3315 3315 }
3316   - nfsd4_put_session(cs->session);
  3316 + /* Renew the clientid on success and on replay */
  3317 + release_session_client(cs->session);
3317 3318 }
3318 3319 return 1;
3319 3320 }
... ... @@ -420,6 +420,7 @@
420 420 extern void nfsd4_recdir_purge_old(void);
421 421 extern int nfsd4_create_clid_dir(struct nfs4_client *clp);
422 422 extern void nfsd4_remove_clid_dir(struct nfs4_client *clp);
  423 +extern void release_session_client(struct nfsd4_session *);
423 424  
424 425 static inline void
425 426 nfs4_put_stateowner(struct nfs4_stateowner *so)