diff --git a/lib/iov_iter.c b/lib/iov_iter.c index f9193f952f49..a8c90676d715 100644 --- a/lib/iov_iter.c +++ b/lib/iov_iter.c @@ -1149,10 +1149,15 @@ static ssize_t __iov_iter_get_pages_alloc(struct iov_iter *i, { unsigned int n, gup_flags = 0; + pr_err("DEBUG: __iov_iter_get_pages_alloc: initial maxsize=%zu, i->count=%zu\n", + maxsize, i->count); + if (maxsize > i->count) maxsize = i->count; - if (!maxsize) + if (!maxsize) { + pr_err("DEBUG: __iov_iter_get_pages_alloc: returning 0 - no maxsize\n"); return 0; + } if (maxsize > MAX_RW_COUNT) maxsize = MAX_RW_COUNT; @@ -1166,15 +1171,31 @@ static ssize_t __iov_iter_get_pages_alloc(struct iov_iter *i, gup_flags |= FOLL_NOFAULT; addr = first_iovec_segment(i, &maxsize); + pr_err("DEBUG: first_iovec_segment returned addr=%lx, maxsize_after=%zu\n", + addr, maxsize); + *start = addr % PAGE_SIZE; addr &= PAGE_MASK; n = want_pages_array(pages, maxsize, *start, maxpages); + + pr_err("DEBUG: want_pages_array returned n=%u, addr=%lx, start=%zu\n", + n, addr, *start); + if (!n) return -ENOMEM; + res = get_user_pages_fast(addr, n, gup_flags, *pages); + + pr_err("DEBUG: get_user_pages_fast returned res=%d (requested n=%u)\n", + res, n); + if (unlikely(res <= 0)) return res; + maxsize = min_t(size_t, maxsize, res * PAGE_SIZE - *start); + + pr_err("DEBUG: final maxsize=%zu, advancing iterator\n", maxsize); + iov_iter_advance(i, maxsize); return maxsize; } @@ -1213,11 +1234,21 @@ static ssize_t __iov_iter_get_pages_alloc(struct iov_iter *i, ssize_t iov_iter_get_pages2(struct iov_iter *i, struct page **pages, size_t maxsize, unsigned maxpages, size_t *start) { + ssize_t result; + + pr_err("DEBUG: iov_iter_get_pages2: maxsize=%zu, maxpages=%u, iter_count=%zu, iter_type=%u\n", + maxsize, maxpages, iov_iter_count(i), i->iter_type); + if (!maxpages) return 0; BUG_ON(!pages); - return __iov_iter_get_pages_alloc(i, &pages, maxsize, maxpages, start); + result = __iov_iter_get_pages_alloc(i, &pages, maxsize, maxpages, start); + + pr_err("DEBUG: iov_iter_get_pages2: returning result=%zd, start=%zu, iter_count_after=%zu\n", + result, start ? *start : 0, iov_iter_count(i)); + + return result; } EXPORT_SYMBOL(iov_iter_get_pages2); diff --git a/net/core/datagram.c b/net/core/datagram.c index 94cc4705e91d..135dc37bd746 100644 --- a/net/core/datagram.c +++ b/net/core/datagram.c @@ -623,6 +623,21 @@ int zerocopy_fill_skb_from_iter(struct sk_buff *skb, { int frag = skb_shinfo(skb)->nr_frags; + pr_err("DEBUG: zerocopy_fill_skb_from_iter: initial length=%zu, iov_iter_count=%zu, iter_type=%u\n", + length, iov_iter_count(from), from->iter_type); + + if (from->iter_type == ITER_IOVEC) { + pr_err("DEBUG: IOVEC iterator: nr_segs=%lu, iov_offset=%zu\n", + from->nr_segs, from->iov_offset); + if (from->__iov && from->nr_segs > 0) { + pr_err("DEBUG: Current iovec[0]: base=%px, len=%zu\n", + from->__iov[0].iov_base, from->__iov[0].iov_len); + if (from->nr_segs > 1) + pr_err("DEBUG: Next iovec[1]: base=%px, len=%zu\n", + from->__iov[1].iov_base, from->__iov[1].iov_len); + } + } + if (!skb_frags_readable(skb)) return -EFAULT; @@ -633,16 +648,32 @@ int zerocopy_fill_skb_from_iter(struct sk_buff *skb, size_t start; ssize_t copied; + pr_err("DEBUG: zerocopy loop: length=%zu, iov_iter_count=%zu, frag=%d\n", + length, iov_iter_count(from), frag); + if (frag == MAX_SKB_FRAGS) return -EMSGSIZE; copied = iov_iter_get_pages2(from, pages, length, - MAX_SKB_FRAGS - frag, &start); + MAX_SKB_FRAGS - frag, &start); + + pr_err("DEBUG: iov_iter_get_pages2 returned copied=%zd, start=%zu\n", + copied, start); + pr_err("DEBUG: iterator state after get_pages2: iov_iter_count=%zu\n", + iov_iter_count(from)); + if (copied < 0) return -EFAULT; + if (copied == 0 && iov_iter_count(from) > 0) + pr_err("BUG: iov_iter_get_pages2 returned 0 but iterator claims %zu bytes remaining (requested %zu bytes)\n", + iov_iter_count(from), length); + length -= copied; + pr_err("DEBUG: after processing: length=%zu, iov_iter_count=%zu, copied=%zd\n", + length, iov_iter_count(from), copied); + skb->data_len += copied; skb->len += copied; skb->truesize += PAGE_ALIGN(copied + start); @@ -686,6 +717,12 @@ int zerocopy_fill_skb_from_iter(struct sk_buff *skb, if (refs) page_ref_sub(last_head, refs); } + + pr_err("DEBUG: zerocopy_fill_skb_from_iter: loop exit - length=%zu, iov_iter_count=%zu\n", + length, iov_iter_count(from)); + pr_err("DEBUG: zerocopy_fill_skb_from_iter: final skb->len=%u, skb->data_len=%u\n", + skb->len, skb->data_len); + return 0; } diff --git a/net/vmw_vsock/virtio_transport_common.c b/net/vmw_vsock/virtio_transport_common.c index fe92e5fa95b4..25300125b789 100644 --- a/net/vmw_vsock/virtio_transport_common.c +++ b/net/vmw_vsock/virtio_transport_common.c @@ -288,7 +288,14 @@ static struct sk_buff *virtio_transport_alloc_skb(struct virtio_vsock_pkt_info * if (info->msg && payload_len > 0) { int err; + pr_err("DEBUG: virtio_transport_alloc_skb: calling fill_skb with payload_len=%zu, zcopy=%d\n", + payload_len, zcopy); + err = virtio_transport_fill_skb(skb, info, payload_len, zcopy); + + pr_err("DEBUG: virtio_transport_fill_skb returned err=%d, skb->len=%u\n", + err, skb->len); + if (err) goto out;