[NET]: Avoid allocating skb in skb_pad

First of all it is unnecessary to allocate a new skb in skb_pad since
the existing one is not shared.  More importantly, our hard_start_xmit
interface does not allow a new skb to be allocated since that breaks
requeueing.

This patch uses pskb_expand_head to expand the existing skb and linearize
it if needed.  Actually, someone should sift through every instance of
skb_pad on a non-linear skb as they do not fit the reasons why this was
originally created.

Incidentally, this fixes a minor bug when the skb is cloned (tcpdump,
TCP, etc.).  As it is skb_pad will simply write over a cloned skb.  Because
of the position of the write it is unlikely to cause problems but still
it's best if we don't do it.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Herbert Xu
2006-06-23 02:06:41 -07:00
committed by David S. Miller
parent 5fa21d821f
commit 5b057c6b1a
36 changed files with 74 additions and 103 deletions
+1 -2
View File
@@ -1031,8 +1031,7 @@ static int mc32_send_packet(struct sk_buff *skb, struct net_device *dev)
return 1; return 1;
} }
skb = skb_padto(skb, ETH_ZLEN); if (skb_padto(skb, ETH_ZLEN)) {
if (skb == NULL) {
netif_wake_queue(dev); netif_wake_queue(dev);
return 0; return 0;
} }
+1 -2
View File
@@ -1070,8 +1070,7 @@ static int i596_start_xmit(struct sk_buff *skb, struct net_device *dev)
skb->len, (unsigned int)skb->data)); skb->len, (unsigned int)skb->data));
if (skb->len < ETH_ZLEN) { if (skb->len < ETH_ZLEN) {
skb = skb_padto(skb, ETH_ZLEN); if (skb_padto(skb, ETH_ZLEN))
if (skb == NULL)
return 0; return 0;
length = ETH_ZLEN; length = ETH_ZLEN;
} }
+1 -2
View File
@@ -573,8 +573,7 @@ static int lance_start_xmit (struct sk_buff *skb, struct net_device *dev)
if (len < ETH_ZLEN) { if (len < ETH_ZLEN) {
len = ETH_ZLEN; len = ETH_ZLEN;
skb = skb_padto(skb, ETH_ZLEN); if (skb_padto(skb, ETH_ZLEN))
if (skb == NULL)
return 0; return 0;
} }
+1 -2
View File
@@ -607,8 +607,7 @@ static int ariadne_start_xmit(struct sk_buff *skb, struct net_device *dev)
/* FIXME: is the 79C960 new enough to do its own padding right ? */ /* FIXME: is the 79C960 new enough to do its own padding right ? */
if (skb->len < ETH_ZLEN) if (skb->len < ETH_ZLEN)
{ {
skb = skb_padto(skb, ETH_ZLEN); if (skb_padto(skb, ETH_ZLEN))
if (skb == NULL)
return 0; return 0;
len = ETH_ZLEN; len = ETH_ZLEN;
} }
+1 -2
View File
@@ -700,8 +700,7 @@ ether1_sendpacket (struct sk_buff *skb, struct net_device *dev)
} }
if (skb->len < ETH_ZLEN) { if (skb->len < ETH_ZLEN) {
skb = skb_padto(skb, ETH_ZLEN); if (skb_padto(skb, ETH_ZLEN))
if (skb == NULL)
goto out; goto out;
} }
+1 -2
View File
@@ -518,8 +518,7 @@ ether3_sendpacket(struct sk_buff *skb, struct net_device *dev)
length = (length + 1) & ~1; length = (length + 1) & ~1;
if (length != skb->len) { if (length != skb->len) {
skb = skb_padto(skb, length); if (skb_padto(skb, length))
if (skb == NULL)
goto out; goto out;
} }
+1 -2
View File
@@ -804,8 +804,7 @@ static int lance_start_xmit( struct sk_buff *skb, struct net_device *dev )
++len; ++len;
if (len > skb->len) { if (len > skb->len) {
skb = skb_padto(skb, len); if (skb_padto(skb, len))
if (skb == NULL)
return 0; return 0;
} }
+1 -2
View File
@@ -2915,8 +2915,7 @@ static int cas_start_xmit(struct sk_buff *skb, struct net_device *dev)
*/ */
static int ring; static int ring;
skb = skb_padto(skb, cp->min_frame_size); if (skb_padto(skb, cp->min_frame_size))
if (!skb)
return 0; return 0;
/* XXX: we need some higher-level QoS hooks to steer packets to /* XXX: we need some higher-level QoS hooks to steer packets to
+1 -2
View File
@@ -885,8 +885,7 @@ static int lance_start_xmit(struct sk_buff *skb, struct net_device *dev)
len = skblen; len = skblen;
if (len < ETH_ZLEN) { if (len < ETH_ZLEN) {
skb = skb_padto(skb, ETH_ZLEN); if (skb_padto(skb, ETH_ZLEN))
if (skb == NULL)
return 0; return 0;
len = ETH_ZLEN; len = ETH_ZLEN;
} }
+2 -5
View File
@@ -938,11 +938,8 @@ static int depca_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (skb->len < 1) if (skb->len < 1)
goto out; goto out;
if (skb->len < ETH_ZLEN) { if (skb_padto(skb, ETH_ZLEN))
skb = skb_padto(skb, ETH_ZLEN); goto out;
if (skb == NULL)
goto out;
}
netif_stop_queue(dev); netif_stop_queue(dev);
+1 -2
View File
@@ -1154,8 +1154,7 @@ static int eepro_send_packet(struct sk_buff *skb, struct net_device *dev)
printk(KERN_DEBUG "%s: entering eepro_send_packet routine.\n", dev->name); printk(KERN_DEBUG "%s: entering eepro_send_packet routine.\n", dev->name);
if (length < ETH_ZLEN) { if (length < ETH_ZLEN) {
skb = skb_padto(skb, ETH_ZLEN); if (skb_padto(skb, ETH_ZLEN))
if (skb == NULL)
return 0; return 0;
length = ETH_ZLEN; length = ETH_ZLEN;
} }
+1 -2
View File
@@ -677,8 +677,7 @@ static int eexp_xmit(struct sk_buff *buf, struct net_device *dev)
#endif #endif
if (buf->len < ETH_ZLEN) { if (buf->len < ETH_ZLEN) {
buf = skb_padto(buf, ETH_ZLEN); if (skb_padto(buf, ETH_ZLEN))
if (buf == NULL)
return 0; return 0;
length = ETH_ZLEN; length = ETH_ZLEN;
} }
+2 -5
View File
@@ -1027,11 +1027,8 @@ static int epic_start_xmit(struct sk_buff *skb, struct net_device *dev)
u32 ctrl_word; u32 ctrl_word;
unsigned long flags; unsigned long flags;
if (skb->len < ETH_ZLEN) { if (skb_padto(skb, ETH_ZLEN))
skb = skb_padto(skb, ETH_ZLEN); return 0;
if (skb == NULL)
return 0;
}
/* Caution: the write order is important here, set the field with the /* Caution: the write order is important here, set the field with the
"ownership" bit last. */ "ownership" bit last. */
+1 -2
View File
@@ -1064,8 +1064,7 @@ static int eth16i_tx(struct sk_buff *skb, struct net_device *dev)
unsigned long flags; unsigned long flags;
if (length < ETH_ZLEN) { if (length < ETH_ZLEN) {
skb = skb_padto(skb, ETH_ZLEN); if (skb_padto(skb, ETH_ZLEN))
if (skb == NULL)
return 0; return 0;
length = ETH_ZLEN; length = ETH_ZLEN;
} }
+2 -5
View File
@@ -1487,11 +1487,8 @@ static int hp100_start_xmit_bm(struct sk_buff *skb, struct net_device *dev)
if (skb->len <= 0) if (skb->len <= 0)
return 0; return 0;
if (skb->len < ETH_ZLEN && lp->chip == HP100_CHIPID_SHASTA) { if (lp->chip == HP100_CHIPID_SHASTA && skb_padto(skb, ETH_ZLEN))
skb = skb_padto(skb, ETH_ZLEN); return 0;
if (skb == NULL)
return 0;
}
/* Get Tx ring tail pointer */ /* Get Tx ring tail pointer */
if (lp->txrtail->next == lp->txrhead) { if (lp->txrtail->next == lp->txrhead) {
+1 -2
View File
@@ -968,8 +968,7 @@ static int lance_start_xmit(struct sk_buff *skb, struct net_device *dev)
/* The old LANCE chips doesn't automatically pad buffers to min. size. */ /* The old LANCE chips doesn't automatically pad buffers to min. size. */
if (chip_table[lp->chip_version].flags & LANCE_MUST_PAD) { if (chip_table[lp->chip_version].flags & LANCE_MUST_PAD) {
if (skb->len < ETH_ZLEN) { if (skb->len < ETH_ZLEN) {
skb = skb_padto(skb, ETH_ZLEN); if (skb_padto(skb, ETH_ZLEN))
if (skb == NULL)
goto out; goto out;
lp->tx_ring[entry].length = -ETH_ZLEN; lp->tx_ring[entry].length = -ETH_ZLEN;
} }
+1 -2
View File
@@ -1083,8 +1083,7 @@ static int i596_start_xmit(struct sk_buff *skb, struct net_device *dev)
skb->len, skb->data)); skb->len, skb->data));
if (length < ETH_ZLEN) { if (length < ETH_ZLEN) {
skb = skb_padto(skb, ETH_ZLEN); if (skb_padto(skb, ETH_ZLEN))
if (skb == NULL)
return 0; return 0;
length = ETH_ZLEN; length = ETH_ZLEN;
} }
+1 -2
View File
@@ -877,8 +877,7 @@ static int i596_start_xmit (struct sk_buff *skb, struct net_device *dev) {
length = skb->len; length = skb->len;
if (length < ETH_ZLEN) { if (length < ETH_ZLEN) {
skb = skb_padto(skb, ETH_ZLEN); if (skb_padto(skb, ETH_ZLEN))
if (skb == NULL)
return 0; return 0;
length = ETH_ZLEN; length = ETH_ZLEN;
} }
+1 -2
View File
@@ -1939,8 +1939,7 @@ again:
/* pad frames to at least ETH_ZLEN bytes */ /* pad frames to at least ETH_ZLEN bytes */
if (unlikely(skb->len < ETH_ZLEN)) { if (unlikely(skb->len < ETH_ZLEN)) {
skb = skb_padto(skb, ETH_ZLEN); if (skb_padto(skb, ETH_ZLEN)) {
if (skb == NULL) {
/* The packet is gone, so we must /* The packet is gone, so we must
* return 0 */ * return 0 */
mgp->stats.tx_dropped += 1; mgp->stats.tx_dropped += 1;
+1 -2
View File
@@ -831,8 +831,7 @@ static int fjn_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (length < ETH_ZLEN) if (length < ETH_ZLEN)
{ {
skb = skb_padto(skb, ETH_ZLEN); if (skb_padto(skb, ETH_ZLEN))
if (skb == NULL)
return 0; return 0;
length = ETH_ZLEN; length = ETH_ZLEN;
} }

Some files were not shown because too many files have changed in this diff Show More