aboutsummaryrefslogtreecommitdiffstats
path: root/net/core/skbuff.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2011-09-22 03:23:13 -0400
committerDavid S. Miller <davem@davemloft.net>2011-09-22 03:23:13 -0400
commit8decf868790b48a727d7e7ca164f2bcd3c1389c0 (patch)
treeb759a5f861f842af7ea76f9011b579d06e9d5508 /net/core/skbuff.c
parent3fc72370186be2f9d4d6ef06d99e1caa5d92c564 (diff)
parentd93dc5c4478c1fd5de85a3e8aece9aad7bbae044 (diff)
Merge branch 'master' of github.com:davem330/net
Conflicts: MAINTAINERS drivers/net/Kconfig drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c drivers/net/ethernet/broadcom/tg3.c drivers/net/wireless/iwlwifi/iwl-pci.c drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c drivers/net/wireless/rt2x00/rt2800usb.c drivers/net/wireless/wl12xx/main.c
Diffstat (limited to 'net/core/skbuff.c')
-rw-r--r--net/core/skbuff.c22
1 files changed, 17 insertions, 5 deletions
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 296afd0aa8d2..5b2c5f1d4dba 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -613,8 +613,21 @@ struct sk_buff *skb_morph(struct sk_buff *dst, struct sk_buff *src)
613} 613}
614EXPORT_SYMBOL_GPL(skb_morph); 614EXPORT_SYMBOL_GPL(skb_morph);
615 615
616/* skb frags copy userspace buffers to kernel */ 616/* skb_copy_ubufs - copy userspace skb frags buffers to kernel
617static int skb_copy_ubufs(struct sk_buff *skb, gfp_t gfp_mask) 617 * @skb: the skb to modify
618 * @gfp_mask: allocation priority
619 *
620 * This must be called on SKBTX_DEV_ZEROCOPY skb.
621 * It will copy all frags into kernel and drop the reference
622 * to userspace pages.
623 *
624 * If this function is called from an interrupt gfp_mask() must be
625 * %GFP_ATOMIC.
626 *
627 * Returns 0 on success or a negative error code on failure
628 * to allocate kernel memory to copy to.
629 */
630int skb_copy_ubufs(struct sk_buff *skb, gfp_t gfp_mask)
618{ 631{
619 int i; 632 int i;
620 int num_frags = skb_shinfo(skb)->nr_frags; 633 int num_frags = skb_shinfo(skb)->nr_frags;
@@ -654,6 +667,8 @@ static int skb_copy_ubufs(struct sk_buff *skb, gfp_t gfp_mask)
654 skb_shinfo(skb)->frags[i - 1].page = head; 667 skb_shinfo(skb)->frags[i - 1].page = head;
655 head = (struct page *)head->private; 668 head = (struct page *)head->private;
656 } 669 }
670
671 skb_shinfo(skb)->tx_flags &= ~SKBTX_DEV_ZEROCOPY;
657 return 0; 672 return 0;
658} 673}
659 674
@@ -679,7 +694,6 @@ struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask)
679 if (skb_shinfo(skb)->tx_flags & SKBTX_DEV_ZEROCOPY) { 694 if (skb_shinfo(skb)->tx_flags & SKBTX_DEV_ZEROCOPY) {
680 if (skb_copy_ubufs(skb, gfp_mask)) 695 if (skb_copy_ubufs(skb, gfp_mask))
681 return NULL; 696 return NULL;
682 skb_shinfo(skb)->tx_flags &= ~SKBTX_DEV_ZEROCOPY;
683 } 697 }
684 698
685 n = skb + 1; 699 n = skb + 1;
@@ -805,7 +819,6 @@ struct sk_buff *pskb_copy(struct sk_buff *skb, gfp_t gfp_mask)
805 n = NULL; 819 n = NULL;
806 goto out; 820 goto out;
807 } 821 }
808 skb_shinfo(skb)->tx_flags &= ~SKBTX_DEV_ZEROCOPY;
809 } 822 }
810 for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { 823 for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
811 skb_shinfo(n)->frags[i] = skb_shinfo(skb)->frags[i]; 824 skb_shinfo(n)->frags[i] = skb_shinfo(skb)->frags[i];
@@ -898,7 +911,6 @@ int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail,
898 if (skb_shinfo(skb)->tx_flags & SKBTX_DEV_ZEROCOPY) { 911 if (skb_shinfo(skb)->tx_flags & SKBTX_DEV_ZEROCOPY) {
899 if (skb_copy_ubufs(skb, gfp_mask)) 912 if (skb_copy_ubufs(skb, gfp_mask))
900 goto nofrags; 913 goto nofrags;
901 skb_shinfo(skb)->tx_flags &= ~SKBTX_DEV_ZEROCOPY;
902 } 914 }
903 for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) 915 for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
904 skb_frag_ref(skb, i); 916 skb_frag_ref(skb, i);