Skip to content

Commit

Permalink
Bluetooth: Handle fragmented skbs in bt_sock_stream_recvmsg()
Browse files Browse the repository at this point in the history
ERTM reassembly will be more efficient when skbs are linked together
rather than copying every incoming data byte. The existing stream recv
function assumes skbs are linear, so it needs to know how to handle
fragments before reassembly is changed.

bt_sock_recvmsg() already handles fragmented skbs.

Signed-off-by: Mat Martineau <mathewm@codeaurora.org>
Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
  • Loading branch information
Mat Martineau authored and Gustavo F. Padovan committed Sep 27, 2011
1 parent 4493572 commit 5b668eb
Showing 1 changed file with 28 additions and 2 deletions.
30 changes: 28 additions & 2 deletions net/bluetooth/af_bluetooth.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down

0 comments on commit 5b668eb

Please sign in to comment.