forked from Minki/linux
net: Walk fragments in __skb_splice_bits
Add walking of fragments in __skb_splice_bits. Signed-off-by: Tom Herbert <tom@herbertland.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
f092276d85
commit
fa9835e52e
@ -1918,6 +1918,7 @@ static bool __skb_splice_bits(struct sk_buff *skb, struct pipe_inode_info *pipe,
|
||||
struct splice_pipe_desc *spd, struct sock *sk)
|
||||
{
|
||||
int seg;
|
||||
struct sk_buff *iter;
|
||||
|
||||
/* map the linear part :
|
||||
* If skb->head_frag is set, this 'linear' part is backed by a
|
||||
@ -1944,6 +1945,19 @@ static bool __skb_splice_bits(struct sk_buff *skb, struct pipe_inode_info *pipe,
|
||||
return true;
|
||||
}
|
||||
|
||||
skb_walk_frags(skb, iter) {
|
||||
if (*offset >= iter->len) {
|
||||
*offset -= iter->len;
|
||||
continue;
|
||||
}
|
||||
/* __skb_splice_bits() only fails if the output has no room
|
||||
* left, so no point in going over the frag_list for the error
|
||||
* case.
|
||||
*/
|
||||
if (__skb_splice_bits(iter, pipe, offset, len, spd, sk))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1970,9 +1984,7 @@ ssize_t skb_socket_splice(struct sock *sk,
|
||||
|
||||
/*
|
||||
* Map data from the skb to a pipe. Should handle both the linear part,
|
||||
* the fragments, and the frag list. It does NOT handle frag lists within
|
||||
* the frag list, if such a thing exists. We'd probably need to recurse to
|
||||
* handle that cleanly.
|
||||
* the fragments, and the frag list.
|
||||
*/
|
||||
int skb_splice_bits(struct sk_buff *skb, struct sock *sk, unsigned int offset,
|
||||
struct pipe_inode_info *pipe, unsigned int tlen,
|
||||
@ -1991,29 +2003,10 @@ int skb_splice_bits(struct sk_buff *skb, struct sock *sk, unsigned int offset,
|
||||
.ops = &nosteal_pipe_buf_ops,
|
||||
.spd_release = sock_spd_release,
|
||||
};
|
||||
struct sk_buff *frag_iter;
|
||||
int ret = 0;
|
||||
|
||||
/*
|
||||
* __skb_splice_bits() only fails if the output has no room left,
|
||||
* so no point in going over the frag_list for the error case.
|
||||
*/
|
||||
if (__skb_splice_bits(skb, pipe, &offset, &tlen, &spd, sk))
|
||||
goto done;
|
||||
else if (!tlen)
|
||||
goto done;
|
||||
__skb_splice_bits(skb, pipe, &offset, &tlen, &spd, sk);
|
||||
|
||||
/*
|
||||
* now see if we have a frag_list to map
|
||||
*/
|
||||
skb_walk_frags(skb, frag_iter) {
|
||||
if (!tlen)
|
||||
break;
|
||||
if (__skb_splice_bits(frag_iter, pipe, &offset, &tlen, &spd, sk))
|
||||
break;
|
||||
}
|
||||
|
||||
done:
|
||||
if (spd.nr_pages)
|
||||
ret = splice_cb(sk, pipe, &spd);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user