diff options
author | Mat Martineau <mathewm@codeaurora.org> | 2010-09-08 13:05:28 -0400 |
---|---|---|
committer | Gustavo F. Padovan <padovan@profusion.mobi> | 2010-10-12 11:44:51 -0400 |
commit | 3d7d01dffec4a6757ed1e3182f01c7ef5caa2539 (patch) | |
tree | 0903ad1ffcf4378fd5f3d33716fc37d7059998b0 | |
parent | 796c86eec84ddfd02281c5071838ed1fefda6b90 (diff) |
Bluetooth: Use common SOCK_STREAM receive code in RFCOMM
To reduce code duplication, have rfcomm_sock_recvmsg() call
bt_sock_stream_recvmsg(). The common bt_sock_stream_recvmsg()
code is nearly identical, with the RFCOMM-specific functionality
for deferred setup and connection unthrottling left in
rfcomm_sock_recvmsg().
Signed-off-by: Mat Martineau <mathewm@codeaurora.org>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
-rw-r--r-- | net/bluetooth/rfcomm/sock.c | 104 |
1 files changed, 6 insertions, 98 deletions
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index 194b3a04cfd3..aec505f934df 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c | |||
@@ -621,121 +621,29 @@ static int rfcomm_sock_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
621 | return sent; | 621 | return sent; |
622 | } | 622 | } |
623 | 623 | ||
624 | static long rfcomm_sock_data_wait(struct sock *sk, long timeo) | ||
625 | { | ||
626 | DECLARE_WAITQUEUE(wait, current); | ||
627 | |||
628 | add_wait_queue(sk_sleep(sk), &wait); | ||
629 | for (;;) { | ||
630 | set_current_state(TASK_INTERRUPTIBLE); | ||
631 | |||
632 | if (!skb_queue_empty(&sk->sk_receive_queue) || | ||
633 | sk->sk_err || | ||
634 | (sk->sk_shutdown & RCV_SHUTDOWN) || | ||
635 | signal_pending(current) || | ||
636 | !timeo) | ||
637 | break; | ||
638 | |||
639 | set_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); | ||
640 | release_sock(sk); | ||
641 | timeo = schedule_timeout(timeo); | ||
642 | lock_sock(sk); | ||
643 | clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); | ||
644 | } | ||
645 | |||
646 | __set_current_state(TASK_RUNNING); | ||
647 | remove_wait_queue(sk_sleep(sk), &wait); | ||
648 | return timeo; | ||
649 | } | ||
650 | |||
651 | static int rfcomm_sock_recvmsg(struct kiocb *iocb, struct socket *sock, | 624 | static int rfcomm_sock_recvmsg(struct kiocb *iocb, struct socket *sock, |
652 | struct msghdr *msg, size_t size, int flags) | 625 | struct msghdr *msg, size_t size, int flags) |
653 | { | 626 | { |
654 | struct sock *sk = sock->sk; | 627 | struct sock *sk = sock->sk; |
655 | struct rfcomm_dlc *d = rfcomm_pi(sk)->dlc; | 628 | struct rfcomm_dlc *d = rfcomm_pi(sk)->dlc; |
656 | int err = 0; | 629 | int len; |
657 | size_t target, copied = 0; | ||
658 | long timeo; | ||
659 | 630 | ||
660 | if (test_and_clear_bit(RFCOMM_DEFER_SETUP, &d->flags)) { | 631 | if (test_and_clear_bit(RFCOMM_DEFER_SETUP, &d->flags)) { |
661 | rfcomm_dlc_accept(d); | 632 | rfcomm_dlc_accept(d); |
662 | return 0; | 633 | return 0; |
663 | } | 634 | } |
664 | 635 | ||
665 | if (flags & MSG_OOB) | 636 | len = bt_sock_stream_recvmsg(iocb, sock, msg, size, flags); |
666 | return -EOPNOTSUPP; | ||
667 | |||
668 | msg->msg_namelen = 0; | ||
669 | |||
670 | BT_DBG("sk %p size %zu", sk, size); | ||
671 | 637 | ||
672 | lock_sock(sk); | 638 | lock_sock(sk); |
639 | if (!(flags & MSG_PEEK) && len > 0) | ||
640 | atomic_sub(len, &sk->sk_rmem_alloc); | ||
673 | 641 | ||
674 | target = sock_rcvlowat(sk, flags & MSG_WAITALL, size); | ||
675 | timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT); | ||
676 | |||
677 | do { | ||
678 | struct sk_buff *skb; | ||
679 | int chunk; | ||
680 | |||
681 | skb = skb_dequeue(&sk->sk_receive_queue); | ||
682 | if (!skb) { | ||
683 | if (copied >= target) | ||
684 | break; | ||
685 | |||
686 | if ((err = sock_error(sk)) != 0) | ||
687 | break; | ||
688 | if (sk->sk_shutdown & RCV_SHUTDOWN) | ||
689 | break; | ||
690 | |||
691 | err = -EAGAIN; | ||
692 | if (!timeo) | ||
693 | break; | ||
694 | |||
695 | timeo = rfcomm_sock_data_wait(sk, timeo); | ||
696 | |||
697 | if (signal_pending(current)) { | ||
698 | err = sock_intr_errno(timeo); | ||
699 | goto out; | ||
700 | } | ||
701 | continue; | ||
702 | } | ||
703 | |||
704 | chunk = min_t(unsigned int, skb->len, size); | ||
705 | if (memcpy_toiovec(msg->msg_iov, skb->data, chunk)) { | ||
706 | skb_queue_head(&sk->sk_receive_queue, skb); | ||
707 | if (!copied) | ||
708 | copied = -EFAULT; | ||
709 | break; | ||
710 | } | ||
711 | copied += chunk; | ||
712 | size -= chunk; | ||
713 | |||
714 | sock_recv_ts_and_drops(msg, sk, skb); | ||
715 | |||
716 | if (!(flags & MSG_PEEK)) { | ||
717 | atomic_sub(chunk, &sk->sk_rmem_alloc); | ||
718 | |||
719 | skb_pull(skb, chunk); | ||
720 | if (skb->len) { | ||
721 | skb_queue_head(&sk->sk_receive_queue, skb); | ||
722 | break; | ||
723 | } | ||
724 | kfree_skb(skb); | ||
725 | |||
726 | } else { | ||
727 | /* put message back and return */ | ||
728 | skb_queue_head(&sk->sk_receive_queue, skb); | ||
729 | break; | ||
730 | } | ||
731 | } while (size); | ||
732 | |||
733 | out: | ||
734 | if (atomic_read(&sk->sk_rmem_alloc) <= (sk->sk_rcvbuf >> 2)) | 642 | if (atomic_read(&sk->sk_rmem_alloc) <= (sk->sk_rcvbuf >> 2)) |
735 | rfcomm_dlc_unthrottle(rfcomm_pi(sk)->dlc); | 643 | rfcomm_dlc_unthrottle(rfcomm_pi(sk)->dlc); |
736 | |||
737 | release_sock(sk); | 644 | release_sock(sk); |
738 | return copied ? : err; | 645 | |
646 | return len; | ||
739 | } | 647 | } |
740 | 648 | ||
741 | static int rfcomm_sock_setsockopt_old(struct socket *sock, int optname, char __user *optval, unsigned int optlen) | 649 | static int rfcomm_sock_setsockopt_old(struct socket *sock, int optname, char __user *optval, unsigned int optlen) |