From deddf2418dd943df8c636cee0b8ce76132363833 Mon Sep 17 00:00:00 2001 From: Mat Martineau Date: Fri, 22 Jul 2011 14:53:59 -0700 Subject: [PATCH] --- yaml --- r: 266647 b: refs/heads/master c: 5b668eb3270f3f9c13ddf6e4fb57bf20c83dccff h: refs/heads/master i: 266645: 2574c9bec30abce1a177a4cf3744001b43331541 266643: 0a55de1fa8898d1f3250a99ad59d0ca33b481274 266639: 3045fedc4a07512a37e38c574d05c8b63ba48a0f v: v3 --- [refs] | 2 +- trunk/net/bluetooth/af_bluetooth.c | 30 ++++++++++++++++++++++++++++-- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/[refs] b/[refs] index bb0aaf223d44..3748b5f73406 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 449357200c5d73d80a9c42dee5dafed684b3cd17 +refs/heads/master: 5b668eb3270f3f9c13ddf6e4fb57bf20c83dccff diff --git a/trunk/net/bluetooth/af_bluetooth.c b/trunk/net/bluetooth/af_bluetooth.c index 117e0d161780..062124cd89cf 100644 --- a/trunk/net/bluetooth/af_bluetooth.c +++ b/trunk/net/bluetooth/af_bluetooth.c @@ -349,7 +349,7 @@ int bt_sock_stream_recvmsg(struct kiocb *iocb, struct socket *sock, } chunk = min_t(unsigned int, skb->len, size); - if (memcpy_toiovec(msg->msg_iov, skb->data, chunk)) { + if (skb_copy_datagram_iovec(skb, 0, msg->msg_iov, chunk)) { skb_queue_head(&sk->sk_receive_queue, skb); if (!copied) copied = -EFAULT; @@ -361,7 +361,33 @@ int bt_sock_stream_recvmsg(struct kiocb *iocb, struct socket *sock, sock_recv_ts_and_drops(msg, sk, skb); if (!(flags & MSG_PEEK)) { - skb_pull(skb, chunk); + int skb_len = skb_headlen(skb); + + if (chunk <= skb_len) { + __skb_pull(skb, chunk); + } else { + struct sk_buff *frag; + + __skb_pull(skb, skb_len); + chunk -= skb_len; + + skb_walk_frags(skb, frag) { + if (chunk <= frag->len) { + /* Pulling partial data */ + skb->len -= chunk; + skb->data_len -= chunk; + __skb_pull(frag, chunk); + break; + } else if (frag->len) { + /* Pulling all frag data */ + chunk -= frag->len; + skb->len -= frag->len; + skb->data_len -= frag->len; + __skb_pull(frag, frag->len); + } + } + } + if (skb->len) { skb_queue_head(&sk->sk_receive_queue, skb); break;