diff options
Diffstat (limited to 'net/sunrpc/svc_xprt.c')
-rw-r--r-- | net/sunrpc/svc_xprt.c | 66 |
1 files changed, 28 insertions, 38 deletions
diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c index df124f78ee48..061b2e0f9118 100644 --- a/net/sunrpc/svc_xprt.c +++ b/net/sunrpc/svc_xprt.c | |||
@@ -9,6 +9,7 @@ | |||
9 | #include <linux/errno.h> | 9 | #include <linux/errno.h> |
10 | #include <linux/freezer.h> | 10 | #include <linux/freezer.h> |
11 | #include <linux/kthread.h> | 11 | #include <linux/kthread.h> |
12 | #include <linux/slab.h> | ||
12 | #include <net/sock.h> | 13 | #include <net/sock.h> |
13 | #include <linux/sunrpc/stats.h> | 14 | #include <linux/sunrpc/stats.h> |
14 | #include <linux/sunrpc/svc_xprt.h> | 15 | #include <linux/sunrpc/svc_xprt.h> |
@@ -16,8 +17,6 @@ | |||
16 | 17 | ||
17 | #define RPCDBG_FACILITY RPCDBG_SVCXPRT | 18 | #define RPCDBG_FACILITY RPCDBG_SVCXPRT |
18 | 19 | ||
19 | #define SVC_MAX_WAKING 5 | ||
20 | |||
21 | static struct svc_deferred_req *svc_deferred_dequeue(struct svc_xprt *xprt); | 20 | static struct svc_deferred_req *svc_deferred_dequeue(struct svc_xprt *xprt); |
22 | static int svc_deferred_recv(struct svc_rqst *rqstp); | 21 | static int svc_deferred_recv(struct svc_rqst *rqstp); |
23 | static struct cache_deferred_req *svc_defer(struct cache_req *req); | 22 | static struct cache_deferred_req *svc_defer(struct cache_req *req); |
@@ -129,8 +128,8 @@ static void svc_xprt_free(struct kref *kref) | |||
129 | struct svc_xprt *xprt = | 128 | struct svc_xprt *xprt = |
130 | container_of(kref, struct svc_xprt, xpt_ref); | 129 | container_of(kref, struct svc_xprt, xpt_ref); |
131 | struct module *owner = xprt->xpt_class->xcl_owner; | 130 | struct module *owner = xprt->xpt_class->xcl_owner; |
132 | if (test_bit(XPT_CACHE_AUTH, &xprt->xpt_flags) | 131 | if (test_bit(XPT_CACHE_AUTH, &xprt->xpt_flags) && |
133 | && xprt->xpt_auth_cache != NULL) | 132 | xprt->xpt_auth_cache != NULL) |
134 | svcauth_unix_info_release(xprt->xpt_auth_cache); | 133 | svcauth_unix_info_release(xprt->xpt_auth_cache); |
135 | xprt->xpt_ops->xpo_free(xprt); | 134 | xprt->xpt_ops->xpo_free(xprt); |
136 | module_put(owner); | 135 | module_put(owner); |
@@ -175,11 +174,13 @@ static struct svc_xprt *__svc_xpo_create(struct svc_xprt_class *xcl, | |||
175 | .sin_addr.s_addr = htonl(INADDR_ANY), | 174 | .sin_addr.s_addr = htonl(INADDR_ANY), |
176 | .sin_port = htons(port), | 175 | .sin_port = htons(port), |
177 | }; | 176 | }; |
177 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
178 | struct sockaddr_in6 sin6 = { | 178 | struct sockaddr_in6 sin6 = { |
179 | .sin6_family = AF_INET6, | 179 | .sin6_family = AF_INET6, |
180 | .sin6_addr = IN6ADDR_ANY_INIT, | 180 | .sin6_addr = IN6ADDR_ANY_INIT, |
181 | .sin6_port = htons(port), | 181 | .sin6_port = htons(port), |
182 | }; | 182 | }; |
183 | #endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */ | ||
183 | struct sockaddr *sap; | 184 | struct sockaddr *sap; |
184 | size_t len; | 185 | size_t len; |
185 | 186 | ||
@@ -188,10 +189,12 @@ static struct svc_xprt *__svc_xpo_create(struct svc_xprt_class *xcl, | |||
188 | sap = (struct sockaddr *)&sin; | 189 | sap = (struct sockaddr *)&sin; |
189 | len = sizeof(sin); | 190 | len = sizeof(sin); |
190 | break; | 191 | break; |
192 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
191 | case PF_INET6: | 193 | case PF_INET6: |
192 | sap = (struct sockaddr *)&sin6; | 194 | sap = (struct sockaddr *)&sin6; |
193 | len = sizeof(sin6); | 195 | len = sizeof(sin6); |
194 | break; | 196 | break; |
197 | #endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */ | ||
195 | default: | 198 | default: |
196 | return ERR_PTR(-EAFNOSUPPORT); | 199 | return ERR_PTR(-EAFNOSUPPORT); |
197 | } | 200 | } |
@@ -233,7 +236,10 @@ int svc_create_xprt(struct svc_serv *serv, const char *xprt_name, | |||
233 | err: | 236 | err: |
234 | spin_unlock(&svc_xprt_class_lock); | 237 | spin_unlock(&svc_xprt_class_lock); |
235 | dprintk("svc: transport %s not found\n", xprt_name); | 238 | dprintk("svc: transport %s not found\n", xprt_name); |
236 | return -ENOENT; | 239 | |
240 | /* This errno is exposed to user space. Provide a reasonable | ||
241 | * perror msg for a bad transport. */ | ||
242 | return -EPROTONOSUPPORT; | ||
237 | } | 243 | } |
238 | EXPORT_SYMBOL_GPL(svc_create_xprt); | 244 | EXPORT_SYMBOL_GPL(svc_create_xprt); |
239 | 245 | ||
@@ -306,7 +312,6 @@ void svc_xprt_enqueue(struct svc_xprt *xprt) | |||
306 | struct svc_pool *pool; | 312 | struct svc_pool *pool; |
307 | struct svc_rqst *rqstp; | 313 | struct svc_rqst *rqstp; |
308 | int cpu; | 314 | int cpu; |
309 | int thread_avail; | ||
310 | 315 | ||
311 | if (!(xprt->xpt_flags & | 316 | if (!(xprt->xpt_flags & |
312 | ((1<<XPT_CONN)|(1<<XPT_DATA)|(1<<XPT_CLOSE)|(1<<XPT_DEFERRED)))) | 317 | ((1<<XPT_CONN)|(1<<XPT_DATA)|(1<<XPT_CLOSE)|(1<<XPT_DEFERRED)))) |
@@ -318,6 +323,12 @@ void svc_xprt_enqueue(struct svc_xprt *xprt) | |||
318 | 323 | ||
319 | spin_lock_bh(&pool->sp_lock); | 324 | spin_lock_bh(&pool->sp_lock); |
320 | 325 | ||
326 | if (!list_empty(&pool->sp_threads) && | ||
327 | !list_empty(&pool->sp_sockets)) | ||
328 | printk(KERN_ERR | ||
329 | "svc_xprt_enqueue: " | ||
330 | "threads and transports both waiting??\n"); | ||
331 | |||
321 | if (test_bit(XPT_DEAD, &xprt->xpt_flags)) { | 332 | if (test_bit(XPT_DEAD, &xprt->xpt_flags)) { |
322 | /* Don't enqueue dead transports */ | 333 | /* Don't enqueue dead transports */ |
323 | dprintk("svc: transport %p is dead, not enqueued\n", xprt); | 334 | dprintk("svc: transport %p is dead, not enqueued\n", xprt); |
@@ -358,15 +369,7 @@ void svc_xprt_enqueue(struct svc_xprt *xprt) | |||
358 | } | 369 | } |
359 | 370 | ||
360 | process: | 371 | process: |
361 | /* Work out whether threads are available */ | 372 | if (!list_empty(&pool->sp_threads)) { |
362 | thread_avail = !list_empty(&pool->sp_threads); /* threads are asleep */ | ||
363 | if (pool->sp_nwaking >= SVC_MAX_WAKING) { | ||
364 | /* too many threads are runnable and trying to wake up */ | ||
365 | thread_avail = 0; | ||
366 | pool->sp_stats.overloads_avoided++; | ||
367 | } | ||
368 | |||
369 | if (thread_avail) { | ||
370 | rqstp = list_entry(pool->sp_threads.next, | 373 | rqstp = list_entry(pool->sp_threads.next, |
371 | struct svc_rqst, | 374 | struct svc_rqst, |
372 | rq_list); | 375 | rq_list); |
@@ -381,8 +384,6 @@ void svc_xprt_enqueue(struct svc_xprt *xprt) | |||
381 | svc_xprt_get(xprt); | 384 | svc_xprt_get(xprt); |
382 | rqstp->rq_reserved = serv->sv_max_mesg; | 385 | rqstp->rq_reserved = serv->sv_max_mesg; |
383 | atomic_add(rqstp->rq_reserved, &xprt->xpt_reserved); | 386 | atomic_add(rqstp->rq_reserved, &xprt->xpt_reserved); |
384 | rqstp->rq_waking = 1; | ||
385 | pool->sp_nwaking++; | ||
386 | pool->sp_stats.threads_woken++; | 387 | pool->sp_stats.threads_woken++; |
387 | BUG_ON(xprt->xpt_pool != pool); | 388 | BUG_ON(xprt->xpt_pool != pool); |
388 | wake_up(&rqstp->rq_wait); | 389 | wake_up(&rqstp->rq_wait); |
@@ -651,11 +652,6 @@ int svc_recv(struct svc_rqst *rqstp, long timeout) | |||
651 | return -EINTR; | 652 | return -EINTR; |
652 | 653 | ||
653 | spin_lock_bh(&pool->sp_lock); | 654 | spin_lock_bh(&pool->sp_lock); |
654 | if (rqstp->rq_waking) { | ||
655 | rqstp->rq_waking = 0; | ||
656 | pool->sp_nwaking--; | ||
657 | BUG_ON(pool->sp_nwaking < 0); | ||
658 | } | ||
659 | xprt = svc_xprt_dequeue(pool); | 655 | xprt = svc_xprt_dequeue(pool); |
660 | if (xprt) { | 656 | if (xprt) { |
661 | rqstp->rq_xprt = xprt; | 657 | rqstp->rq_xprt = xprt; |
@@ -711,7 +707,10 @@ int svc_recv(struct svc_rqst *rqstp, long timeout) | |||
711 | spin_unlock_bh(&pool->sp_lock); | 707 | spin_unlock_bh(&pool->sp_lock); |
712 | 708 | ||
713 | len = 0; | 709 | len = 0; |
714 | if (test_bit(XPT_LISTENER, &xprt->xpt_flags)) { | 710 | if (test_bit(XPT_CLOSE, &xprt->xpt_flags)) { |
711 | dprintk("svc_recv: found XPT_CLOSE\n"); | ||
712 | svc_delete_xprt(xprt); | ||
713 | } else if (test_bit(XPT_LISTENER, &xprt->xpt_flags)) { | ||
715 | struct svc_xprt *newxpt; | 714 | struct svc_xprt *newxpt; |
716 | newxpt = xprt->xpt_ops->xpo_accept(xprt); | 715 | newxpt = xprt->xpt_ops->xpo_accept(xprt); |
717 | if (newxpt) { | 716 | if (newxpt) { |
@@ -737,7 +736,7 @@ int svc_recv(struct svc_rqst *rqstp, long timeout) | |||
737 | svc_xprt_received(newxpt); | 736 | svc_xprt_received(newxpt); |
738 | } | 737 | } |
739 | svc_xprt_received(xprt); | 738 | svc_xprt_received(xprt); |
740 | } else if (!test_bit(XPT_CLOSE, &xprt->xpt_flags)) { | 739 | } else { |
741 | dprintk("svc: server %p, pool %u, transport %p, inuse=%d\n", | 740 | dprintk("svc: server %p, pool %u, transport %p, inuse=%d\n", |
742 | rqstp, pool->sp_id, xprt, | 741 | rqstp, pool->sp_id, xprt, |
743 | atomic_read(&xprt->xpt_ref.refcount)); | 742 | atomic_read(&xprt->xpt_ref.refcount)); |
@@ -750,11 +749,6 @@ int svc_recv(struct svc_rqst *rqstp, long timeout) | |||
750 | dprintk("svc: got len=%d\n", len); | 749 | dprintk("svc: got len=%d\n", len); |
751 | } | 750 | } |
752 | 751 | ||
753 | if (test_bit(XPT_CLOSE, &xprt->xpt_flags)) { | ||
754 | dprintk("svc_recv: found XPT_CLOSE\n"); | ||
755 | svc_delete_xprt(xprt); | ||
756 | } | ||
757 | |||
758 | /* No data, incomplete (TCP) read, or accept() */ | 752 | /* No data, incomplete (TCP) read, or accept() */ |
759 | if (len == 0 || len == -EAGAIN) { | 753 | if (len == 0 || len == -EAGAIN) { |
760 | rqstp->rq_res.len = 0; | 754 | rqstp->rq_res.len = 0; |
@@ -846,8 +840,8 @@ static void svc_age_temp_xprts(unsigned long closure) | |||
846 | * through, close it. */ | 840 | * through, close it. */ |
847 | if (!test_and_set_bit(XPT_OLD, &xprt->xpt_flags)) | 841 | if (!test_and_set_bit(XPT_OLD, &xprt->xpt_flags)) |
848 | continue; | 842 | continue; |
849 | if (atomic_read(&xprt->xpt_ref.refcount) > 1 | 843 | if (atomic_read(&xprt->xpt_ref.refcount) > 1 || |
850 | || test_bit(XPT_BUSY, &xprt->xpt_flags)) | 844 | test_bit(XPT_BUSY, &xprt->xpt_flags)) |
851 | continue; | 845 | continue; |
852 | svc_xprt_get(xprt); | 846 | svc_xprt_get(xprt); |
853 | list_move(le, &to_be_aged); | 847 | list_move(le, &to_be_aged); |
@@ -900,11 +894,8 @@ void svc_delete_xprt(struct svc_xprt *xprt) | |||
900 | if (test_bit(XPT_TEMP, &xprt->xpt_flags)) | 894 | if (test_bit(XPT_TEMP, &xprt->xpt_flags)) |
901 | serv->sv_tmpcnt--; | 895 | serv->sv_tmpcnt--; |
902 | 896 | ||
903 | for (dr = svc_deferred_dequeue(xprt); dr; | 897 | while ((dr = svc_deferred_dequeue(xprt)) != NULL) |
904 | dr = svc_deferred_dequeue(xprt)) { | ||
905 | svc_xprt_put(xprt); | ||
906 | kfree(dr); | 898 | kfree(dr); |
907 | } | ||
908 | 899 | ||
909 | svc_xprt_put(xprt); | 900 | svc_xprt_put(xprt); |
910 | spin_unlock_bh(&serv->sv_lock); | 901 | spin_unlock_bh(&serv->sv_lock); |
@@ -1204,16 +1195,15 @@ static int svc_pool_stats_show(struct seq_file *m, void *p) | |||
1204 | struct svc_pool *pool = p; | 1195 | struct svc_pool *pool = p; |
1205 | 1196 | ||
1206 | if (p == SEQ_START_TOKEN) { | 1197 | if (p == SEQ_START_TOKEN) { |
1207 | seq_puts(m, "# pool packets-arrived sockets-enqueued threads-woken overloads-avoided threads-timedout\n"); | 1198 | seq_puts(m, "# pool packets-arrived sockets-enqueued threads-woken threads-timedout\n"); |
1208 | return 0; | 1199 | return 0; |
1209 | } | 1200 | } |
1210 | 1201 | ||
1211 | seq_printf(m, "%u %lu %lu %lu %lu %lu\n", | 1202 | seq_printf(m, "%u %lu %lu %lu %lu\n", |
1212 | pool->sp_id, | 1203 | pool->sp_id, |
1213 | pool->sp_stats.packets, | 1204 | pool->sp_stats.packets, |
1214 | pool->sp_stats.sockets_queued, | 1205 | pool->sp_stats.sockets_queued, |
1215 | pool->sp_stats.threads_woken, | 1206 | pool->sp_stats.threads_woken, |
1216 | pool->sp_stats.overloads_avoided, | ||
1217 | pool->sp_stats.threads_timedout); | 1207 | pool->sp_stats.threads_timedout); |
1218 | 1208 | ||
1219 | return 0; | 1209 | return 0; |