diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-08-04 19:59:06 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-08-04 19:59:06 -0400 |
commit | a71e36045e1fd5813addad2fce878d96e2827d66 (patch) | |
tree | c71345261c6342b2d3ee2e5784148898ee59557d /net | |
parent | d58b0d980f0b1c27204da0e05537b606da45a07f (diff) | |
parent | 2b11885921a48767b6ace27c481beba3b42371ce (diff) |
Merge tag 'nfsd-4.8' of git://linux-nfs.org/~bfields/linux
Pull nfsd updates from Bruce Fields:
"Highlights:
- Trond made a change to the server's tcp logic that allows a fast
client to better take advantage of high bandwidth networks, but may
increase the risk that a single client could starve other clients;
a new sunrpc.svc_rpc_per_connection_limit parameter should help
mitigate this in the (hopefully unlikely) event this becomes a
problem in practice.
- Tom Haynes added a minimal flex-layout pnfs server, which is of no
use in production for now--don't build it unless you're doing
client testing or further server development"
* tag 'nfsd-4.8' of git://linux-nfs.org/~bfields/linux: (32 commits)
nfsd: remove some dead code in nfsd_create_locked()
nfsd: drop unnecessary MAY_EXEC check from create
nfsd: clean up bad-type check in nfsd_create_locked
nfsd: remove unnecessary positive-dentry check
nfsd: reorganize nfsd_create
nfsd: check d_can_lookup in fh_verify of directories
nfsd: remove redundant zero-length check from create
nfsd: Make creates return EEXIST instead of EACCES
SUNRPC: Detect immediate closure of accepted sockets
SUNRPC: accept() may return sockets that are still in SYN_RECV
nfsd: allow nfsd to advertise multiple layout types
nfsd: Close race between nfsd4_release_lockowner and nfsd4_lock
nfsd/blocklayout: Make sure calculate signature/designator length aligned
xfs: abstract block export operations from nfsd layouts
SUNRPC: Remove unused callback xpo_adjust_wspace()
SUNRPC: Change TCP socket space reservation
SUNRPC: Add a server side per-connection limit
SUNRPC: Micro optimisation for svc_data_ready
SUNRPC: Call the default socket callbacks instead of open coding
SUNRPC: lock the socket while detaching it
...
Diffstat (limited to 'net')
-rw-r--r-- | net/sunrpc/auth_gss/svcauth_gss.c | 5 | ||||
-rw-r--r-- | net/sunrpc/cache.c | 2 | ||||
-rw-r--r-- | net/sunrpc/svc_xprt.c | 51 | ||||
-rw-r--r-- | net/sunrpc/svcsock.c | 150 |
4 files changed, 86 insertions, 122 deletions
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c index e085f5ae1548..1d281816f2bf 100644 --- a/net/sunrpc/auth_gss/svcauth_gss.c +++ b/net/sunrpc/auth_gss/svcauth_gss.c | |||
@@ -1230,8 +1230,9 @@ static int svcauth_gss_proxy_init(struct svc_rqst *rqstp, | |||
1230 | if (status) | 1230 | if (status) |
1231 | goto out; | 1231 | goto out; |
1232 | 1232 | ||
1233 | dprintk("RPC: svcauth_gss: gss major status = %d\n", | 1233 | dprintk("RPC: svcauth_gss: gss major status = %d " |
1234 | ud.major_status); | 1234 | "minor status = %d\n", |
1235 | ud.major_status, ud.minor_status); | ||
1235 | 1236 | ||
1236 | switch (ud.major_status) { | 1237 | switch (ud.major_status) { |
1237 | case GSS_S_CONTINUE_NEEDED: | 1238 | case GSS_S_CONTINUE_NEEDED: |
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index 553bf95f7003..4d8e11f94a35 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c | |||
@@ -362,7 +362,7 @@ void sunrpc_destroy_cache_detail(struct cache_detail *cd) | |||
362 | cache_purge(cd); | 362 | cache_purge(cd); |
363 | spin_lock(&cache_list_lock); | 363 | spin_lock(&cache_list_lock); |
364 | write_lock(&cd->hash_lock); | 364 | write_lock(&cd->hash_lock); |
365 | if (cd->entries || atomic_read(&cd->inuse)) { | 365 | if (cd->entries) { |
366 | write_unlock(&cd->hash_lock); | 366 | write_unlock(&cd->hash_lock); |
367 | spin_unlock(&cache_list_lock); | 367 | spin_unlock(&cache_list_lock); |
368 | goto out; | 368 | goto out; |
diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c index 4f01f63102ee..c3f652395a80 100644 --- a/net/sunrpc/svc_xprt.c +++ b/net/sunrpc/svc_xprt.c | |||
@@ -21,6 +21,10 @@ | |||
21 | 21 | ||
22 | #define RPCDBG_FACILITY RPCDBG_SVCXPRT | 22 | #define RPCDBG_FACILITY RPCDBG_SVCXPRT |
23 | 23 | ||
24 | static unsigned int svc_rpc_per_connection_limit __read_mostly; | ||
25 | module_param(svc_rpc_per_connection_limit, uint, 0644); | ||
26 | |||
27 | |||
24 | static struct svc_deferred_req *svc_deferred_dequeue(struct svc_xprt *xprt); | 28 | static struct svc_deferred_req *svc_deferred_dequeue(struct svc_xprt *xprt); |
25 | static int svc_deferred_recv(struct svc_rqst *rqstp); | 29 | static int svc_deferred_recv(struct svc_rqst *rqstp); |
26 | static struct cache_deferred_req *svc_defer(struct cache_req *req); | 30 | static struct cache_deferred_req *svc_defer(struct cache_req *req); |
@@ -329,12 +333,45 @@ char *svc_print_addr(struct svc_rqst *rqstp, char *buf, size_t len) | |||
329 | } | 333 | } |
330 | EXPORT_SYMBOL_GPL(svc_print_addr); | 334 | EXPORT_SYMBOL_GPL(svc_print_addr); |
331 | 335 | ||
336 | static bool svc_xprt_slots_in_range(struct svc_xprt *xprt) | ||
337 | { | ||
338 | unsigned int limit = svc_rpc_per_connection_limit; | ||
339 | int nrqsts = atomic_read(&xprt->xpt_nr_rqsts); | ||
340 | |||
341 | return limit == 0 || (nrqsts >= 0 && nrqsts < limit); | ||
342 | } | ||
343 | |||
344 | static bool svc_xprt_reserve_slot(struct svc_rqst *rqstp, struct svc_xprt *xprt) | ||
345 | { | ||
346 | if (!test_bit(RQ_DATA, &rqstp->rq_flags)) { | ||
347 | if (!svc_xprt_slots_in_range(xprt)) | ||
348 | return false; | ||
349 | atomic_inc(&xprt->xpt_nr_rqsts); | ||
350 | set_bit(RQ_DATA, &rqstp->rq_flags); | ||
351 | } | ||
352 | return true; | ||
353 | } | ||
354 | |||
355 | static void svc_xprt_release_slot(struct svc_rqst *rqstp) | ||
356 | { | ||
357 | struct svc_xprt *xprt = rqstp->rq_xprt; | ||
358 | if (test_and_clear_bit(RQ_DATA, &rqstp->rq_flags)) { | ||
359 | atomic_dec(&xprt->xpt_nr_rqsts); | ||
360 | svc_xprt_enqueue(xprt); | ||
361 | } | ||
362 | } | ||
363 | |||
332 | static bool svc_xprt_has_something_to_do(struct svc_xprt *xprt) | 364 | static bool svc_xprt_has_something_to_do(struct svc_xprt *xprt) |
333 | { | 365 | { |
334 | if (xprt->xpt_flags & ((1<<XPT_CONN)|(1<<XPT_CLOSE))) | 366 | if (xprt->xpt_flags & ((1<<XPT_CONN)|(1<<XPT_CLOSE))) |
335 | return true; | 367 | return true; |
336 | if (xprt->xpt_flags & ((1<<XPT_DATA)|(1<<XPT_DEFERRED))) | 368 | if (xprt->xpt_flags & ((1<<XPT_DATA)|(1<<XPT_DEFERRED))) { |
337 | return xprt->xpt_ops->xpo_has_wspace(xprt); | 369 | if (xprt->xpt_ops->xpo_has_wspace(xprt) && |
370 | svc_xprt_slots_in_range(xprt)) | ||
371 | return true; | ||
372 | trace_svc_xprt_no_write_space(xprt); | ||
373 | return false; | ||
374 | } | ||
338 | return false; | 375 | return false; |
339 | } | 376 | } |
340 | 377 | ||
@@ -480,8 +517,6 @@ void svc_reserve(struct svc_rqst *rqstp, int space) | |||
480 | atomic_sub((rqstp->rq_reserved - space), &xprt->xpt_reserved); | 517 | atomic_sub((rqstp->rq_reserved - space), &xprt->xpt_reserved); |
481 | rqstp->rq_reserved = space; | 518 | rqstp->rq_reserved = space; |
482 | 519 | ||
483 | if (xprt->xpt_ops->xpo_adjust_wspace) | ||
484 | xprt->xpt_ops->xpo_adjust_wspace(xprt); | ||
485 | svc_xprt_enqueue(xprt); | 520 | svc_xprt_enqueue(xprt); |
486 | } | 521 | } |
487 | } | 522 | } |
@@ -512,8 +547,8 @@ static void svc_xprt_release(struct svc_rqst *rqstp) | |||
512 | 547 | ||
513 | rqstp->rq_res.head[0].iov_len = 0; | 548 | rqstp->rq_res.head[0].iov_len = 0; |
514 | svc_reserve(rqstp, 0); | 549 | svc_reserve(rqstp, 0); |
550 | svc_xprt_release_slot(rqstp); | ||
515 | rqstp->rq_xprt = NULL; | 551 | rqstp->rq_xprt = NULL; |
516 | |||
517 | svc_xprt_put(xprt); | 552 | svc_xprt_put(xprt); |
518 | } | 553 | } |
519 | 554 | ||
@@ -781,7 +816,7 @@ static int svc_handle_xprt(struct svc_rqst *rqstp, struct svc_xprt *xprt) | |||
781 | svc_add_new_temp_xprt(serv, newxpt); | 816 | svc_add_new_temp_xprt(serv, newxpt); |
782 | else | 817 | else |
783 | module_put(xprt->xpt_class->xcl_owner); | 818 | module_put(xprt->xpt_class->xcl_owner); |
784 | } else { | 819 | } else if (svc_xprt_reserve_slot(rqstp, xprt)) { |
785 | /* XPT_DATA|XPT_DEFERRED case: */ | 820 | /* XPT_DATA|XPT_DEFERRED case: */ |
786 | dprintk("svc: server %p, pool %u, transport %p, inuse=%d\n", | 821 | dprintk("svc: server %p, pool %u, transport %p, inuse=%d\n", |
787 | rqstp, rqstp->rq_pool->sp_id, xprt, | 822 | rqstp, rqstp->rq_pool->sp_id, xprt, |
@@ -871,6 +906,7 @@ EXPORT_SYMBOL_GPL(svc_recv); | |||
871 | */ | 906 | */ |
872 | void svc_drop(struct svc_rqst *rqstp) | 907 | void svc_drop(struct svc_rqst *rqstp) |
873 | { | 908 | { |
909 | trace_svc_drop(rqstp); | ||
874 | dprintk("svc: xprt %p dropped request\n", rqstp->rq_xprt); | 910 | dprintk("svc: xprt %p dropped request\n", rqstp->rq_xprt); |
875 | svc_xprt_release(rqstp); | 911 | svc_xprt_release(rqstp); |
876 | } | 912 | } |
@@ -1148,6 +1184,7 @@ static void svc_revisit(struct cache_deferred_req *dreq, int too_many) | |||
1148 | spin_unlock(&xprt->xpt_lock); | 1184 | spin_unlock(&xprt->xpt_lock); |
1149 | dprintk("revisit canceled\n"); | 1185 | dprintk("revisit canceled\n"); |
1150 | svc_xprt_put(xprt); | 1186 | svc_xprt_put(xprt); |
1187 | trace_svc_drop_deferred(dr); | ||
1151 | kfree(dr); | 1188 | kfree(dr); |
1152 | return; | 1189 | return; |
1153 | } | 1190 | } |
@@ -1205,6 +1242,7 @@ static struct cache_deferred_req *svc_defer(struct cache_req *req) | |||
1205 | set_bit(RQ_DROPME, &rqstp->rq_flags); | 1242 | set_bit(RQ_DROPME, &rqstp->rq_flags); |
1206 | 1243 | ||
1207 | dr->handle.revisit = svc_revisit; | 1244 | dr->handle.revisit = svc_revisit; |
1245 | trace_svc_defer(rqstp); | ||
1208 | return &dr->handle; | 1246 | return &dr->handle; |
1209 | } | 1247 | } |
1210 | 1248 | ||
@@ -1245,6 +1283,7 @@ static struct svc_deferred_req *svc_deferred_dequeue(struct svc_xprt *xprt) | |||
1245 | struct svc_deferred_req, | 1283 | struct svc_deferred_req, |
1246 | handle.recent); | 1284 | handle.recent); |
1247 | list_del_init(&dr->handle.recent); | 1285 | list_del_init(&dr->handle.recent); |
1286 | trace_svc_revisit_deferred(dr); | ||
1248 | } else | 1287 | } else |
1249 | clear_bit(XPT_DEFERRED, &xprt->xpt_flags); | 1288 | clear_bit(XPT_DEFERRED, &xprt->xpt_flags); |
1250 | spin_unlock(&xprt->xpt_lock); | 1289 | spin_unlock(&xprt->xpt_lock); |
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index dadfec66dbd8..57625f64efd5 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c | |||
@@ -60,7 +60,6 @@ | |||
60 | 60 | ||
61 | static struct svc_sock *svc_setup_socket(struct svc_serv *, struct socket *, | 61 | static struct svc_sock *svc_setup_socket(struct svc_serv *, struct socket *, |
62 | int flags); | 62 | int flags); |
63 | static void svc_udp_data_ready(struct sock *); | ||
64 | static int svc_udp_recvfrom(struct svc_rqst *); | 63 | static int svc_udp_recvfrom(struct svc_rqst *); |
65 | static int svc_udp_sendto(struct svc_rqst *); | 64 | static int svc_udp_sendto(struct svc_rqst *); |
66 | static void svc_sock_detach(struct svc_xprt *); | 65 | static void svc_sock_detach(struct svc_xprt *); |
@@ -398,48 +397,21 @@ static int svc_sock_secure_port(struct svc_rqst *rqstp) | |||
398 | return svc_port_is_privileged(svc_addr(rqstp)); | 397 | return svc_port_is_privileged(svc_addr(rqstp)); |
399 | } | 398 | } |
400 | 399 | ||
401 | static bool sunrpc_waitqueue_active(wait_queue_head_t *wq) | ||
402 | { | ||
403 | if (!wq) | ||
404 | return false; | ||
405 | /* | ||
406 | * There should normally be a memory * barrier here--see | ||
407 | * wq_has_sleeper(). | ||
408 | * | ||
409 | * It appears that isn't currently necessary, though, basically | ||
410 | * because callers all appear to have sufficient memory barriers | ||
411 | * between the time the relevant change is made and the | ||
412 | * time they call these callbacks. | ||
413 | * | ||
414 | * The nfsd code itself doesn't actually explicitly wait on | ||
415 | * these waitqueues, but it may wait on them for example in | ||
416 | * sendpage() or sendmsg() calls. (And those may be the only | ||
417 | * places, since it it uses nonblocking reads.) | ||
418 | * | ||
419 | * Maybe we should add the memory barriers anyway, but these are | ||
420 | * hot paths so we'd need to be convinced there's no sigificant | ||
421 | * penalty. | ||
422 | */ | ||
423 | return waitqueue_active(wq); | ||
424 | } | ||
425 | |||
426 | /* | 400 | /* |
427 | * INET callback when data has been received on the socket. | 401 | * INET callback when data has been received on the socket. |
428 | */ | 402 | */ |
429 | static void svc_udp_data_ready(struct sock *sk) | 403 | static void svc_data_ready(struct sock *sk) |
430 | { | 404 | { |
431 | struct svc_sock *svsk = (struct svc_sock *)sk->sk_user_data; | 405 | struct svc_sock *svsk = (struct svc_sock *)sk->sk_user_data; |
432 | wait_queue_head_t *wq = sk_sleep(sk); | ||
433 | 406 | ||
434 | if (svsk) { | 407 | if (svsk) { |
435 | dprintk("svc: socket %p(inet %p), busy=%d\n", | 408 | dprintk("svc: socket %p(inet %p), busy=%d\n", |
436 | svsk, sk, | 409 | svsk, sk, |
437 | test_bit(XPT_BUSY, &svsk->sk_xprt.xpt_flags)); | 410 | test_bit(XPT_BUSY, &svsk->sk_xprt.xpt_flags)); |
438 | set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags); | 411 | svsk->sk_odata(sk); |
439 | svc_xprt_enqueue(&svsk->sk_xprt); | 412 | if (!test_and_set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags)) |
413 | svc_xprt_enqueue(&svsk->sk_xprt); | ||
440 | } | 414 | } |
441 | if (sunrpc_waitqueue_active(wq)) | ||
442 | wake_up_interruptible(wq); | ||
443 | } | 415 | } |
444 | 416 | ||
445 | /* | 417 | /* |
@@ -448,56 +420,22 @@ static void svc_udp_data_ready(struct sock *sk) | |||
448 | static void svc_write_space(struct sock *sk) | 420 | static void svc_write_space(struct sock *sk) |
449 | { | 421 | { |
450 | struct svc_sock *svsk = (struct svc_sock *)(sk->sk_user_data); | 422 | struct svc_sock *svsk = (struct svc_sock *)(sk->sk_user_data); |
451 | wait_queue_head_t *wq = sk_sleep(sk); | ||
452 | 423 | ||
453 | if (svsk) { | 424 | if (svsk) { |
454 | dprintk("svc: socket %p(inet %p), write_space busy=%d\n", | 425 | dprintk("svc: socket %p(inet %p), write_space busy=%d\n", |
455 | svsk, sk, test_bit(XPT_BUSY, &svsk->sk_xprt.xpt_flags)); | 426 | svsk, sk, test_bit(XPT_BUSY, &svsk->sk_xprt.xpt_flags)); |
427 | svsk->sk_owspace(sk); | ||
456 | svc_xprt_enqueue(&svsk->sk_xprt); | 428 | svc_xprt_enqueue(&svsk->sk_xprt); |
457 | } | 429 | } |
458 | |||
459 | if (sunrpc_waitqueue_active(wq)) { | ||
460 | dprintk("RPC svc_write_space: someone sleeping on %p\n", | ||
461 | svsk); | ||
462 | wake_up_interruptible(wq); | ||
463 | } | ||
464 | } | 430 | } |
465 | 431 | ||
466 | static int svc_tcp_has_wspace(struct svc_xprt *xprt) | 432 | static int svc_tcp_has_wspace(struct svc_xprt *xprt) |
467 | { | 433 | { |
468 | struct svc_sock *svsk = container_of(xprt, struct svc_sock, sk_xprt); | 434 | struct svc_sock *svsk = container_of(xprt, struct svc_sock, sk_xprt); |
469 | struct svc_serv *serv = svsk->sk_xprt.xpt_server; | ||
470 | int required; | ||
471 | 435 | ||
472 | if (test_bit(XPT_LISTENER, &xprt->xpt_flags)) | 436 | if (test_bit(XPT_LISTENER, &xprt->xpt_flags)) |
473 | return 1; | 437 | return 1; |
474 | required = atomic_read(&xprt->xpt_reserved) + serv->sv_max_mesg; | 438 | return !test_bit(SOCK_NOSPACE, &svsk->sk_sock->flags); |
475 | if (sk_stream_wspace(svsk->sk_sk) >= required || | ||
476 | (sk_stream_min_wspace(svsk->sk_sk) == 0 && | ||
477 | atomic_read(&xprt->xpt_reserved) == 0)) | ||
478 | return 1; | ||
479 | set_bit(SOCK_NOSPACE, &svsk->sk_sock->flags); | ||
480 | return 0; | ||
481 | } | ||
482 | |||
483 | static void svc_tcp_write_space(struct sock *sk) | ||
484 | { | ||
485 | struct svc_sock *svsk = (struct svc_sock *)(sk->sk_user_data); | ||
486 | struct socket *sock = sk->sk_socket; | ||
487 | |||
488 | if (!sk_stream_is_writeable(sk) || !sock) | ||
489 | return; | ||
490 | if (!svsk || svc_tcp_has_wspace(&svsk->sk_xprt)) | ||
491 | clear_bit(SOCK_NOSPACE, &sock->flags); | ||
492 | svc_write_space(sk); | ||
493 | } | ||
494 | |||
495 | static void svc_tcp_adjust_wspace(struct svc_xprt *xprt) | ||
496 | { | ||
497 | struct svc_sock *svsk = container_of(xprt, struct svc_sock, sk_xprt); | ||
498 | |||
499 | if (svc_tcp_has_wspace(xprt)) | ||
500 | clear_bit(SOCK_NOSPACE, &svsk->sk_sock->flags); | ||
501 | } | 439 | } |
502 | 440 | ||
503 | /* | 441 | /* |
@@ -746,7 +684,7 @@ static void svc_udp_init(struct svc_sock *svsk, struct svc_serv *serv) | |||
746 | svc_xprt_init(sock_net(svsk->sk_sock->sk), &svc_udp_class, | 684 | svc_xprt_init(sock_net(svsk->sk_sock->sk), &svc_udp_class, |
747 | &svsk->sk_xprt, serv); | 685 | &svsk->sk_xprt, serv); |
748 | clear_bit(XPT_CACHE_AUTH, &svsk->sk_xprt.xpt_flags); | 686 | clear_bit(XPT_CACHE_AUTH, &svsk->sk_xprt.xpt_flags); |
749 | svsk->sk_sk->sk_data_ready = svc_udp_data_ready; | 687 | svsk->sk_sk->sk_data_ready = svc_data_ready; |
750 | svsk->sk_sk->sk_write_space = svc_write_space; | 688 | svsk->sk_sk->sk_write_space = svc_write_space; |
751 | 689 | ||
752 | /* initialise setting must have enough space to | 690 | /* initialise setting must have enough space to |
@@ -786,11 +724,12 @@ static void svc_udp_init(struct svc_sock *svsk, struct svc_serv *serv) | |||
786 | static void svc_tcp_listen_data_ready(struct sock *sk) | 724 | static void svc_tcp_listen_data_ready(struct sock *sk) |
787 | { | 725 | { |
788 | struct svc_sock *svsk = (struct svc_sock *)sk->sk_user_data; | 726 | struct svc_sock *svsk = (struct svc_sock *)sk->sk_user_data; |
789 | wait_queue_head_t *wq; | ||
790 | 727 | ||
791 | dprintk("svc: socket %p TCP (listen) state change %d\n", | 728 | dprintk("svc: socket %p TCP (listen) state change %d\n", |
792 | sk, sk->sk_state); | 729 | sk, sk->sk_state); |
793 | 730 | ||
731 | if (svsk) | ||
732 | svsk->sk_odata(sk); | ||
794 | /* | 733 | /* |
795 | * This callback may called twice when a new connection | 734 | * This callback may called twice when a new connection |
796 | * is established as a child socket inherits everything | 735 | * is established as a child socket inherits everything |
@@ -808,10 +747,6 @@ static void svc_tcp_listen_data_ready(struct sock *sk) | |||
808 | } else | 747 | } else |
809 | printk("svc: socket %p: no user data\n", sk); | 748 | printk("svc: socket %p: no user data\n", sk); |
810 | } | 749 | } |
811 | |||
812 | wq = sk_sleep(sk); | ||
813 | if (sunrpc_waitqueue_active(wq)) | ||
814 | wake_up_interruptible_all(wq); | ||
815 | } | 750 | } |
816 | 751 | ||
817 | /* | 752 | /* |
@@ -820,7 +755,6 @@ static void svc_tcp_listen_data_ready(struct sock *sk) | |||
820 | static void svc_tcp_state_change(struct sock *sk) | 755 | static void svc_tcp_state_change(struct sock *sk) |
821 | { | 756 | { |
822 | struct svc_sock *svsk = (struct svc_sock *)sk->sk_user_data; | 757 | struct svc_sock *svsk = (struct svc_sock *)sk->sk_user_data; |
823 | wait_queue_head_t *wq = sk_sleep(sk); | ||
824 | 758 | ||
825 | dprintk("svc: socket %p TCP (connected) state change %d (svsk %p)\n", | 759 | dprintk("svc: socket %p TCP (connected) state change %d (svsk %p)\n", |
826 | sk, sk->sk_state, sk->sk_user_data); | 760 | sk, sk->sk_state, sk->sk_user_data); |
@@ -828,26 +762,12 @@ static void svc_tcp_state_change(struct sock *sk) | |||
828 | if (!svsk) | 762 | if (!svsk) |
829 | printk("svc: socket %p: no user data\n", sk); | 763 | printk("svc: socket %p: no user data\n", sk); |
830 | else { | 764 | else { |
831 | set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags); | 765 | svsk->sk_ostate(sk); |
832 | svc_xprt_enqueue(&svsk->sk_xprt); | 766 | if (sk->sk_state != TCP_ESTABLISHED) { |
833 | } | 767 | set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags); |
834 | if (sunrpc_waitqueue_active(wq)) | 768 | svc_xprt_enqueue(&svsk->sk_xprt); |
835 | wake_up_interruptible_all(wq); | 769 | } |
836 | } | ||
837 | |||
838 | static void svc_tcp_data_ready(struct sock *sk) | ||
839 | { | ||
840 | struct svc_sock *svsk = (struct svc_sock *)sk->sk_user_data; | ||
841 | wait_queue_head_t *wq = sk_sleep(sk); | ||
842 | |||
843 | dprintk("svc: socket %p TCP data ready (svsk %p)\n", | ||
844 | sk, sk->sk_user_data); | ||
845 | if (svsk) { | ||
846 | set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags); | ||
847 | svc_xprt_enqueue(&svsk->sk_xprt); | ||
848 | } | 770 | } |
849 | if (sunrpc_waitqueue_active(wq)) | ||
850 | wake_up_interruptible(wq); | ||
851 | } | 771 | } |
852 | 772 | ||
853 | /* | 773 | /* |
@@ -901,6 +821,11 @@ static struct svc_xprt *svc_tcp_accept(struct svc_xprt *xprt) | |||
901 | dprintk("%s: connect from %s\n", serv->sv_name, | 821 | dprintk("%s: connect from %s\n", serv->sv_name, |
902 | __svc_print_addr(sin, buf, sizeof(buf))); | 822 | __svc_print_addr(sin, buf, sizeof(buf))); |
903 | 823 | ||
824 | /* Reset the inherited callbacks before calling svc_setup_socket */ | ||
825 | newsock->sk->sk_state_change = svsk->sk_ostate; | ||
826 | newsock->sk->sk_data_ready = svsk->sk_odata; | ||
827 | newsock->sk->sk_write_space = svsk->sk_owspace; | ||
828 | |||
904 | /* make sure that a write doesn't block forever when | 829 | /* make sure that a write doesn't block forever when |
905 | * low on memory | 830 | * low on memory |
906 | */ | 831 | */ |
@@ -1317,7 +1242,6 @@ static struct svc_xprt_ops svc_tcp_ops = { | |||
1317 | .xpo_has_wspace = svc_tcp_has_wspace, | 1242 | .xpo_has_wspace = svc_tcp_has_wspace, |
1318 | .xpo_accept = svc_tcp_accept, | 1243 | .xpo_accept = svc_tcp_accept, |
1319 | .xpo_secure_port = svc_sock_secure_port, | 1244 | .xpo_secure_port = svc_sock_secure_port, |
1320 | .xpo_adjust_wspace = svc_tcp_adjust_wspace, | ||
1321 | }; | 1245 | }; |
1322 | 1246 | ||
1323 | static struct svc_xprt_class svc_tcp_class = { | 1247 | static struct svc_xprt_class svc_tcp_class = { |
@@ -1357,8 +1281,8 @@ static void svc_tcp_init(struct svc_sock *svsk, struct svc_serv *serv) | |||
1357 | } else { | 1281 | } else { |
1358 | dprintk("setting up TCP socket for reading\n"); | 1282 | dprintk("setting up TCP socket for reading\n"); |
1359 | sk->sk_state_change = svc_tcp_state_change; | 1283 | sk->sk_state_change = svc_tcp_state_change; |
1360 | sk->sk_data_ready = svc_tcp_data_ready; | 1284 | sk->sk_data_ready = svc_data_ready; |
1361 | sk->sk_write_space = svc_tcp_write_space; | 1285 | sk->sk_write_space = svc_write_space; |
1362 | 1286 | ||
1363 | svsk->sk_reclen = 0; | 1287 | svsk->sk_reclen = 0; |
1364 | svsk->sk_tcplen = 0; | 1288 | svsk->sk_tcplen = 0; |
@@ -1368,8 +1292,13 @@ static void svc_tcp_init(struct svc_sock *svsk, struct svc_serv *serv) | |||
1368 | tcp_sk(sk)->nonagle |= TCP_NAGLE_OFF; | 1292 | tcp_sk(sk)->nonagle |= TCP_NAGLE_OFF; |
1369 | 1293 | ||
1370 | set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags); | 1294 | set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags); |
1371 | if (sk->sk_state != TCP_ESTABLISHED) | 1295 | switch (sk->sk_state) { |
1296 | case TCP_SYN_RECV: | ||
1297 | case TCP_ESTABLISHED: | ||
1298 | break; | ||
1299 | default: | ||
1372 | set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags); | 1300 | set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags); |
1301 | } | ||
1373 | } | 1302 | } |
1374 | } | 1303 | } |
1375 | 1304 | ||
@@ -1428,17 +1357,14 @@ static struct svc_sock *svc_setup_socket(struct svc_serv *serv, | |||
1428 | /* Initialize the socket */ | 1357 | /* Initialize the socket */ |
1429 | if (sock->type == SOCK_DGRAM) | 1358 | if (sock->type == SOCK_DGRAM) |
1430 | svc_udp_init(svsk, serv); | 1359 | svc_udp_init(svsk, serv); |
1431 | else { | 1360 | else |
1432 | /* initialise setting must have enough space to | ||
1433 | * receive and respond to one request. | ||
1434 | */ | ||
1435 | svc_sock_setbufsize(svsk->sk_sock, 4 * serv->sv_max_mesg, | ||
1436 | 4 * serv->sv_max_mesg); | ||
1437 | svc_tcp_init(svsk, serv); | 1361 | svc_tcp_init(svsk, serv); |
1438 | } | ||
1439 | 1362 | ||
1440 | dprintk("svc: svc_setup_socket created %p (inet %p)\n", | 1363 | dprintk("svc: svc_setup_socket created %p (inet %p), " |
1441 | svsk, svsk->sk_sk); | 1364 | "listen %d close %d\n", |
1365 | svsk, svsk->sk_sk, | ||
1366 | test_bit(XPT_LISTENER, &svsk->sk_xprt.xpt_flags), | ||
1367 | test_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags)); | ||
1442 | 1368 | ||
1443 | return svsk; | 1369 | return svsk; |
1444 | } | 1370 | } |
@@ -1606,18 +1532,16 @@ static void svc_sock_detach(struct svc_xprt *xprt) | |||
1606 | { | 1532 | { |
1607 | struct svc_sock *svsk = container_of(xprt, struct svc_sock, sk_xprt); | 1533 | struct svc_sock *svsk = container_of(xprt, struct svc_sock, sk_xprt); |
1608 | struct sock *sk = svsk->sk_sk; | 1534 | struct sock *sk = svsk->sk_sk; |
1609 | wait_queue_head_t *wq; | ||
1610 | 1535 | ||
1611 | dprintk("svc: svc_sock_detach(%p)\n", svsk); | 1536 | dprintk("svc: svc_sock_detach(%p)\n", svsk); |
1612 | 1537 | ||
1613 | /* put back the old socket callbacks */ | 1538 | /* put back the old socket callbacks */ |
1539 | lock_sock(sk); | ||
1614 | sk->sk_state_change = svsk->sk_ostate; | 1540 | sk->sk_state_change = svsk->sk_ostate; |
1615 | sk->sk_data_ready = svsk->sk_odata; | 1541 | sk->sk_data_ready = svsk->sk_odata; |
1616 | sk->sk_write_space = svsk->sk_owspace; | 1542 | sk->sk_write_space = svsk->sk_owspace; |
1617 | 1543 | sk->sk_user_data = NULL; | |
1618 | wq = sk_sleep(sk); | 1544 | release_sock(sk); |
1619 | if (sunrpc_waitqueue_active(wq)) | ||
1620 | wake_up_interruptible(wq); | ||
1621 | } | 1545 | } |
1622 | 1546 | ||
1623 | /* | 1547 | /* |