diff options
| author | J. Bruce Fields <bfields@redhat.com> | 2010-10-12 19:55:25 -0400 |
|---|---|---|
| committer | J. Bruce Fields <bfields@redhat.com> | 2010-10-21 10:11:56 -0400 |
| commit | 792c95dd519c54d6b0fd6401b3da7ea67b0d6b72 (patch) | |
| tree | 1bd872c92be9fcc8790e5c68d8acb2ababc0b241 | |
| parent | 5a3c9d71343cf27b7afef24ed312368d48dada09 (diff) | |
nfsd4: delay session removal till free_client
Have unhash_client_locked() remove client and associated sessions from
global hashes, but delay further dismantling till free_client().
(After unhash_client_locked(), the only remaining references outside the
destroying thread are from any connections which have xpt_user callbacks
registered.)
This will simplify locking on session destruction.
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
| -rw-r--r-- | fs/nfsd/nfs4state.c | 21 |
1 files changed, 13 insertions, 8 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 2327a8c00862..0f2643dac22a 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
| @@ -883,6 +883,13 @@ static struct nfs4_client *alloc_client(struct xdr_netobj name) | |||
| 883 | static inline void | 883 | static inline void |
| 884 | free_client(struct nfs4_client *clp) | 884 | free_client(struct nfs4_client *clp) |
| 885 | { | 885 | { |
| 886 | while (!list_empty(&clp->cl_sessions)) { | ||
| 887 | struct nfsd4_session *ses; | ||
| 888 | ses = list_entry(clp->cl_sessions.next, struct nfsd4_session, | ||
| 889 | se_perclnt); | ||
| 890 | list_del(&ses->se_perclnt); | ||
| 891 | nfsd4_put_session(ses); | ||
| 892 | } | ||
| 886 | if (clp->cl_cred.cr_group_info) | 893 | if (clp->cl_cred.cr_group_info) |
| 887 | put_group_info(clp->cl_cred.cr_group_info); | 894 | put_group_info(clp->cl_cred.cr_group_info); |
| 888 | kfree(clp->cl_principal); | 895 | kfree(clp->cl_principal); |
| @@ -909,15 +916,12 @@ release_session_client(struct nfsd4_session *session) | |||
| 909 | static inline void | 916 | static inline void |
| 910 | unhash_client_locked(struct nfs4_client *clp) | 917 | unhash_client_locked(struct nfs4_client *clp) |
| 911 | { | 918 | { |
| 919 | struct nfsd4_session *ses; | ||
| 920 | |||
| 912 | mark_client_expired(clp); | 921 | mark_client_expired(clp); |
| 913 | list_del(&clp->cl_lru); | 922 | list_del(&clp->cl_lru); |
| 914 | while (!list_empty(&clp->cl_sessions)) { | 923 | list_for_each_entry(ses, &clp->cl_sessions, se_perclnt) |
| 915 | struct nfsd4_session *ses; | 924 | list_del_init(&ses->se_hash); |
| 916 | ses = list_entry(clp->cl_sessions.next, struct nfsd4_session, | ||
| 917 | se_perclnt); | ||
| 918 | unhash_session(ses); | ||
| 919 | nfsd4_put_session(ses); | ||
| 920 | } | ||
| 921 | } | 925 | } |
| 922 | 926 | ||
| 923 | static void | 927 | static void |
| @@ -1031,6 +1035,8 @@ static struct nfs4_client *create_client(struct xdr_netobj name, char *recdir, | |||
| 1031 | if (clp == NULL) | 1035 | if (clp == NULL) |
| 1032 | return NULL; | 1036 | return NULL; |
| 1033 | 1037 | ||
| 1038 | INIT_LIST_HEAD(&clp->cl_sessions); | ||
| 1039 | |||
| 1034 | princ = svc_gss_principal(rqstp); | 1040 | princ = svc_gss_principal(rqstp); |
| 1035 | if (princ) { | 1041 | if (princ) { |
| 1036 | clp->cl_principal = kstrdup(princ, GFP_KERNEL); | 1042 | clp->cl_principal = kstrdup(princ, GFP_KERNEL); |
| @@ -1047,7 +1053,6 @@ static struct nfs4_client *create_client(struct xdr_netobj name, char *recdir, | |||
| 1047 | INIT_LIST_HEAD(&clp->cl_strhash); | 1053 | INIT_LIST_HEAD(&clp->cl_strhash); |
| 1048 | INIT_LIST_HEAD(&clp->cl_openowners); | 1054 | INIT_LIST_HEAD(&clp->cl_openowners); |
| 1049 | INIT_LIST_HEAD(&clp->cl_delegations); | 1055 | INIT_LIST_HEAD(&clp->cl_delegations); |
| 1050 | INIT_LIST_HEAD(&clp->cl_sessions); | ||
| 1051 | INIT_LIST_HEAD(&clp->cl_lru); | 1056 | INIT_LIST_HEAD(&clp->cl_lru); |
| 1052 | spin_lock_init(&clp->cl_lock); | 1057 | spin_lock_init(&clp->cl_lock); |
| 1053 | INIT_WORK(&clp->cl_cb_null.cb_work, nfsd4_do_callback_rpc); | 1058 | INIT_WORK(&clp->cl_cb_null.cb_work, nfsd4_do_callback_rpc); |
