diff options
Diffstat (limited to 'fs/nfsd/nfs4state.c')
-rw-r--r-- | fs/nfsd/nfs4state.c | 41 |
1 files changed, 26 insertions, 15 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index aecafb2e4056..3f572cb3f896 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
@@ -250,7 +250,7 @@ unhash_delegation(struct nfs4_delegation *dp) | |||
250 | * SETCLIENTID state | 250 | * SETCLIENTID state |
251 | */ | 251 | */ |
252 | 252 | ||
253 | /* client_lock protects the session hash table */ | 253 | /* client_lock protects the client lru list and session hash table */ |
254 | static DEFINE_SPINLOCK(client_lock); | 254 | static DEFINE_SPINLOCK(client_lock); |
255 | 255 | ||
256 | /* Hash tables for nfs4_clientid state */ | 256 | /* Hash tables for nfs4_clientid state */ |
@@ -628,8 +628,9 @@ free_session(struct kref *kref) | |||
628 | kfree(ses); | 628 | kfree(ses); |
629 | } | 629 | } |
630 | 630 | ||
631 | /* must be called under the client_lock */ | ||
631 | static inline void | 632 | static inline void |
632 | renew_client(struct nfs4_client *clp) | 633 | renew_client_locked(struct nfs4_client *clp) |
633 | { | 634 | { |
634 | /* | 635 | /* |
635 | * Move client to the end to the LRU list. | 636 | * Move client to the end to the LRU list. |
@@ -641,6 +642,14 @@ renew_client(struct nfs4_client *clp) | |||
641 | clp->cl_time = get_seconds(); | 642 | clp->cl_time = get_seconds(); |
642 | } | 643 | } |
643 | 644 | ||
645 | static inline void | ||
646 | renew_client(struct nfs4_client *clp) | ||
647 | { | ||
648 | spin_lock(&client_lock); | ||
649 | renew_client_locked(clp); | ||
650 | spin_unlock(&client_lock); | ||
651 | } | ||
652 | |||
644 | /* SETCLIENTID and SETCLIENTID_CONFIRM Helper functions */ | 653 | /* SETCLIENTID and SETCLIENTID_CONFIRM Helper functions */ |
645 | static int | 654 | static int |
646 | STALE_CLIENTID(clientid_t *clid) | 655 | STALE_CLIENTID(clientid_t *clid) |
@@ -706,14 +715,14 @@ expire_client(struct nfs4_client *clp) | |||
706 | list_del_init(&dp->dl_recall_lru); | 715 | list_del_init(&dp->dl_recall_lru); |
707 | unhash_delegation(dp); | 716 | unhash_delegation(dp); |
708 | } | 717 | } |
709 | list_del(&clp->cl_idhash); | ||
710 | list_del(&clp->cl_strhash); | ||
711 | list_del(&clp->cl_lru); | ||
712 | while (!list_empty(&clp->cl_openowners)) { | 718 | while (!list_empty(&clp->cl_openowners)) { |
713 | sop = list_entry(clp->cl_openowners.next, struct nfs4_stateowner, so_perclient); | 719 | sop = list_entry(clp->cl_openowners.next, struct nfs4_stateowner, so_perclient); |
714 | release_openowner(sop); | 720 | release_openowner(sop); |
715 | } | 721 | } |
722 | list_del(&clp->cl_idhash); | ||
723 | list_del(&clp->cl_strhash); | ||
716 | spin_lock(&client_lock); | 724 | spin_lock(&client_lock); |
725 | list_del(&clp->cl_lru); | ||
717 | while (!list_empty(&clp->cl_sessions)) { | 726 | while (!list_empty(&clp->cl_sessions)) { |
718 | struct nfsd4_session *ses; | 727 | struct nfsd4_session *ses; |
719 | ses = list_entry(clp->cl_sessions.next, struct nfsd4_session, | 728 | ses = list_entry(clp->cl_sessions.next, struct nfsd4_session, |
@@ -848,8 +857,7 @@ add_to_unconfirmed(struct nfs4_client *clp, unsigned int strhashval) | |||
848 | list_add(&clp->cl_strhash, &unconf_str_hashtbl[strhashval]); | 857 | list_add(&clp->cl_strhash, &unconf_str_hashtbl[strhashval]); |
849 | idhashval = clientid_hashval(clp->cl_clientid.cl_id); | 858 | idhashval = clientid_hashval(clp->cl_clientid.cl_id); |
850 | list_add(&clp->cl_idhash, &unconf_id_hashtbl[idhashval]); | 859 | list_add(&clp->cl_idhash, &unconf_id_hashtbl[idhashval]); |
851 | list_add_tail(&clp->cl_lru, &client_lru); | 860 | renew_client(clp); |
852 | clp->cl_time = get_seconds(); | ||
853 | } | 861 | } |
854 | 862 | ||
855 | static void | 863 | static void |
@@ -1447,15 +1455,12 @@ nfsd4_sequence(struct svc_rqst *rqstp, | |||
1447 | 1455 | ||
1448 | out: | 1456 | out: |
1449 | /* Hold a session reference until done processing the compound. */ | 1457 | /* Hold a session reference until done processing the compound. */ |
1450 | if (cstate->session) | ||
1451 | nfsd4_get_session(cstate->session); | ||
1452 | spin_unlock(&client_lock); | ||
1453 | /* Renew the clientid on success and on replay */ | ||
1454 | if (cstate->session) { | 1458 | if (cstate->session) { |
1455 | nfs4_lock_state(); | 1459 | nfsd4_get_session(cstate->session); |
1456 | renew_client(session->se_client); | 1460 | /* Renew the clientid on success and on replay */ |
1457 | nfs4_unlock_state(); | 1461 | renew_client_locked(session->se_client); |
1458 | } | 1462 | } |
1463 | spin_unlock(&client_lock); | ||
1459 | dprintk("%s: return %d\n", __func__, ntohl(status)); | 1464 | dprintk("%s: return %d\n", __func__, ntohl(status)); |
1460 | return status; | 1465 | return status; |
1461 | } | 1466 | } |
@@ -2564,6 +2569,8 @@ nfs4_laundromat(void) | |||
2564 | dprintk("NFSD: laundromat service - starting\n"); | 2569 | dprintk("NFSD: laundromat service - starting\n"); |
2565 | if (locks_in_grace()) | 2570 | if (locks_in_grace()) |
2566 | nfsd4_end_grace(); | 2571 | nfsd4_end_grace(); |
2572 | INIT_LIST_HEAD(&reaplist); | ||
2573 | spin_lock(&client_lock); | ||
2567 | list_for_each_safe(pos, next, &client_lru) { | 2574 | list_for_each_safe(pos, next, &client_lru) { |
2568 | clp = list_entry(pos, struct nfs4_client, cl_lru); | 2575 | clp = list_entry(pos, struct nfs4_client, cl_lru); |
2569 | if (time_after((unsigned long)clp->cl_time, (unsigned long)cutoff)) { | 2576 | if (time_after((unsigned long)clp->cl_time, (unsigned long)cutoff)) { |
@@ -2572,12 +2579,16 @@ nfs4_laundromat(void) | |||
2572 | clientid_val = t; | 2579 | clientid_val = t; |
2573 | break; | 2580 | break; |
2574 | } | 2581 | } |
2582 | list_move(&clp->cl_lru, &reaplist); | ||
2583 | } | ||
2584 | spin_unlock(&client_lock); | ||
2585 | list_for_each_safe(pos, next, &reaplist) { | ||
2586 | clp = list_entry(pos, struct nfs4_client, cl_lru); | ||
2575 | dprintk("NFSD: purging unused client (clientid %08x)\n", | 2587 | dprintk("NFSD: purging unused client (clientid %08x)\n", |
2576 | clp->cl_clientid.cl_id); | 2588 | clp->cl_clientid.cl_id); |
2577 | nfsd4_remove_clid_dir(clp); | 2589 | nfsd4_remove_clid_dir(clp); |
2578 | expire_client(clp); | 2590 | expire_client(clp); |
2579 | } | 2591 | } |
2580 | INIT_LIST_HEAD(&reaplist); | ||
2581 | spin_lock(&recall_lock); | 2592 | spin_lock(&recall_lock); |
2582 | list_for_each_safe(pos, next, &del_recall_lru) { | 2593 | list_for_each_safe(pos, next, &del_recall_lru) { |
2583 | dp = list_entry (pos, struct nfs4_delegation, dl_recall_lru); | 2594 | dp = list_entry (pos, struct nfs4_delegation, dl_recall_lru); |