diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-12 21:53:54 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-12 21:53:54 -0400 |
commit | bd81ccea8558daab570d70d2c23746413f26cecf (patch) | |
tree | a3a75dde2dc3cf26c74353b21792da30d65d7c13 /net/sunrpc | |
parent | 98260daa184c4a171834463cf85ab3a2c509d983 (diff) | |
parent | a9ca4043d074509b9d15003fbcb068d3cdae85a4 (diff) |
Merge branch 'for-3.7' of git://linux-nfs.org/~bfields/linux
Pull nfsd update from J Bruce Fields:
"Another relatively quiet cycle. There was some progress on my
remaining 4.1 todo's, but a couple of them were just of the form
"check that we do X correctly", so didn't have much affect on the
code.
Other than that, a bunch of cleanup and some bugfixes (including an
annoying NFSv4.0 state leak and a busy-loop in the server that could
cause it to peg the CPU without making progress)."
* 'for-3.7' of git://linux-nfs.org/~bfields/linux: (46 commits)
UAPI: (Scripted) Disintegrate include/linux/sunrpc
UAPI: (Scripted) Disintegrate include/linux/nfsd
nfsd4: don't allow reclaims of expired clients
nfsd4: remove redundant callback probe
nfsd4: expire old client earlier
nfsd4: separate session allocation and initialization
nfsd4: clean up session allocation
nfsd4: minor free_session cleanup
nfsd4: new_conn_from_crses should only allocate
nfsd4: separate connection allocation and initialization
nfsd4: reject bad forechannel attrs earlier
nfsd4: enforce per-client sessions/no-sessions distinction
nfsd4: set cl_minorversion at create time
nfsd4: don't pin clientids to pseudoflavors
nfsd4: fix bind_conn_to_session xdr comment
nfsd4: cast readlink() bug argument
NFSD: pass null terminated buf to kstrtouint()
nfsd: remove duplicate init in nfsd4_cb_recall
nfsd4: eliminate redundant nfs4_free_stateid
fs/nfsd/nfs4idmap.c: adjust inconsistent IS_ERR and PTR_ERR
...
Diffstat (limited to 'net/sunrpc')
-rw-r--r-- | net/sunrpc/svc_xprt.c | 233 | ||||
-rw-r--r-- | net/sunrpc/svcsock.c | 157 | ||||
-rw-r--r-- | net/sunrpc/xprtrdma/svc_rdma_transport.c | 4 |
3 files changed, 190 insertions, 204 deletions
diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c index bac973a31367..194d865fae72 100644 --- a/net/sunrpc/svc_xprt.c +++ b/net/sunrpc/svc_xprt.c | |||
@@ -208,6 +208,35 @@ static struct svc_xprt *__svc_xpo_create(struct svc_xprt_class *xcl, | |||
208 | return xcl->xcl_ops->xpo_create(serv, net, sap, len, flags); | 208 | return xcl->xcl_ops->xpo_create(serv, net, sap, len, flags); |
209 | } | 209 | } |
210 | 210 | ||
211 | /* | ||
212 | * svc_xprt_received conditionally queues the transport for processing | ||
213 | * by another thread. The caller must hold the XPT_BUSY bit and must | ||
214 | * not thereafter touch transport data. | ||
215 | * | ||
216 | * Note: XPT_DATA only gets cleared when a read-attempt finds no (or | ||
217 | * insufficient) data. | ||
218 | */ | ||
219 | static void svc_xprt_received(struct svc_xprt *xprt) | ||
220 | { | ||
221 | BUG_ON(!test_bit(XPT_BUSY, &xprt->xpt_flags)); | ||
222 | /* As soon as we clear busy, the xprt could be closed and | ||
223 | * 'put', so we need a reference to call svc_xprt_enqueue with: | ||
224 | */ | ||
225 | svc_xprt_get(xprt); | ||
226 | clear_bit(XPT_BUSY, &xprt->xpt_flags); | ||
227 | svc_xprt_enqueue(xprt); | ||
228 | svc_xprt_put(xprt); | ||
229 | } | ||
230 | |||
231 | void svc_add_new_perm_xprt(struct svc_serv *serv, struct svc_xprt *new) | ||
232 | { | ||
233 | clear_bit(XPT_TEMP, &new->xpt_flags); | ||
234 | spin_lock_bh(&serv->sv_lock); | ||
235 | list_add(&new->xpt_list, &serv->sv_permsocks); | ||
236 | spin_unlock_bh(&serv->sv_lock); | ||
237 | svc_xprt_received(new); | ||
238 | } | ||
239 | |||
211 | int svc_create_xprt(struct svc_serv *serv, const char *xprt_name, | 240 | int svc_create_xprt(struct svc_serv *serv, const char *xprt_name, |
212 | struct net *net, const int family, | 241 | struct net *net, const int family, |
213 | const unsigned short port, int flags) | 242 | const unsigned short port, int flags) |
@@ -232,13 +261,8 @@ int svc_create_xprt(struct svc_serv *serv, const char *xprt_name, | |||
232 | module_put(xcl->xcl_owner); | 261 | module_put(xcl->xcl_owner); |
233 | return PTR_ERR(newxprt); | 262 | return PTR_ERR(newxprt); |
234 | } | 263 | } |
235 | 264 | svc_add_new_perm_xprt(serv, newxprt); | |
236 | clear_bit(XPT_TEMP, &newxprt->xpt_flags); | ||
237 | spin_lock_bh(&serv->sv_lock); | ||
238 | list_add(&newxprt->xpt_list, &serv->sv_permsocks); | ||
239 | spin_unlock_bh(&serv->sv_lock); | ||
240 | newport = svc_xprt_local_port(newxprt); | 265 | newport = svc_xprt_local_port(newxprt); |
241 | clear_bit(XPT_BUSY, &newxprt->xpt_flags); | ||
242 | return newport; | 266 | return newport; |
243 | } | 267 | } |
244 | err: | 268 | err: |
@@ -394,27 +418,6 @@ static struct svc_xprt *svc_xprt_dequeue(struct svc_pool *pool) | |||
394 | return xprt; | 418 | return xprt; |
395 | } | 419 | } |
396 | 420 | ||
397 | /* | ||
398 | * svc_xprt_received conditionally queues the transport for processing | ||
399 | * by another thread. The caller must hold the XPT_BUSY bit and must | ||
400 | * not thereafter touch transport data. | ||
401 | * | ||
402 | * Note: XPT_DATA only gets cleared when a read-attempt finds no (or | ||
403 | * insufficient) data. | ||
404 | */ | ||
405 | void svc_xprt_received(struct svc_xprt *xprt) | ||
406 | { | ||
407 | BUG_ON(!test_bit(XPT_BUSY, &xprt->xpt_flags)); | ||
408 | /* As soon as we clear busy, the xprt could be closed and | ||
409 | * 'put', so we need a reference to call svc_xprt_enqueue with: | ||
410 | */ | ||
411 | svc_xprt_get(xprt); | ||
412 | clear_bit(XPT_BUSY, &xprt->xpt_flags); | ||
413 | svc_xprt_enqueue(xprt); | ||
414 | svc_xprt_put(xprt); | ||
415 | } | ||
416 | EXPORT_SYMBOL_GPL(svc_xprt_received); | ||
417 | |||
418 | /** | 421 | /** |
419 | * svc_reserve - change the space reserved for the reply to a request. | 422 | * svc_reserve - change the space reserved for the reply to a request. |
420 | * @rqstp: The request in question | 423 | * @rqstp: The request in question |
@@ -565,33 +568,12 @@ static void svc_check_conn_limits(struct svc_serv *serv) | |||
565 | } | 568 | } |
566 | } | 569 | } |
567 | 570 | ||
568 | /* | 571 | int svc_alloc_arg(struct svc_rqst *rqstp) |
569 | * Receive the next request on any transport. This code is carefully | ||
570 | * organised not to touch any cachelines in the shared svc_serv | ||
571 | * structure, only cachelines in the local svc_pool. | ||
572 | */ | ||
573 | int svc_recv(struct svc_rqst *rqstp, long timeout) | ||
574 | { | 572 | { |
575 | struct svc_xprt *xprt = NULL; | 573 | struct svc_serv *serv = rqstp->rq_server; |
576 | struct svc_serv *serv = rqstp->rq_server; | 574 | struct xdr_buf *arg; |
577 | struct svc_pool *pool = rqstp->rq_pool; | 575 | int pages; |
578 | int len, i; | 576 | int i; |
579 | int pages; | ||
580 | struct xdr_buf *arg; | ||
581 | DECLARE_WAITQUEUE(wait, current); | ||
582 | long time_left; | ||
583 | |||
584 | dprintk("svc: server %p waiting for data (to = %ld)\n", | ||
585 | rqstp, timeout); | ||
586 | |||
587 | if (rqstp->rq_xprt) | ||
588 | printk(KERN_ERR | ||
589 | "svc_recv: service %p, transport not NULL!\n", | ||
590 | rqstp); | ||
591 | if (waitqueue_active(&rqstp->rq_wait)) | ||
592 | printk(KERN_ERR | ||
593 | "svc_recv: service %p, wait queue active!\n", | ||
594 | rqstp); | ||
595 | 577 | ||
596 | /* now allocate needed pages. If we get a failure, sleep briefly */ | 578 | /* now allocate needed pages. If we get a failure, sleep briefly */ |
597 | pages = (serv->sv_max_mesg + PAGE_SIZE) / PAGE_SIZE; | 579 | pages = (serv->sv_max_mesg + PAGE_SIZE) / PAGE_SIZE; |
@@ -621,11 +603,15 @@ int svc_recv(struct svc_rqst *rqstp, long timeout) | |||
621 | arg->page_len = (pages-2)*PAGE_SIZE; | 603 | arg->page_len = (pages-2)*PAGE_SIZE; |
622 | arg->len = (pages-1)*PAGE_SIZE; | 604 | arg->len = (pages-1)*PAGE_SIZE; |
623 | arg->tail[0].iov_len = 0; | 605 | arg->tail[0].iov_len = 0; |
606 | return 0; | ||
607 | } | ||
624 | 608 | ||
625 | try_to_freeze(); | 609 | struct svc_xprt *svc_get_next_xprt(struct svc_rqst *rqstp, long timeout) |
626 | cond_resched(); | 610 | { |
627 | if (signalled() || kthread_should_stop()) | 611 | struct svc_xprt *xprt; |
628 | return -EINTR; | 612 | struct svc_pool *pool = rqstp->rq_pool; |
613 | DECLARE_WAITQUEUE(wait, current); | ||
614 | long time_left; | ||
629 | 615 | ||
630 | /* Normally we will wait up to 5 seconds for any required | 616 | /* Normally we will wait up to 5 seconds for any required |
631 | * cache information to be provided. | 617 | * cache information to be provided. |
@@ -663,7 +649,7 @@ int svc_recv(struct svc_rqst *rqstp, long timeout) | |||
663 | if (kthread_should_stop()) { | 649 | if (kthread_should_stop()) { |
664 | set_current_state(TASK_RUNNING); | 650 | set_current_state(TASK_RUNNING); |
665 | spin_unlock_bh(&pool->sp_lock); | 651 | spin_unlock_bh(&pool->sp_lock); |
666 | return -EINTR; | 652 | return ERR_PTR(-EINTR); |
667 | } | 653 | } |
668 | 654 | ||
669 | add_wait_queue(&rqstp->rq_wait, &wait); | 655 | add_wait_queue(&rqstp->rq_wait, &wait); |
@@ -684,48 +670,58 @@ int svc_recv(struct svc_rqst *rqstp, long timeout) | |||
684 | spin_unlock_bh(&pool->sp_lock); | 670 | spin_unlock_bh(&pool->sp_lock); |
685 | dprintk("svc: server %p, no data yet\n", rqstp); | 671 | dprintk("svc: server %p, no data yet\n", rqstp); |
686 | if (signalled() || kthread_should_stop()) | 672 | if (signalled() || kthread_should_stop()) |
687 | return -EINTR; | 673 | return ERR_PTR(-EINTR); |
688 | else | 674 | else |
689 | return -EAGAIN; | 675 | return ERR_PTR(-EAGAIN); |
690 | } | 676 | } |
691 | } | 677 | } |
692 | spin_unlock_bh(&pool->sp_lock); | 678 | spin_unlock_bh(&pool->sp_lock); |
679 | return xprt; | ||
680 | } | ||
681 | |||
682 | void svc_add_new_temp_xprt(struct svc_serv *serv, struct svc_xprt *newxpt) | ||
683 | { | ||
684 | spin_lock_bh(&serv->sv_lock); | ||
685 | set_bit(XPT_TEMP, &newxpt->xpt_flags); | ||
686 | list_add(&newxpt->xpt_list, &serv->sv_tempsocks); | ||
687 | serv->sv_tmpcnt++; | ||
688 | if (serv->sv_temptimer.function == NULL) { | ||
689 | /* setup timer to age temp transports */ | ||
690 | setup_timer(&serv->sv_temptimer, svc_age_temp_xprts, | ||
691 | (unsigned long)serv); | ||
692 | mod_timer(&serv->sv_temptimer, | ||
693 | jiffies + svc_conn_age_period * HZ); | ||
694 | } | ||
695 | spin_unlock_bh(&serv->sv_lock); | ||
696 | svc_xprt_received(newxpt); | ||
697 | } | ||
698 | |||
699 | static int svc_handle_xprt(struct svc_rqst *rqstp, struct svc_xprt *xprt) | ||
700 | { | ||
701 | struct svc_serv *serv = rqstp->rq_server; | ||
702 | int len = 0; | ||
693 | 703 | ||
694 | len = 0; | ||
695 | if (test_bit(XPT_CLOSE, &xprt->xpt_flags)) { | 704 | if (test_bit(XPT_CLOSE, &xprt->xpt_flags)) { |
696 | dprintk("svc_recv: found XPT_CLOSE\n"); | 705 | dprintk("svc_recv: found XPT_CLOSE\n"); |
697 | svc_delete_xprt(xprt); | 706 | svc_delete_xprt(xprt); |
698 | /* Leave XPT_BUSY set on the dead xprt: */ | 707 | /* Leave XPT_BUSY set on the dead xprt: */ |
699 | goto out; | 708 | return 0; |
700 | } | 709 | } |
701 | if (test_bit(XPT_LISTENER, &xprt->xpt_flags)) { | 710 | if (test_bit(XPT_LISTENER, &xprt->xpt_flags)) { |
702 | struct svc_xprt *newxpt; | 711 | struct svc_xprt *newxpt; |
712 | /* | ||
713 | * We know this module_get will succeed because the | ||
714 | * listener holds a reference too | ||
715 | */ | ||
716 | __module_get(xprt->xpt_class->xcl_owner); | ||
717 | svc_check_conn_limits(xprt->xpt_server); | ||
703 | newxpt = xprt->xpt_ops->xpo_accept(xprt); | 718 | newxpt = xprt->xpt_ops->xpo_accept(xprt); |
704 | if (newxpt) { | 719 | if (newxpt) |
705 | /* | 720 | svc_add_new_temp_xprt(serv, newxpt); |
706 | * We know this module_get will succeed because the | ||
707 | * listener holds a reference too | ||
708 | */ | ||
709 | __module_get(newxpt->xpt_class->xcl_owner); | ||
710 | svc_check_conn_limits(xprt->xpt_server); | ||
711 | spin_lock_bh(&serv->sv_lock); | ||
712 | set_bit(XPT_TEMP, &newxpt->xpt_flags); | ||
713 | list_add(&newxpt->xpt_list, &serv->sv_tempsocks); | ||
714 | serv->sv_tmpcnt++; | ||
715 | if (serv->sv_temptimer.function == NULL) { | ||
716 | /* setup timer to age temp transports */ | ||
717 | setup_timer(&serv->sv_temptimer, | ||
718 | svc_age_temp_xprts, | ||
719 | (unsigned long)serv); | ||
720 | mod_timer(&serv->sv_temptimer, | ||
721 | jiffies + svc_conn_age_period * HZ); | ||
722 | } | ||
723 | spin_unlock_bh(&serv->sv_lock); | ||
724 | svc_xprt_received(newxpt); | ||
725 | } | ||
726 | } else if (xprt->xpt_ops->xpo_has_wspace(xprt)) { | 721 | } else if (xprt->xpt_ops->xpo_has_wspace(xprt)) { |
722 | /* XPT_DATA|XPT_DEFERRED case: */ | ||
727 | dprintk("svc: server %p, pool %u, transport %p, inuse=%d\n", | 723 | dprintk("svc: server %p, pool %u, transport %p, inuse=%d\n", |
728 | rqstp, pool->sp_id, xprt, | 724 | rqstp, rqstp->rq_pool->sp_id, xprt, |
729 | atomic_read(&xprt->xpt_ref.refcount)); | 725 | atomic_read(&xprt->xpt_ref.refcount)); |
730 | rqstp->rq_deferred = svc_deferred_dequeue(xprt); | 726 | rqstp->rq_deferred = svc_deferred_dequeue(xprt); |
731 | if (rqstp->rq_deferred) | 727 | if (rqstp->rq_deferred) |
@@ -736,10 +732,51 @@ int svc_recv(struct svc_rqst *rqstp, long timeout) | |||
736 | rqstp->rq_reserved = serv->sv_max_mesg; | 732 | rqstp->rq_reserved = serv->sv_max_mesg; |
737 | atomic_add(rqstp->rq_reserved, &xprt->xpt_reserved); | 733 | atomic_add(rqstp->rq_reserved, &xprt->xpt_reserved); |
738 | } | 734 | } |
735 | /* clear XPT_BUSY: */ | ||
739 | svc_xprt_received(xprt); | 736 | svc_xprt_received(xprt); |
737 | return len; | ||
738 | } | ||
739 | |||
740 | /* | ||
741 | * Receive the next request on any transport. This code is carefully | ||
742 | * organised not to touch any cachelines in the shared svc_serv | ||
743 | * structure, only cachelines in the local svc_pool. | ||
744 | */ | ||
745 | int svc_recv(struct svc_rqst *rqstp, long timeout) | ||
746 | { | ||
747 | struct svc_xprt *xprt = NULL; | ||
748 | struct svc_serv *serv = rqstp->rq_server; | ||
749 | int len, err; | ||
750 | |||
751 | dprintk("svc: server %p waiting for data (to = %ld)\n", | ||
752 | rqstp, timeout); | ||
753 | |||
754 | if (rqstp->rq_xprt) | ||
755 | printk(KERN_ERR | ||
756 | "svc_recv: service %p, transport not NULL!\n", | ||
757 | rqstp); | ||
758 | if (waitqueue_active(&rqstp->rq_wait)) | ||
759 | printk(KERN_ERR | ||
760 | "svc_recv: service %p, wait queue active!\n", | ||
761 | rqstp); | ||
762 | |||
763 | err = svc_alloc_arg(rqstp); | ||
764 | if (err) | ||
765 | return err; | ||
766 | |||
767 | try_to_freeze(); | ||
768 | cond_resched(); | ||
769 | if (signalled() || kthread_should_stop()) | ||
770 | return -EINTR; | ||
771 | |||
772 | xprt = svc_get_next_xprt(rqstp, timeout); | ||
773 | if (IS_ERR(xprt)) | ||
774 | return PTR_ERR(xprt); | ||
775 | |||
776 | len = svc_handle_xprt(rqstp, xprt); | ||
740 | 777 | ||
741 | /* No data, incomplete (TCP) read, or accept() */ | 778 | /* No data, incomplete (TCP) read, or accept() */ |
742 | if (len == 0 || len == -EAGAIN) | 779 | if (len <= 0) |
743 | goto out; | 780 | goto out; |
744 | 781 | ||
745 | clear_bit(XPT_OLD, &xprt->xpt_flags); | 782 | clear_bit(XPT_OLD, &xprt->xpt_flags); |
@@ -917,16 +954,18 @@ void svc_close_xprt(struct svc_xprt *xprt) | |||
917 | } | 954 | } |
918 | EXPORT_SYMBOL_GPL(svc_close_xprt); | 955 | EXPORT_SYMBOL_GPL(svc_close_xprt); |
919 | 956 | ||
920 | static void svc_close_list(struct list_head *xprt_list, struct net *net) | 957 | static void svc_close_list(struct svc_serv *serv, struct list_head *xprt_list, struct net *net) |
921 | { | 958 | { |
922 | struct svc_xprt *xprt; | 959 | struct svc_xprt *xprt; |
923 | 960 | ||
961 | spin_lock(&serv->sv_lock); | ||
924 | list_for_each_entry(xprt, xprt_list, xpt_list) { | 962 | list_for_each_entry(xprt, xprt_list, xpt_list) { |
925 | if (xprt->xpt_net != net) | 963 | if (xprt->xpt_net != net) |
926 | continue; | 964 | continue; |
927 | set_bit(XPT_CLOSE, &xprt->xpt_flags); | 965 | set_bit(XPT_CLOSE, &xprt->xpt_flags); |
928 | set_bit(XPT_BUSY, &xprt->xpt_flags); | 966 | set_bit(XPT_BUSY, &xprt->xpt_flags); |
929 | } | 967 | } |
968 | spin_unlock(&serv->sv_lock); | ||
930 | } | 969 | } |
931 | 970 | ||
932 | static void svc_clear_pools(struct svc_serv *serv, struct net *net) | 971 | static void svc_clear_pools(struct svc_serv *serv, struct net *net) |
@@ -949,24 +988,28 @@ static void svc_clear_pools(struct svc_serv *serv, struct net *net) | |||
949 | } | 988 | } |
950 | } | 989 | } |
951 | 990 | ||
952 | static void svc_clear_list(struct list_head *xprt_list, struct net *net) | 991 | static void svc_clear_list(struct svc_serv *serv, struct list_head *xprt_list, struct net *net) |
953 | { | 992 | { |
954 | struct svc_xprt *xprt; | 993 | struct svc_xprt *xprt; |
955 | struct svc_xprt *tmp; | 994 | struct svc_xprt *tmp; |
995 | LIST_HEAD(victims); | ||
956 | 996 | ||
997 | spin_lock(&serv->sv_lock); | ||
957 | list_for_each_entry_safe(xprt, tmp, xprt_list, xpt_list) { | 998 | list_for_each_entry_safe(xprt, tmp, xprt_list, xpt_list) { |
958 | if (xprt->xpt_net != net) | 999 | if (xprt->xpt_net != net) |
959 | continue; | 1000 | continue; |
960 | svc_delete_xprt(xprt); | 1001 | list_move(&xprt->xpt_list, &victims); |
961 | } | 1002 | } |
962 | list_for_each_entry(xprt, xprt_list, xpt_list) | 1003 | spin_unlock(&serv->sv_lock); |
963 | BUG_ON(xprt->xpt_net == net); | 1004 | |
1005 | list_for_each_entry_safe(xprt, tmp, &victims, xpt_list) | ||
1006 | svc_delete_xprt(xprt); | ||
964 | } | 1007 | } |
965 | 1008 | ||
966 | void svc_close_net(struct svc_serv *serv, struct net *net) | 1009 | void svc_close_net(struct svc_serv *serv, struct net *net) |
967 | { | 1010 | { |
968 | svc_close_list(&serv->sv_tempsocks, net); | 1011 | svc_close_list(serv, &serv->sv_tempsocks, net); |
969 | svc_close_list(&serv->sv_permsocks, net); | 1012 | svc_close_list(serv, &serv->sv_permsocks, net); |
970 | 1013 | ||
971 | svc_clear_pools(serv, net); | 1014 | svc_clear_pools(serv, net); |
972 | /* | 1015 | /* |
@@ -974,8 +1017,8 @@ void svc_close_net(struct svc_serv *serv, struct net *net) | |||
974 | * svc_xprt_enqueue will not add new entries without taking the | 1017 | * svc_xprt_enqueue will not add new entries without taking the |
975 | * sp_lock and checking XPT_BUSY. | 1018 | * sp_lock and checking XPT_BUSY. |
976 | */ | 1019 | */ |
977 | svc_clear_list(&serv->sv_tempsocks, net); | 1020 | svc_clear_list(serv, &serv->sv_tempsocks, net); |
978 | svc_clear_list(&serv->sv_permsocks, net); | 1021 | svc_clear_list(serv, &serv->sv_permsocks, net); |
979 | } | 1022 | } |
980 | 1023 | ||
981 | /* | 1024 | /* |
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index 998aa8c1807c..03827cef1fa7 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c | |||
@@ -59,7 +59,7 @@ | |||
59 | 59 | ||
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 *errp, int flags); | 62 | int flags); |
63 | static void svc_udp_data_ready(struct sock *, int); | 63 | static void svc_udp_data_ready(struct sock *, int); |
64 | static int svc_udp_recvfrom(struct svc_rqst *); | 64 | static int svc_udp_recvfrom(struct svc_rqst *); |
65 | static int svc_udp_sendto(struct svc_rqst *); | 65 | static int svc_udp_sendto(struct svc_rqst *); |
@@ -305,57 +305,6 @@ static int svc_one_sock_name(struct svc_sock *svsk, char *buf, int remaining) | |||
305 | return len; | 305 | return len; |
306 | } | 306 | } |
307 | 307 | ||
308 | /** | ||
309 | * svc_sock_names - construct a list of listener names in a string | ||
310 | * @serv: pointer to RPC service | ||
311 | * @buf: pointer to a buffer to fill in with socket names | ||
312 | * @buflen: size of the buffer to be filled | ||
313 | * @toclose: pointer to '\0'-terminated C string containing the name | ||
314 | * of a listener to be closed | ||
315 | * | ||
316 | * Fills in @buf with a '\n'-separated list of names of listener | ||
317 | * sockets. If @toclose is not NULL, the socket named by @toclose | ||
318 | * is closed, and is not included in the output list. | ||
319 | * | ||
320 | * Returns positive length of the socket name string, or a negative | ||
321 | * errno value on error. | ||
322 | */ | ||
323 | int svc_sock_names(struct svc_serv *serv, char *buf, const size_t buflen, | ||
324 | const char *toclose) | ||
325 | { | ||
326 | struct svc_sock *svsk, *closesk = NULL; | ||
327 | int len = 0; | ||
328 | |||
329 | if (!serv) | ||
330 | return 0; | ||
331 | |||
332 | spin_lock_bh(&serv->sv_lock); | ||
333 | list_for_each_entry(svsk, &serv->sv_permsocks, sk_xprt.xpt_list) { | ||
334 | int onelen = svc_one_sock_name(svsk, buf + len, buflen - len); | ||
335 | if (onelen < 0) { | ||
336 | len = onelen; | ||
337 | break; | ||
338 | } | ||
339 | if (toclose && strcmp(toclose, buf + len) == 0) { | ||
340 | closesk = svsk; | ||
341 | svc_xprt_get(&closesk->sk_xprt); | ||
342 | } else | ||
343 | len += onelen; | ||
344 | } | ||
345 | spin_unlock_bh(&serv->sv_lock); | ||
346 | |||
347 | if (closesk) { | ||
348 | /* Should unregister with portmap, but you cannot | ||
349 | * unregister just one protocol... | ||
350 | */ | ||
351 | svc_close_xprt(&closesk->sk_xprt); | ||
352 | svc_xprt_put(&closesk->sk_xprt); | ||
353 | } else if (toclose) | ||
354 | return -ENOENT; | ||
355 | return len; | ||
356 | } | ||
357 | EXPORT_SYMBOL_GPL(svc_sock_names); | ||
358 | |||
359 | /* | 308 | /* |
360 | * Check input queue length | 309 | * Check input queue length |
361 | */ | 310 | */ |
@@ -598,11 +547,9 @@ static int svc_udp_recvfrom(struct svc_rqst *rqstp) | |||
598 | dprintk("svc: recvfrom returned error %d\n", -err); | 547 | dprintk("svc: recvfrom returned error %d\n", -err); |
599 | set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags); | 548 | set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags); |
600 | } | 549 | } |
601 | return -EAGAIN; | 550 | return 0; |
602 | } | 551 | } |
603 | len = svc_addr_len(svc_addr(rqstp)); | 552 | len = svc_addr_len(svc_addr(rqstp)); |
604 | if (len == 0) | ||
605 | return -EAFNOSUPPORT; | ||
606 | rqstp->rq_addrlen = len; | 553 | rqstp->rq_addrlen = len; |
607 | if (skb->tstamp.tv64 == 0) { | 554 | if (skb->tstamp.tv64 == 0) { |
608 | skb->tstamp = ktime_get_real(); | 555 | skb->tstamp = ktime_get_real(); |
@@ -620,10 +567,7 @@ static int svc_udp_recvfrom(struct svc_rqst *rqstp) | |||
620 | if (!svc_udp_get_dest_address(rqstp, cmh)) { | 567 | if (!svc_udp_get_dest_address(rqstp, cmh)) { |
621 | net_warn_ratelimited("svc: received unknown control message %d/%d; dropping RPC reply datagram\n", | 568 | net_warn_ratelimited("svc: received unknown control message %d/%d; dropping RPC reply datagram\n", |
622 | cmh->cmsg_level, cmh->cmsg_type); | 569 | cmh->cmsg_level, cmh->cmsg_type); |
623 | out_free: | 570 | goto out_free; |
624 | trace_kfree_skb(skb, svc_udp_recvfrom); | ||
625 | skb_free_datagram_locked(svsk->sk_sk, skb); | ||
626 | return 0; | ||
627 | } | 571 | } |
628 | rqstp->rq_daddrlen = svc_addr_len(svc_daddr(rqstp)); | 572 | rqstp->rq_daddrlen = svc_addr_len(svc_daddr(rqstp)); |
629 | 573 | ||
@@ -662,6 +606,10 @@ out_free: | |||
662 | serv->sv_stats->netudpcnt++; | 606 | serv->sv_stats->netudpcnt++; |
663 | 607 | ||
664 | return len; | 608 | return len; |
609 | out_free: | ||
610 | trace_kfree_skb(skb, svc_udp_recvfrom); | ||
611 | skb_free_datagram_locked(svsk->sk_sk, skb); | ||
612 | return 0; | ||
665 | } | 613 | } |
666 | 614 | ||
667 | static int | 615 | static int |
@@ -900,8 +848,9 @@ static struct svc_xprt *svc_tcp_accept(struct svc_xprt *xprt) | |||
900 | */ | 848 | */ |
901 | newsock->sk->sk_sndtimeo = HZ*30; | 849 | newsock->sk->sk_sndtimeo = HZ*30; |
902 | 850 | ||
903 | if (!(newsvsk = svc_setup_socket(serv, newsock, &err, | 851 | newsvsk = svc_setup_socket(serv, newsock, |
904 | (SVC_SOCK_ANONYMOUS | SVC_SOCK_TEMPORARY)))) | 852 | (SVC_SOCK_ANONYMOUS | SVC_SOCK_TEMPORARY)); |
853 | if (IS_ERR(newsvsk)) | ||
905 | goto failed; | 854 | goto failed; |
906 | svc_xprt_set_remote(&newsvsk->sk_xprt, sin, slen); | 855 | svc_xprt_set_remote(&newsvsk->sk_xprt, sin, slen); |
907 | err = kernel_getsockname(newsock, sin, &slen); | 856 | err = kernel_getsockname(newsock, sin, &slen); |
@@ -1174,13 +1123,13 @@ error: | |||
1174 | if (len != -EAGAIN) | 1123 | if (len != -EAGAIN) |
1175 | goto err_other; | 1124 | goto err_other; |
1176 | dprintk("RPC: TCP recvfrom got EAGAIN\n"); | 1125 | dprintk("RPC: TCP recvfrom got EAGAIN\n"); |
1177 | return -EAGAIN; | 1126 | return 0; |
1178 | err_other: | 1127 | err_other: |
1179 | printk(KERN_NOTICE "%s: recvfrom returned errno %d\n", | 1128 | printk(KERN_NOTICE "%s: recvfrom returned errno %d\n", |
1180 | svsk->sk_xprt.xpt_server->sv_name, -len); | 1129 | svsk->sk_xprt.xpt_server->sv_name, -len); |
1181 | set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags); | 1130 | set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags); |
1182 | err_noclose: | 1131 | err_noclose: |
1183 | return -EAGAIN; /* record not complete */ | 1132 | return 0; /* record not complete */ |
1184 | } | 1133 | } |
1185 | 1134 | ||
1186 | /* | 1135 | /* |
@@ -1383,29 +1332,29 @@ EXPORT_SYMBOL_GPL(svc_sock_update_bufs); | |||
1383 | */ | 1332 | */ |
1384 | static struct svc_sock *svc_setup_socket(struct svc_serv *serv, | 1333 | static struct svc_sock *svc_setup_socket(struct svc_serv *serv, |
1385 | struct socket *sock, | 1334 | struct socket *sock, |
1386 | int *errp, int flags) | 1335 | int flags) |
1387 | { | 1336 | { |
1388 | struct svc_sock *svsk; | 1337 | struct svc_sock *svsk; |
1389 | struct sock *inet; | 1338 | struct sock *inet; |
1390 | int pmap_register = !(flags & SVC_SOCK_ANONYMOUS); | 1339 | int pmap_register = !(flags & SVC_SOCK_ANONYMOUS); |
1340 | int err = 0; | ||
1391 | 1341 | ||
1392 | dprintk("svc: svc_setup_socket %p\n", sock); | 1342 | dprintk("svc: svc_setup_socket %p\n", sock); |
1393 | if (!(svsk = kzalloc(sizeof(*svsk), GFP_KERNEL))) { | 1343 | svsk = kzalloc(sizeof(*svsk), GFP_KERNEL); |
1394 | *errp = -ENOMEM; | 1344 | if (!svsk) |
1395 | return NULL; | 1345 | return ERR_PTR(-ENOMEM); |
1396 | } | ||
1397 | 1346 | ||
1398 | inet = sock->sk; | 1347 | inet = sock->sk; |
1399 | 1348 | ||
1400 | /* Register socket with portmapper */ | 1349 | /* Register socket with portmapper */ |
1401 | if (*errp >= 0 && pmap_register) | 1350 | if (pmap_register) |
1402 | *errp = svc_register(serv, sock_net(sock->sk), inet->sk_family, | 1351 | err = svc_register(serv, sock_net(sock->sk), inet->sk_family, |
1403 | inet->sk_protocol, | 1352 | inet->sk_protocol, |
1404 | ntohs(inet_sk(inet)->inet_sport)); | 1353 | ntohs(inet_sk(inet)->inet_sport)); |
1405 | 1354 | ||
1406 | if (*errp < 0) { | 1355 | if (err < 0) { |
1407 | kfree(svsk); | 1356 | kfree(svsk); |
1408 | return NULL; | 1357 | return ERR_PTR(err); |
1409 | } | 1358 | } |
1410 | 1359 | ||
1411 | inet->sk_user_data = svsk; | 1360 | inet->sk_user_data = svsk; |
@@ -1450,42 +1399,38 @@ int svc_addsock(struct svc_serv *serv, const int fd, char *name_return, | |||
1450 | int err = 0; | 1399 | int err = 0; |
1451 | struct socket *so = sockfd_lookup(fd, &err); | 1400 | struct socket *so = sockfd_lookup(fd, &err); |
1452 | struct svc_sock *svsk = NULL; | 1401 | struct svc_sock *svsk = NULL; |
1402 | struct sockaddr_storage addr; | ||
1403 | struct sockaddr *sin = (struct sockaddr *)&addr; | ||
1404 | int salen; | ||
1453 | 1405 | ||
1454 | if (!so) | 1406 | if (!so) |
1455 | return err; | 1407 | return err; |
1408 | err = -EAFNOSUPPORT; | ||
1456 | if ((so->sk->sk_family != PF_INET) && (so->sk->sk_family != PF_INET6)) | 1409 | if ((so->sk->sk_family != PF_INET) && (so->sk->sk_family != PF_INET6)) |
1457 | err = -EAFNOSUPPORT; | 1410 | goto out; |
1458 | else if (so->sk->sk_protocol != IPPROTO_TCP && | 1411 | err = -EPROTONOSUPPORT; |
1412 | if (so->sk->sk_protocol != IPPROTO_TCP && | ||
1459 | so->sk->sk_protocol != IPPROTO_UDP) | 1413 | so->sk->sk_protocol != IPPROTO_UDP) |
1460 | err = -EPROTONOSUPPORT; | 1414 | goto out; |
1461 | else if (so->state > SS_UNCONNECTED) | 1415 | err = -EISCONN; |
1462 | err = -EISCONN; | 1416 | if (so->state > SS_UNCONNECTED) |
1463 | else { | 1417 | goto out; |
1464 | if (!try_module_get(THIS_MODULE)) | 1418 | err = -ENOENT; |
1465 | err = -ENOENT; | 1419 | if (!try_module_get(THIS_MODULE)) |
1466 | else | 1420 | goto out; |
1467 | svsk = svc_setup_socket(serv, so, &err, | 1421 | svsk = svc_setup_socket(serv, so, SVC_SOCK_DEFAULTS); |
1468 | SVC_SOCK_DEFAULTS); | 1422 | if (IS_ERR(svsk)) { |
1469 | if (svsk) { | 1423 | module_put(THIS_MODULE); |
1470 | struct sockaddr_storage addr; | 1424 | err = PTR_ERR(svsk); |
1471 | struct sockaddr *sin = (struct sockaddr *)&addr; | 1425 | goto out; |
1472 | int salen; | ||
1473 | if (kernel_getsockname(svsk->sk_sock, sin, &salen) == 0) | ||
1474 | svc_xprt_set_local(&svsk->sk_xprt, sin, salen); | ||
1475 | clear_bit(XPT_TEMP, &svsk->sk_xprt.xpt_flags); | ||
1476 | spin_lock_bh(&serv->sv_lock); | ||
1477 | list_add(&svsk->sk_xprt.xpt_list, &serv->sv_permsocks); | ||
1478 | spin_unlock_bh(&serv->sv_lock); | ||
1479 | svc_xprt_received(&svsk->sk_xprt); | ||
1480 | err = 0; | ||
1481 | } else | ||
1482 | module_put(THIS_MODULE); | ||
1483 | } | ||
1484 | if (err) { | ||
1485 | sockfd_put(so); | ||
1486 | return err; | ||
1487 | } | 1426 | } |
1427 | if (kernel_getsockname(svsk->sk_sock, sin, &salen) == 0) | ||
1428 | svc_xprt_set_local(&svsk->sk_xprt, sin, salen); | ||
1429 | svc_add_new_perm_xprt(serv, &svsk->sk_xprt); | ||
1488 | return svc_one_sock_name(svsk, name_return, len); | 1430 | return svc_one_sock_name(svsk, name_return, len); |
1431 | out: | ||
1432 | sockfd_put(so); | ||
1433 | return err; | ||
1489 | } | 1434 | } |
1490 | EXPORT_SYMBOL_GPL(svc_addsock); | 1435 | EXPORT_SYMBOL_GPL(svc_addsock); |
1491 | 1436 | ||
@@ -1563,11 +1508,13 @@ static struct svc_xprt *svc_create_socket(struct svc_serv *serv, | |||
1563 | goto bummer; | 1508 | goto bummer; |
1564 | } | 1509 | } |
1565 | 1510 | ||
1566 | if ((svsk = svc_setup_socket(serv, sock, &error, flags)) != NULL) { | 1511 | svsk = svc_setup_socket(serv, sock, flags); |
1567 | svc_xprt_set_local(&svsk->sk_xprt, newsin, newlen); | 1512 | if (IS_ERR(svsk)) { |
1568 | return (struct svc_xprt *)svsk; | 1513 | error = PTR_ERR(svsk); |
1514 | goto bummer; | ||
1569 | } | 1515 | } |
1570 | 1516 | svc_xprt_set_local(&svsk->sk_xprt, newsin, newlen); | |
1517 | return (struct svc_xprt *)svsk; | ||
1571 | bummer: | 1518 | bummer: |
1572 | dprintk("svc: svc_create_socket error = %d\n", -error); | 1519 | dprintk("svc: svc_create_socket error = %d\n", -error); |
1573 | sock_release(sock); | 1520 | sock_release(sock); |
diff --git a/net/sunrpc/xprtrdma/svc_rdma_transport.c b/net/sunrpc/xprtrdma/svc_rdma_transport.c index 73b428bef598..62e4f9bcc387 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_transport.c +++ b/net/sunrpc/xprtrdma/svc_rdma_transport.c | |||
@@ -578,10 +578,6 @@ static void handle_connect_req(struct rdma_cm_id *new_cma_id, size_t client_ird) | |||
578 | list_add_tail(&newxprt->sc_accept_q, &listen_xprt->sc_accept_q); | 578 | list_add_tail(&newxprt->sc_accept_q, &listen_xprt->sc_accept_q); |
579 | spin_unlock_bh(&listen_xprt->sc_lock); | 579 | spin_unlock_bh(&listen_xprt->sc_lock); |
580 | 580 | ||
581 | /* | ||
582 | * Can't use svc_xprt_received here because we are not on a | ||
583 | * rqstp thread | ||
584 | */ | ||
585 | set_bit(XPT_CONN, &listen_xprt->sc_xprt.xpt_flags); | 581 | set_bit(XPT_CONN, &listen_xprt->sc_xprt.xpt_flags); |
586 | svc_xprt_enqueue(&listen_xprt->sc_xprt); | 582 | svc_xprt_enqueue(&listen_xprt->sc_xprt); |
587 | } | 583 | } |