diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-01-14 15:26:41 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-01-14 15:26:41 -0500 |
commit | 0b48d42235caf627121f440b57d376f48a9af8b6 (patch) | |
tree | 400967c5fcb1cd08bbc0e1739e229f9717590f19 /net/sunrpc/svc_xprt.c | |
parent | 8e63dd6e1c589ba99a18df9cbaa41c3178607641 (diff) | |
parent | 7a6ef8c72314f254c107c6a9ed7cb201961ee05a (diff) |
Merge branch 'for-3.3' of git://linux-nfs.org/~bfields/linux
* 'for-3.3' of git://linux-nfs.org/~bfields/linux: (31 commits)
nfsd4: nfsd4_create_clid_dir return value is unused
NFSD: Change name of extended attribute containing junction
svcrpc: don't revert to SVC_POOL_DEFAULT on nfsd shutdown
svcrpc: fix double-free on shutdown of nfsd after changing pool mode
nfsd4: be forgiving in the absence of the recovery directory
nfsd4: fix spurious 4.1 post-reboot failures
NFSD: forget_delegations should use list_for_each_entry_safe
NFSD: Only reinitilize the recall_lru list under the recall lock
nfsd4: initialize special stateid's at compile time
NFSd: use network-namespace-aware cache registering routines
SUNRPC: create svc_xprt in proper network namespace
svcrpc: update outdated BKL comment
nfsd41: allow non-reclaim open-by-fh's in 4.1
svcrpc: avoid memory-corruption on pool shutdown
svcrpc: destroy server sockets all at once
svcrpc: make svc_delete_xprt static
nfsd: Fix oops when parsing a 0 length export
nfsd4: Use kmemdup rather than duplicating its implementation
nfsd4: add a separate (lockowner, inode) lookup
nfsd4: fix CONFIG_NFSD_FAULT_INJECTION compile error
...
Diffstat (limited to 'net/sunrpc/svc_xprt.c')
-rw-r--r-- | net/sunrpc/svc_xprt.c | 62 |
1 files changed, 41 insertions, 21 deletions
diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c index 38649cfa4e81..74cb0d8e9ca1 100644 --- a/net/sunrpc/svc_xprt.c +++ b/net/sunrpc/svc_xprt.c | |||
@@ -22,6 +22,7 @@ static struct svc_deferred_req *svc_deferred_dequeue(struct svc_xprt *xprt); | |||
22 | static int svc_deferred_recv(struct svc_rqst *rqstp); | 22 | static int svc_deferred_recv(struct svc_rqst *rqstp); |
23 | static struct cache_deferred_req *svc_defer(struct cache_req *req); | 23 | static struct cache_deferred_req *svc_defer(struct cache_req *req); |
24 | static void svc_age_temp_xprts(unsigned long closure); | 24 | static void svc_age_temp_xprts(unsigned long closure); |
25 | static void svc_delete_xprt(struct svc_xprt *xprt); | ||
25 | 26 | ||
26 | /* apparently the "standard" is that clients close | 27 | /* apparently the "standard" is that clients close |
27 | * idle connections after 5 minutes, servers after | 28 | * idle connections after 5 minutes, servers after |
@@ -147,8 +148,8 @@ EXPORT_SYMBOL_GPL(svc_xprt_put); | |||
147 | * Called by transport drivers to initialize the transport independent | 148 | * Called by transport drivers to initialize the transport independent |
148 | * portion of the transport instance. | 149 | * portion of the transport instance. |
149 | */ | 150 | */ |
150 | void svc_xprt_init(struct svc_xprt_class *xcl, struct svc_xprt *xprt, | 151 | void svc_xprt_init(struct net *net, struct svc_xprt_class *xcl, |
151 | struct svc_serv *serv) | 152 | struct svc_xprt *xprt, struct svc_serv *serv) |
152 | { | 153 | { |
153 | memset(xprt, 0, sizeof(*xprt)); | 154 | memset(xprt, 0, sizeof(*xprt)); |
154 | xprt->xpt_class = xcl; | 155 | xprt->xpt_class = xcl; |
@@ -163,7 +164,7 @@ void svc_xprt_init(struct svc_xprt_class *xcl, struct svc_xprt *xprt, | |||
163 | spin_lock_init(&xprt->xpt_lock); | 164 | spin_lock_init(&xprt->xpt_lock); |
164 | set_bit(XPT_BUSY, &xprt->xpt_flags); | 165 | set_bit(XPT_BUSY, &xprt->xpt_flags); |
165 | rpc_init_wait_queue(&xprt->xpt_bc_pending, "xpt_bc_pending"); | 166 | rpc_init_wait_queue(&xprt->xpt_bc_pending, "xpt_bc_pending"); |
166 | xprt->xpt_net = get_net(&init_net); | 167 | xprt->xpt_net = get_net(net); |
167 | } | 168 | } |
168 | EXPORT_SYMBOL_GPL(svc_xprt_init); | 169 | EXPORT_SYMBOL_GPL(svc_xprt_init); |
169 | 170 | ||
@@ -878,7 +879,7 @@ static void call_xpt_users(struct svc_xprt *xprt) | |||
878 | /* | 879 | /* |
879 | * Remove a dead transport | 880 | * Remove a dead transport |
880 | */ | 881 | */ |
881 | void svc_delete_xprt(struct svc_xprt *xprt) | 882 | static void svc_delete_xprt(struct svc_xprt *xprt) |
882 | { | 883 | { |
883 | struct svc_serv *serv = xprt->xpt_server; | 884 | struct svc_serv *serv = xprt->xpt_server; |
884 | struct svc_deferred_req *dr; | 885 | struct svc_deferred_req *dr; |
@@ -893,14 +894,7 @@ void svc_delete_xprt(struct svc_xprt *xprt) | |||
893 | spin_lock_bh(&serv->sv_lock); | 894 | spin_lock_bh(&serv->sv_lock); |
894 | if (!test_and_set_bit(XPT_DETACHED, &xprt->xpt_flags)) | 895 | if (!test_and_set_bit(XPT_DETACHED, &xprt->xpt_flags)) |
895 | list_del_init(&xprt->xpt_list); | 896 | list_del_init(&xprt->xpt_list); |
896 | /* | 897 | BUG_ON(!list_empty(&xprt->xpt_ready)); |
897 | * The only time we're called while xpt_ready is still on a list | ||
898 | * is while the list itself is about to be destroyed (in | ||
899 | * svc_destroy). BUT svc_xprt_enqueue could still be attempting | ||
900 | * to add new entries to the sp_sockets list, so we can't leave | ||
901 | * a freed xprt on it. | ||
902 | */ | ||
903 | list_del_init(&xprt->xpt_ready); | ||
904 | if (test_bit(XPT_TEMP, &xprt->xpt_flags)) | 898 | if (test_bit(XPT_TEMP, &xprt->xpt_flags)) |
905 | serv->sv_tmpcnt--; | 899 | serv->sv_tmpcnt--; |
906 | spin_unlock_bh(&serv->sv_lock); | 900 | spin_unlock_bh(&serv->sv_lock); |
@@ -928,22 +922,48 @@ void svc_close_xprt(struct svc_xprt *xprt) | |||
928 | } | 922 | } |
929 | EXPORT_SYMBOL_GPL(svc_close_xprt); | 923 | EXPORT_SYMBOL_GPL(svc_close_xprt); |
930 | 924 | ||
931 | void svc_close_all(struct list_head *xprt_list) | 925 | static void svc_close_list(struct list_head *xprt_list) |
926 | { | ||
927 | struct svc_xprt *xprt; | ||
928 | |||
929 | list_for_each_entry(xprt, xprt_list, xpt_list) { | ||
930 | set_bit(XPT_CLOSE, &xprt->xpt_flags); | ||
931 | set_bit(XPT_BUSY, &xprt->xpt_flags); | ||
932 | } | ||
933 | } | ||
934 | |||
935 | void svc_close_all(struct svc_serv *serv) | ||
932 | { | 936 | { |
937 | struct svc_pool *pool; | ||
933 | struct svc_xprt *xprt; | 938 | struct svc_xprt *xprt; |
934 | struct svc_xprt *tmp; | 939 | struct svc_xprt *tmp; |
940 | int i; | ||
941 | |||
942 | svc_close_list(&serv->sv_tempsocks); | ||
943 | svc_close_list(&serv->sv_permsocks); | ||
935 | 944 | ||
945 | for (i = 0; i < serv->sv_nrpools; i++) { | ||
946 | pool = &serv->sv_pools[i]; | ||
947 | |||
948 | spin_lock_bh(&pool->sp_lock); | ||
949 | while (!list_empty(&pool->sp_sockets)) { | ||
950 | xprt = list_first_entry(&pool->sp_sockets, struct svc_xprt, xpt_ready); | ||
951 | list_del_init(&xprt->xpt_ready); | ||
952 | } | ||
953 | spin_unlock_bh(&pool->sp_lock); | ||
954 | } | ||
936 | /* | 955 | /* |
937 | * The server is shutting down, and no more threads are running. | 956 | * At this point the sp_sockets lists will stay empty, since |
938 | * svc_xprt_enqueue() might still be running, but at worst it | 957 | * svc_enqueue will not add new entries without taking the |
939 | * will re-add the xprt to sp_sockets, which will soon get | 958 | * sp_lock and checking XPT_BUSY. |
940 | * freed. So we don't bother with any more locking, and don't | ||
941 | * leave the close to the (nonexistent) server threads: | ||
942 | */ | 959 | */ |
943 | list_for_each_entry_safe(xprt, tmp, xprt_list, xpt_list) { | 960 | list_for_each_entry_safe(xprt, tmp, &serv->sv_tempsocks, xpt_list) |
944 | set_bit(XPT_CLOSE, &xprt->xpt_flags); | ||
945 | svc_delete_xprt(xprt); | 961 | svc_delete_xprt(xprt); |
946 | } | 962 | list_for_each_entry_safe(xprt, tmp, &serv->sv_permsocks, xpt_list) |
963 | svc_delete_xprt(xprt); | ||
964 | |||
965 | BUG_ON(!list_empty(&serv->sv_permsocks)); | ||
966 | BUG_ON(!list_empty(&serv->sv_tempsocks)); | ||
947 | } | 967 | } |
948 | 968 | ||
949 | /* | 969 | /* |