aboutsummaryrefslogtreecommitdiffstats
path: root/net/core
diff options
context:
space:
mode:
authorMichael S. Tsirkin <mst@redhat.com>2012-07-20 05:23:17 -0400
committerDavid S. Miller <davem@davemloft.net>2012-07-22 15:39:33 -0400
commit1080e512d44d4f67b8beb8edf25a1bbcb1066dc7 (patch)
tree02cecc2d69f820ac082578daa228cdbe2a4503dd /net/core
parent868eefeb17d40f6acde00ad8165a268529cf6d24 (diff)
net: orphan frags on receive
zero copy packets are normally sent to the outside network, but bridging, tun etc might loop them back to host networking stack. If this happens destructors will never be called, so orphan the frags immediately on receive. Signed-off-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core')
-rw-r--r--net/core/dev.c7
1 files changed, 6 insertions, 1 deletions
diff --git a/net/core/dev.c b/net/core/dev.c
index d70e4a3a49f2..cca02ae7a844 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1632,6 +1632,8 @@ static inline int deliver_skb(struct sk_buff *skb,
1632 struct packet_type *pt_prev, 1632 struct packet_type *pt_prev,
1633 struct net_device *orig_dev) 1633 struct net_device *orig_dev)
1634{ 1634{
1635 if (unlikely(skb_orphan_frags(skb, GFP_ATOMIC)))
1636 return -ENOMEM;
1635 atomic_inc(&skb->users); 1637 atomic_inc(&skb->users);
1636 return pt_prev->func(skb, skb->dev, pt_prev, orig_dev); 1638 return pt_prev->func(skb, skb->dev, pt_prev, orig_dev);
1637} 1639}
@@ -3262,7 +3264,10 @@ ncls:
3262 } 3264 }
3263 3265
3264 if (pt_prev) { 3266 if (pt_prev) {
3265 ret = pt_prev->func(skb, skb->dev, pt_prev, orig_dev); 3267 if (unlikely(skb_orphan_frags(skb, GFP_ATOMIC)))
3268 ret = -ENOMEM;
3269 else
3270 ret = pt_prev->func(skb, skb->dev, pt_prev, orig_dev);
3266 } else { 3271 } else {
3267 atomic_long_inc(&skb->dev->rx_dropped); 3272 atomic_long_inc(&skb->dev->rx_dropped);
3268 kfree_skb(skb); 3273 kfree_skb(skb);