aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/bluetooth/rfcomm/sock.c104
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
624static 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
651static int rfcomm_sock_recvmsg(struct kiocb *iocb, struct socket *sock, 624static 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
733out:
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
741static int rfcomm_sock_setsockopt_old(struct socket *sock, int optname, char __user *optval, unsigned int optlen) 649static int rfcomm_sock_setsockopt_old(struct socket *sock, int optname, char __user *optval, unsigned int optlen)