diff -ru linux-2.6.0-test7/net/8021q/vlan_dev.c linux-2.6/net/8021q/vlan_dev.c --- linux-2.6.0-test7/net/8021q/vlan_dev.c Wed Oct 8 21:24:44 2003 +++ linux-2.6/net/8021q/vlan_dev.c Sat Oct 11 00:45:28 2003 @@ -74,11 +74,7 @@ static inline struct sk_buff *vlan_check_reorder_header(struct sk_buff *skb) { if (VLAN_DEV_INFO(skb->dev)->flags & 1) { - if (skb_shared(skb) || skb_cloned(skb)) { - struct sk_buff *nskb = skb_copy(skb, GFP_ATOMIC); - kfree(skb); - skb = nskb; - } + skb = skb_unshare(skb, GFP_ATOMIC); if (skb) { /* Lifted from Gleb's VLAN code... */ memmove(skb->data - ETH_HLEN, @@ -121,6 +117,7 @@ struct net_device_stats *stats; unsigned short vlan_TCI; unsigned short proto; + struct net_device *vlan_dev; /* vlan_TCI = ntohs(get_unaligned(&vhdr->h_vlan_TCI)); */ vlan_TCI = ntohs(vhdr->h_vlan_TCI); @@ -144,8 +141,8 @@ */ spin_lock_bh(&vlan_group_lock); - skb->dev = __find_vlan_dev(dev, vid); - if (!skb->dev) { + vlan_dev = __find_vlan_dev(dev, vid); + if (!vlan_dev) { spin_unlock_bh(&vlan_group_lock); #ifdef VLAN_DEBUG @@ -156,10 +153,18 @@ return -1; } - skb->dev->last_rx = jiffies; + vlan_dev->last_rx = jiffies; + stats = vlan_dev_get_stats(vlan_dev); + + skb = skb_share_check(skb, GFP_ATOMIC); + if (!skb) { + spin_unlock_bh(&vlan_group_lock); + stats->rx_dropped++; + return NET_RX_DROP; + } + skb->dev = vlan_dev; /* Bump the rx counters for the VLAN device. */ - stats = vlan_dev_get_stats(skb->dev); stats->rx_packets++; stats->rx_bytes += skb->len;