|
@@ -621,121 +621,29 @@ static int rfcomm_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
|
|
|
return sent;
|
|
|
}
|
|
|
|
|
|
-static long rfcomm_sock_data_wait(struct sock *sk, long timeo)
|
|
|
-{
|
|
|
- DECLARE_WAITQUEUE(wait, current);
|
|
|
-
|
|
|
- add_wait_queue(sk_sleep(sk), &wait);
|
|
|
- for (;;) {
|
|
|
- set_current_state(TASK_INTERRUPTIBLE);
|
|
|
-
|
|
|
- if (!skb_queue_empty(&sk->sk_receive_queue) ||
|
|
|
- sk->sk_err ||
|
|
|
- (sk->sk_shutdown & RCV_SHUTDOWN) ||
|
|
|
- signal_pending(current) ||
|
|
|
- !timeo)
|
|
|
- break;
|
|
|
-
|
|
|
- set_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
|
|
|
- release_sock(sk);
|
|
|
- timeo = schedule_timeout(timeo);
|
|
|
- lock_sock(sk);
|
|
|
- clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
|
|
|
- }
|
|
|
-
|
|
|
- __set_current_state(TASK_RUNNING);
|
|
|
- remove_wait_queue(sk_sleep(sk), &wait);
|
|
|
- return timeo;
|
|
|
-}
|
|
|
-
|
|
|
static int rfcomm_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
|
|
|
struct msghdr *msg, size_t size, int flags)
|
|
|
{
|
|
|
struct sock *sk = sock->sk;
|
|
|
struct rfcomm_dlc *d = rfcomm_pi(sk)->dlc;
|
|
|
- int err = 0;
|
|
|
- size_t target, copied = 0;
|
|
|
- long timeo;
|
|
|
+ int len;
|
|
|
|
|
|
if (test_and_clear_bit(RFCOMM_DEFER_SETUP, &d->flags)) {
|
|
|
rfcomm_dlc_accept(d);
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
- if (flags & MSG_OOB)
|
|
|
- return -EOPNOTSUPP;
|
|
|
-
|
|
|
- msg->msg_namelen = 0;
|
|
|
-
|
|
|
- BT_DBG("sk %p size %zu", sk, size);
|
|
|
+ len = bt_sock_stream_recvmsg(iocb, sock, msg, size, flags);
|
|
|
|
|
|
lock_sock(sk);
|
|
|
+ if (!(flags & MSG_PEEK) && len > 0)
|
|
|
+ atomic_sub(len, &sk->sk_rmem_alloc);
|
|
|
|
|
|
- target = sock_rcvlowat(sk, flags & MSG_WAITALL, size);
|
|
|
- timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
|
|
|
-
|
|
|
- do {
|
|
|
- struct sk_buff *skb;
|
|
|
- int chunk;
|
|
|
-
|
|
|
- skb = skb_dequeue(&sk->sk_receive_queue);
|
|
|
- if (!skb) {
|
|
|
- if (copied >= target)
|
|
|
- break;
|
|
|
-
|
|
|
- if ((err = sock_error(sk)) != 0)
|
|
|
- break;
|
|
|
- if (sk->sk_shutdown & RCV_SHUTDOWN)
|
|
|
- break;
|
|
|
-
|
|
|
- err = -EAGAIN;
|
|
|
- if (!timeo)
|
|
|
- break;
|
|
|
-
|
|
|
- timeo = rfcomm_sock_data_wait(sk, timeo);
|
|
|
-
|
|
|
- if (signal_pending(current)) {
|
|
|
- err = sock_intr_errno(timeo);
|
|
|
- goto out;
|
|
|
- }
|
|
|
- continue;
|
|
|
- }
|
|
|
-
|
|
|
- chunk = min_t(unsigned int, skb->len, size);
|
|
|
- if (memcpy_toiovec(msg->msg_iov, skb->data, chunk)) {
|
|
|
- skb_queue_head(&sk->sk_receive_queue, skb);
|
|
|
- if (!copied)
|
|
|
- copied = -EFAULT;
|
|
|
- break;
|
|
|
- }
|
|
|
- copied += chunk;
|
|
|
- size -= chunk;
|
|
|
-
|
|
|
- sock_recv_ts_and_drops(msg, sk, skb);
|
|
|
-
|
|
|
- if (!(flags & MSG_PEEK)) {
|
|
|
- atomic_sub(chunk, &sk->sk_rmem_alloc);
|
|
|
-
|
|
|
- skb_pull(skb, chunk);
|
|
|
- if (skb->len) {
|
|
|
- skb_queue_head(&sk->sk_receive_queue, skb);
|
|
|
- break;
|
|
|
- }
|
|
|
- kfree_skb(skb);
|
|
|
-
|
|
|
- } else {
|
|
|
- /* put message back and return */
|
|
|
- skb_queue_head(&sk->sk_receive_queue, skb);
|
|
|
- break;
|
|
|
- }
|
|
|
- } while (size);
|
|
|
-
|
|
|
-out:
|
|
|
if (atomic_read(&sk->sk_rmem_alloc) <= (sk->sk_rcvbuf >> 2))
|
|
|
rfcomm_dlc_unthrottle(rfcomm_pi(sk)->dlc);
|
|
|
-
|
|
|
release_sock(sk);
|
|
|
- return copied ? : err;
|
|
|
+
|
|
|
+ return len;
|
|
|
}
|
|
|
|
|
|
static int rfcomm_sock_setsockopt_old(struct socket *sock, int optname, char __user *optval, unsigned int optlen)
|