Skip to content

Commit 950fcae

Browse files
Sagi GrimbergChristoph Hellwig
authored andcommitted
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>
1 parent cb002d0 commit 950fcae

File tree

1 file changed

+42
-94
lines changed

1 file changed

+42
-94
lines changed

net/core/datagram.c

Lines changed: 42 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -408,27 +408,20 @@ int skb_kill_datagram(struct sock *sk, struct sk_buff *skb, unsigned int flags)
408408
}
409409
EXPORT_SYMBOL(skb_kill_datagram);
410410

411-
/**
412-
* skb_copy_datagram_iter - Copy a datagram to an iovec iterator.
413-
* @skb: buffer to copy
414-
* @offset: offset in the buffer to start copying from
415-
* @to: iovec iterator to copy to
416-
* @len: amount of data to copy from buffer to iovec
417-
*/
418-
int skb_copy_datagram_iter(const struct sk_buff *skb, int offset,
419-
struct iov_iter *to, int len)
411+
int __skb_datagram_iter(const struct sk_buff *skb, int offset,
412+
struct iov_iter *to, int len, bool fault_short,
413+
size_t (*cb)(const void *, size_t, void *, struct iov_iter *),
414+
void *data)
420415
{
421416
int start = skb_headlen(skb);
422417
int i, copy = start - offset, start_off = offset, n;
423418
struct sk_buff *frag_iter;
424419

425-
trace_skb_copy_datagram_iovec(skb, len);
426-
427420
/* Copy header. */
428421
if (copy > 0) {
429422
if (copy > len)
430423
copy = len;
431-
n = copy_to_iter(skb->data + offset, copy, to);
424+
n = cb(skb->data + offset, copy, data, to);
432425
offset += n;
433426
if (n != copy)
434427
goto short_copy;
@@ -450,8 +443,8 @@ int skb_copy_datagram_iter(const struct sk_buff *skb, int offset,
450443

451444
if (copy > len)
452445
copy = len;
453-
n = copy_to_iter(vaddr + frag->page_offset +
454-
offset - start, copy, to);
446+
n = cb(vaddr + frag->page_offset +
447+
offset - start, copy, data, to);
455448
kunmap(page);
456449
offset += n;
457450
if (n != copy)
@@ -471,8 +464,8 @@ int skb_copy_datagram_iter(const struct sk_buff *skb, int offset,
471464
if ((copy = end - offset) > 0) {
472465
if (copy > len)
473466
copy = len;
474-
if (skb_copy_datagram_iter(frag_iter, offset - start,
475-
to, copy))
467+
if (__skb_datagram_iter(frag_iter, offset - start,
468+
to, copy, short_copy, cb, data))
476469
goto fault;
477470
if ((len -= copy) == 0)
478471
return 0;
@@ -493,11 +486,32 @@ int skb_copy_datagram_iter(const struct sk_buff *skb, int offset,
493486
return -EFAULT;
494487

495488
short_copy:
496-
if (iov_iter_count(to))
489+
if (fault_short || iov_iter_count(to))
497490
goto fault;
498491

499492
return 0;
500493
}
494+
495+
static size_t simple_copy_to_iter(const void *addr, size_t bytes,
496+
void *data __always_unused, struct iov_iter *i)
497+
{
498+
return copy_to_iter(addr, bytes, i);
499+
}
500+
501+
/**
502+
* skb_copy_datagram_iter - Copy a datagram to an iovec iterator.
503+
* @skb: buffer to copy
504+
* @offset: offset in the buffer to start copying from
505+
* @to: iovec iterator to copy to
506+
* @len: amount of data to copy from buffer to iovec
507+
*/
508+
int skb_copy_datagram_iter(const struct sk_buff *skb, int offset,
509+
struct iov_iter *to, int len)
510+
{
511+
trace_skb_copy_datagram_iovec(skb, len);
512+
return __skb_datagram_iter(skb, offset, to, len, false,
513+
simple_copy_to_iter, NULL);
514+
}
501515
EXPORT_SYMBOL(skb_copy_datagram_iter);
502516

503517
/**
@@ -648,87 +662,21 @@ int zerocopy_sg_from_iter(struct sk_buff *skb, struct iov_iter *from)
648662
}
649663
EXPORT_SYMBOL(zerocopy_sg_from_iter);
650664

665+
/**
666+
* skb_copy_and_csum_datagram_iter - Copy datagram to an iovec iterator
667+
* and update a checksum.
668+
* @skb: buffer to copy
669+
* @offset: offset in the buffer to start copying from
670+
* @to: iovec iterator to copy to
671+
* @len: amount of data to copy from buffer to iovec
672+
* @csump: checksum pointer
673+
*/
651674
static int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset,
652675
struct iov_iter *to, int len,
653676
__wsum *csump)
654677
{
655-
int start = skb_headlen(skb);
656-
int i, copy = start - offset, start_off = offset;
657-
struct sk_buff *frag_iter;
658-
int pos = 0;
659-
int n;
660-
661-
/* Copy header. */
662-
if (copy > 0) {
663-
if (copy > len)
664-
copy = len;
665-
n = csum_and_copy_to_iter(skb->data + offset, copy, csump, to);
666-
offset += n;
667-
if (n != copy)
668-
goto fault;
669-
if ((len -= copy) == 0)
670-
return 0;
671-
pos = copy;
672-
}
673-
674-
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
675-
int end;
676-
const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
677-
678-
WARN_ON(start > offset + len);
679-
680-
end = start + skb_frag_size(frag);
681-
if ((copy = end - offset) > 0) {
682-
__wsum csum2 = 0;
683-
struct page *page = skb_frag_page(frag);
684-
u8 *vaddr = kmap(page);
685-
686-
if (copy > len)
687-
copy = len;
688-
n = csum_and_copy_to_iter(vaddr + frag->page_offset +
689-
offset - start, copy,
690-
&csum2, to);
691-
kunmap(page);
692-
offset += n;
693-
if (n != copy)
694-
goto fault;
695-
*csump = csum_block_add(*csump, csum2, pos);
696-
if (!(len -= copy))
697-
return 0;
698-
pos += copy;
699-
}
700-
start = end;
701-
}
702-
703-
skb_walk_frags(skb, frag_iter) {
704-
int end;
705-
706-
WARN_ON(start > offset + len);
707-
708-
end = start + frag_iter->len;
709-
if ((copy = end - offset) > 0) {
710-
__wsum csum2 = 0;
711-
if (copy > len)
712-
copy = len;
713-
if (skb_copy_and_csum_datagram(frag_iter,
714-
offset - start,
715-
to, copy,
716-
&csum2))
717-
goto fault;
718-
*csump = csum_block_add(*csump, csum2, pos);
719-
if ((len -= copy) == 0)
720-
return 0;
721-
offset += copy;
722-
pos += copy;
723-
}
724-
start = end;
725-
}
726-
if (!len)
727-
return 0;
728-
729-
fault:
730-
iov_iter_revert(to, offset - start_off);
731-
return -EFAULT;
678+
return __skb_datagram_iter(skb, offset, to, len, true,
679+
csum_and_copy_to_iter, csump);
732680
}
733681

734682
__sum16 __skb_checksum_complete_head(struct sk_buff *skb, int len)

0 commit comments

Comments
 (0)