forked from luck/tmp_suning_uos_patched
datagram: consolidate datagram copy to iter helpers
skb_copy_datagram_iter and skb_copy_and_csum_datagram are essentialy the same but with a couple of differences: The first is the copy operation used which either a simple copy or a csum_and_copy, and the second are the behavior on the "short copy" path where simply copy needs to return the number of bytes successfully copied while csum_and_copy needs to fault immediately as the checksum is partial. Introduce __skb_datagram_iter that additionally accepts: 1. copy operation function pointer 2. private data that goes with the copy operation 3. fault_short flag to indicate the action on short copy Suggested-by: David S. Miller <davem@davemloft.net> Acked-by: David S. Miller <davem@davemloft.net> Signed-off-by: Sagi Grimberg <sagi@lightbitslabs.com> Signed-off-by: Christoph Hellwig <hch@lst.de>
This commit is contained in:
parent
cb002d074d
commit
950fcaecd5
|
@ -408,27 +408,20 @@ int skb_kill_datagram(struct sock *sk, struct sk_buff *skb, unsigned int flags)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(skb_kill_datagram);
|
EXPORT_SYMBOL(skb_kill_datagram);
|
||||||
|
|
||||||
/**
|
int __skb_datagram_iter(const struct sk_buff *skb, int offset,
|
||||||
* skb_copy_datagram_iter - Copy a datagram to an iovec iterator.
|
struct iov_iter *to, int len, bool fault_short,
|
||||||
* @skb: buffer to copy
|
size_t (*cb)(const void *, size_t, void *, struct iov_iter *),
|
||||||
* @offset: offset in the buffer to start copying from
|
void *data)
|
||||||
* @to: iovec iterator to copy to
|
|
||||||
* @len: amount of data to copy from buffer to iovec
|
|
||||||
*/
|
|
||||||
int skb_copy_datagram_iter(const struct sk_buff *skb, int offset,
|
|
||||||
struct iov_iter *to, int len)
|
|
||||||
{
|
{
|
||||||
int start = skb_headlen(skb);
|
int start = skb_headlen(skb);
|
||||||
int i, copy = start - offset, start_off = offset, n;
|
int i, copy = start - offset, start_off = offset, n;
|
||||||
struct sk_buff *frag_iter;
|
struct sk_buff *frag_iter;
|
||||||
|
|
||||||
trace_skb_copy_datagram_iovec(skb, len);
|
|
||||||
|
|
||||||
/* Copy header. */
|
/* Copy header. */
|
||||||
if (copy > 0) {
|
if (copy > 0) {
|
||||||
if (copy > len)
|
if (copy > len)
|
||||||
copy = len;
|
copy = len;
|
||||||
n = copy_to_iter(skb->data + offset, copy, to);
|
n = cb(skb->data + offset, copy, data, to);
|
||||||
offset += n;
|
offset += n;
|
||||||
if (n != copy)
|
if (n != copy)
|
||||||
goto short_copy;
|
goto short_copy;
|
||||||
|
@ -450,8 +443,8 @@ int skb_copy_datagram_iter(const struct sk_buff *skb, int offset,
|
||||||
|
|
||||||
if (copy > len)
|
if (copy > len)
|
||||||
copy = len;
|
copy = len;
|
||||||
n = copy_to_iter(vaddr + frag->page_offset +
|
n = cb(vaddr + frag->page_offset +
|
||||||
offset - start, copy, to);
|
offset - start, copy, data, to);
|
||||||
kunmap(page);
|
kunmap(page);
|
||||||
offset += n;
|
offset += n;
|
||||||
if (n != copy)
|
if (n != copy)
|
||||||
|
@ -471,8 +464,8 @@ int skb_copy_datagram_iter(const struct sk_buff *skb, int offset,
|
||||||
if ((copy = end - offset) > 0) {
|
if ((copy = end - offset) > 0) {
|
||||||
if (copy > len)
|
if (copy > len)
|
||||||
copy = len;
|
copy = len;
|
||||||
if (skb_copy_datagram_iter(frag_iter, offset - start,
|
if (__skb_datagram_iter(frag_iter, offset - start,
|
||||||
to, copy))
|
to, copy, short_copy, cb, data))
|
||||||
goto fault;
|
goto fault;
|
||||||
if ((len -= copy) == 0)
|
if ((len -= copy) == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -493,11 +486,32 @@ int skb_copy_datagram_iter(const struct sk_buff *skb, int offset,
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
short_copy:
|
short_copy:
|
||||||
if (iov_iter_count(to))
|
if (fault_short || iov_iter_count(to))
|
||||||
goto fault;
|
goto fault;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static size_t simple_copy_to_iter(const void *addr, size_t bytes,
|
||||||
|
void *data __always_unused, struct iov_iter *i)
|
||||||
|
{
|
||||||
|
return copy_to_iter(addr, bytes, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* skb_copy_datagram_iter - Copy a datagram to an iovec iterator.
|
||||||
|
* @skb: buffer to copy
|
||||||
|
* @offset: offset in the buffer to start copying from
|
||||||
|
* @to: iovec iterator to copy to
|
||||||
|
* @len: amount of data to copy from buffer to iovec
|
||||||
|
*/
|
||||||
|
int skb_copy_datagram_iter(const struct sk_buff *skb, int offset,
|
||||||
|
struct iov_iter *to, int len)
|
||||||
|
{
|
||||||
|
trace_skb_copy_datagram_iovec(skb, len);
|
||||||
|
return __skb_datagram_iter(skb, offset, to, len, false,
|
||||||
|
simple_copy_to_iter, NULL);
|
||||||
|
}
|
||||||
EXPORT_SYMBOL(skb_copy_datagram_iter);
|
EXPORT_SYMBOL(skb_copy_datagram_iter);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -648,87 +662,21 @@ int zerocopy_sg_from_iter(struct sk_buff *skb, struct iov_iter *from)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(zerocopy_sg_from_iter);
|
EXPORT_SYMBOL(zerocopy_sg_from_iter);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* skb_copy_and_csum_datagram_iter - Copy datagram to an iovec iterator
|
||||||
|
* and update a checksum.
|
||||||
|
* @skb: buffer to copy
|
||||||
|
* @offset: offset in the buffer to start copying from
|
||||||
|
* @to: iovec iterator to copy to
|
||||||
|
* @len: amount of data to copy from buffer to iovec
|
||||||
|
* @csump: checksum pointer
|
||||||
|
*/
|
||||||
static int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset,
|
static int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset,
|
||||||
struct iov_iter *to, int len,
|
struct iov_iter *to, int len,
|
||||||
__wsum *csump)
|
__wsum *csump)
|
||||||
{
|
{
|
||||||
int start = skb_headlen(skb);
|
return __skb_datagram_iter(skb, offset, to, len, true,
|
||||||
int i, copy = start - offset, start_off = offset;
|
csum_and_copy_to_iter, csump);
|
||||||
struct sk_buff *frag_iter;
|
|
||||||
int pos = 0;
|
|
||||||
int n;
|
|
||||||
|
|
||||||
/* Copy header. */
|
|
||||||
if (copy > 0) {
|
|
||||||
if (copy > len)
|
|
||||||
copy = len;
|
|
||||||
n = csum_and_copy_to_iter(skb->data + offset, copy, csump, to);
|
|
||||||
offset += n;
|
|
||||||
if (n != copy)
|
|
||||||
goto fault;
|
|
||||||
if ((len -= copy) == 0)
|
|
||||||
return 0;
|
|
||||||
pos = copy;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
|
|
||||||
int end;
|
|
||||||
const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
|
|
||||||
|
|
||||||
WARN_ON(start > offset + len);
|
|
||||||
|
|
||||||
end = start + skb_frag_size(frag);
|
|
||||||
if ((copy = end - offset) > 0) {
|
|
||||||
__wsum csum2 = 0;
|
|
||||||
struct page *page = skb_frag_page(frag);
|
|
||||||
u8 *vaddr = kmap(page);
|
|
||||||
|
|
||||||
if (copy > len)
|
|
||||||
copy = len;
|
|
||||||
n = csum_and_copy_to_iter(vaddr + frag->page_offset +
|
|
||||||
offset - start, copy,
|
|
||||||
&csum2, to);
|
|
||||||
kunmap(page);
|
|
||||||
offset += n;
|
|
||||||
if (n != copy)
|
|
||||||
goto fault;
|
|
||||||
*csump = csum_block_add(*csump, csum2, pos);
|
|
||||||
if (!(len -= copy))
|
|
||||||
return 0;
|
|
||||||
pos += copy;
|
|
||||||
}
|
|
||||||
start = end;
|
|
||||||
}
|
|
||||||
|
|
||||||
skb_walk_frags(skb, frag_iter) {
|
|
||||||
int end;
|
|
||||||
|
|
||||||
WARN_ON(start > offset + len);
|
|
||||||
|
|
||||||
end = start + frag_iter->len;
|
|
||||||
if ((copy = end - offset) > 0) {
|
|
||||||
__wsum csum2 = 0;
|
|
||||||
if (copy > len)
|
|
||||||
copy = len;
|
|
||||||
if (skb_copy_and_csum_datagram(frag_iter,
|
|
||||||
offset - start,
|
|
||||||
to, copy,
|
|
||||||
&csum2))
|
|
||||||
goto fault;
|
|
||||||
*csump = csum_block_add(*csump, csum2, pos);
|
|
||||||
if ((len -= copy) == 0)
|
|
||||||
return 0;
|
|
||||||
offset += copy;
|
|
||||||
pos += copy;
|
|
||||||
}
|
|
||||||
start = end;
|
|
||||||
}
|
|
||||||
if (!len)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
fault:
|
|
||||||
iov_iter_revert(to, offset - start_off);
|
|
||||||
return -EFAULT;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
__sum16 __skb_checksum_complete_head(struct sk_buff *skb, int len)
|
__sum16 __skb_checksum_complete_head(struct sk_buff *skb, int len)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user