Re: [PATCH 6/9] s390: qeth driver fixes [3/6]

2006-09-15 Thread Frank Pavlic
yes it would but the problem in qeth is not only bonding related.
We just have found it in a bonding scenario . But this kernel
panic could also occur without bonding. 

But thanks for reviewing it 
On Fri, Sep 15, 2006 at 08:51:25AM -0700, Jay Vosburgh wrote:
> Frank Pavlic <[EMAIL PROTECTED]> wrote:
> 
> >[PATCH 6/9] s390: qeth driver fixes [3/6]
> >
> >From: Frank Pavlic <[EMAIL PROTECTED]>
> > fixed kernel panic caused by qeth driver:
> >Using a bonding device qeth driver will realloc
> >headroom for every skb coming from the bond device.
> >Once this happens qeth frees the original skb and
> >set the skb pointer to the new realloced skb.
> 
>   Frank, does the following patch to bonding (to track larger than
> usual hard_header_len) resolve this problem without changing qeth?  I
> believe this patch is queued for 2.6.19.
> 
> To: netdev@vger.kernel.org, [EMAIL PROTECTED]
> Cc: Jeff Garzik <[EMAIL PROTECTED]>
> Subject: [PATCH 5/7] bonding: Handle large hard_header_len
> X-Mailer: MH-E 7.83; nmh 1.1-RC4; GNU Emacs 21.4.1
> Date: Fri, 01 Sep 2006 15:12:44 -0700
> From: Jay Vosburgh <[EMAIL PROTECTED]>
> 
> 
> The bonding driver fails to adjust its hard_header_len when enslaving
> interfaces.  Whenever an interface with a hard_header_len greater than the
> ETH_HLEN default is enslaved, the potential for an oops exists, and if the
> oops happens while responding to an arp request, for example, the system
> panics.  GIANFAR devices may use an extended hard_header for VLAN or
> hardware checksumming.  Enslaving such a device and then transmitting over
> it causes a kernel panic.
> 
> Patch modified from submitter's original, but submitter agreed with this
> patch in private email.
> 
> Signed-off-by: Mark Huth <[EMAIL PROTECTED]>
> Signed-off-by: Jay Vosburgh <[EMAIL PROTECTED]>
> 
> 
> --- netdev-2.6.git-upstream/drivers/net/bonding/bond_main.c   2006/08/19 
> 14:46:07 1.3
> +++ netdev-2.6.git-upstream/drivers/net/bonding/bond_main.c   2006/08/19 
> 15:47:27 1.4
> @@ -1211,10 +1211,14 @@ static int bond_compute_features(struct 
>   unsigned long features = BOND_INTERSECT_FEATURES;
>   struct slave *slave;
>   struct net_device *bond_dev = bond->dev;
> + unsigned short max_hard_header_len = ETH_HLEN;
>   int i;
>  
> - bond_for_each_slave(bond, slave, i)
> + bond_for_each_slave(bond, slave, i) {
>   features &= (slave->dev->features & BOND_INTERSECT_FEATURES);
> + if (slave->dev->hard_header_len > max_hard_header_len)
> + max_hard_header_len = slave->dev->hard_header_len;
> + }
>  
>   if ((features & NETIF_F_SG) && 
>   !(features & NETIF_F_ALL_CSUM))
> @@ -1232,6 +1236,7 @@ static int bond_compute_features(struct 
>  
>   features |= (bond_dev->features & ~BOND_INTERSECT_FEATURES);
>   bond_dev->features = features;
> + bond_dev->hard_header_len = max_hard_header_len;
>  
>   return 0;
>  }
> 
> 
> 
>   -J
> 
> ---
>   -Jay Vosburgh, IBM Linux Technology Center, [EMAIL PROTECTED]
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 6/9] s390: qeth driver fixes [3/6]

2006-09-15 Thread Jay Vosburgh
Frank Pavlic <[EMAIL PROTECTED]> wrote:

>[PATCH 6/9] s390: qeth driver fixes [3/6]
>
>From: Frank Pavlic <[EMAIL PROTECTED]>
>   fixed kernel panic caused by qeth driver:
>Using a bonding device qeth driver will realloc
>headroom for every skb coming from the bond device.
>Once this happens qeth frees the original skb and
>set the skb pointer to the new realloced skb.

Frank, does the following patch to bonding (to track larger than
usual hard_header_len) resolve this problem without changing qeth?  I
believe this patch is queued for 2.6.19.

To: netdev@vger.kernel.org, [EMAIL PROTECTED]
Cc: Jeff Garzik <[EMAIL PROTECTED]>
Subject: [PATCH 5/7] bonding: Handle large hard_header_len
X-Mailer: MH-E 7.83; nmh 1.1-RC4; GNU Emacs 21.4.1
Date: Fri, 01 Sep 2006 15:12:44 -0700
From: Jay Vosburgh <[EMAIL PROTECTED]>


The bonding driver fails to adjust its hard_header_len when enslaving
interfaces.  Whenever an interface with a hard_header_len greater than the
ETH_HLEN default is enslaved, the potential for an oops exists, and if the
oops happens while responding to an arp request, for example, the system
panics.  GIANFAR devices may use an extended hard_header for VLAN or
hardware checksumming.  Enslaving such a device and then transmitting over
it causes a kernel panic.

Patch modified from submitter's original, but submitter agreed with this
patch in private email.

Signed-off-by: Mark Huth <[EMAIL PROTECTED]>
Signed-off-by: Jay Vosburgh <[EMAIL PROTECTED]>


--- netdev-2.6.git-upstream/drivers/net/bonding/bond_main.c 2006/08/19 
14:46:07 1.3
+++ netdev-2.6.git-upstream/drivers/net/bonding/bond_main.c 2006/08/19 
15:47:27 1.4
@@ -1211,10 +1211,14 @@ static int bond_compute_features(struct 
unsigned long features = BOND_INTERSECT_FEATURES;
struct slave *slave;
struct net_device *bond_dev = bond->dev;
+   unsigned short max_hard_header_len = ETH_HLEN;
int i;
 
-   bond_for_each_slave(bond, slave, i)
+   bond_for_each_slave(bond, slave, i) {
features &= (slave->dev->features & BOND_INTERSECT_FEATURES);
+   if (slave->dev->hard_header_len > max_hard_header_len)
+   max_hard_header_len = slave->dev->hard_header_len;
+   }
 
if ((features & NETIF_F_SG) && 
!(features & NETIF_F_ALL_CSUM))
@@ -1232,6 +1236,7 @@ static int bond_compute_features(struct 
 
features |= (bond_dev->features & ~BOND_INTERSECT_FEATURES);
bond_dev->features = features;
+   bond_dev->hard_header_len = max_hard_header_len;
 
return 0;
 }



-J

---
-Jay Vosburgh, IBM Linux Technology Center, [EMAIL PROTECTED]
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 6/9] s390: qeth driver fixes [3/6]

2006-09-15 Thread Frank Pavlic
[PATCH 6/9] s390: qeth driver fixes [3/6]

From: Frank Pavlic <[EMAIL PROTECTED]>
fixed kernel panic caused by qeth driver:
Using a bonding device qeth driver will realloc
headroom for every skb coming from the bond device.
Once this happens qeth frees the original skb and
set the skb pointer to the new realloced skb.
Under heavy transmit workload (e.g.UDP streams) through bond
network device the qdio output queue might get full.
In this case we return with EBUSY from qeth_send_packet.
Returning to qeth_hard_start_xmit routine
the skb address on the stack still points to the old address,
which has been freed before.
Returning from qeth_hard_start_xmit with EBUSY results in
requeuing the skb. In this case it corrupts the qdisc queue
and results in kernel panic.

Signed-off-by: Frank Pavlic <[EMAIL PROTECTED]>
---

 drivers/s390/net/qeth.h  |   33 +++
 drivers/s390/net/qeth_main.c |  193 ++
 drivers/s390/net/qeth_tso.h  |2 
 3 files changed, 113 insertions(+), 115 deletions(-)

80a8bd094c70579c027f15838501759ab8f3331d
diff --git a/drivers/s390/net/qeth.h b/drivers/s390/net/qeth.h
index e8bd8c5..c04ee91 100644
--- a/drivers/s390/net/qeth.h
+++ b/drivers/s390/net/qeth.h
@@ -859,23 +859,18 @@ qeth_get_ipa_adp_type(enum qeth_link_typ
}
 }
 
-static inline int
-qeth_realloc_headroom(struct qeth_card *card, struct sk_buff **skb, int size)
+static inline struct sk_buff *
+qeth_realloc_headroom(struct qeth_card *card, struct sk_buff *skb, int size)
 {
-   struct sk_buff *new_skb = NULL;
+   struct sk_buff *new_skb = skb;
 
-   if (skb_headroom(*skb) < size){
-   new_skb = skb_realloc_headroom(*skb, size);
-   if (!new_skb) {
-PRINT_ERR("qeth_prepare_skb: could "
-  "not realloc headroom for qeth_hdr "
-  "on interface %s", QETH_CARD_IFNAME(card));
-return -ENOMEM;
-}
-   kfree_skb(*skb);
-*skb = new_skb;
-   }
-   return 0;
+   if (skb_headroom(skb) >= size)
+   return skb;
+   new_skb = skb_realloc_headroom(skb, size);
+   if (!new_skb) 
+   PRINT_ERR("Could not realloc headroom for qeth_hdr "
+ "on interface %s", QETH_CARD_IFNAME(card));
+   return new_skb;
 }
 
 static inline struct sk_buff *
@@ -885,16 +880,15 @@ qeth_pskb_unshare(struct sk_buff *skb, i
 if (!skb_cloned(skb))
 return skb;
 nskb = skb_copy(skb, pri);
-kfree_skb(skb); /* free our shared copy */
 return nskb;
 }
 
 static inline void *
-qeth_push_skb(struct qeth_card *card, struct sk_buff **skb, int size)
+qeth_push_skb(struct qeth_card *card, struct sk_buff *skb, int size)
 {
 void *hdr;
 
-   hdr = (void *) skb_push(*skb, size);
+   hdr = (void *) skb_push(skb, size);
 /*
  * sanity check, the Linux memory allocation scheme should
  * never present us cases like this one (the qdio header size plus
@@ -903,8 +897,7 @@ qeth_push_skb(struct qeth_card *card, st
 if unsigned long) hdr) & (~(PAGE_SIZE - 1))) !=
 (((unsigned long) hdr + size +
   QETH_IP_HEADER_SIZE) & (~(PAGE_SIZE - 1 {
-PRINT_ERR("qeth_prepare_skb: misaligned "
-  "packet on interface %s. Discarded.",
+PRINT_ERR("Misaligned packet on interface %s. Discarded.",
   QETH_CARD_IFNAME(card));
 return NULL;
 }
diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c
index 7a1..522fb9d 100644
--- a/drivers/s390/net/qeth_main.c
+++ b/drivers/s390/net/qeth_main.c
@@ -3919,49 +3919,59 @@ qeth_get_ip_version(struct sk_buff *skb)
}
 }
 
-static inline int
-qeth_prepare_skb(struct qeth_card *card, struct sk_buff **skb,
-struct qeth_hdr **hdr, int ipv)
+static inline struct qeth_hdr *
+__qeth_prepare_skb(struct qeth_card *card, struct sk_buff *skb, int ipv)
 {
-   int rc = 0;
 #ifdef CONFIG_QETH_VLAN
u16 *tag;
-#endif
-
-   QETH_DBF_TEXT(trace, 6, "prepskb");
-   if (card->info.type == QETH_CARD_TYPE_OSN) {
-   *hdr = (struct qeth_hdr *)(*skb)->data;
-   return rc;
-   }
-rc = qeth_realloc_headroom(card, skb, sizeof(struct qeth_hdr));
-if (rc)
-return rc;
-#ifdef CONFIG_QETH_VLAN
-   if (card->vlangrp && vlan_tx_tag_present(*skb) &&
+   if (card->vlangrp && vlan_tx_tag_present(skb) &&
((ipv == 6) || card->options.layer2) ) {

[PATCH 6/9] s390: qeth driver fixes [3/6]

2006-09-06 Thread fpavlic
[PATCH 6/9] s390: qeth driver fixes [3/6]

From: Frank Pavlic <[EMAIL PROTECTED]>
fixed kernel panic caused by qeth driver:
Using a bonding device qeth driver will realloc
headroom for every skb coming from the bond device.
Once this happens qeth frees the original skb and
set the skb pointer to the new realloced skb.
Under heavy transmit workload (e.g.UDP streams) through bond
network device the qdio output queue might get full.
In this case we return with EBUSY from qeth_send_packet.
Returning to qeth_hard_start_xmit routine
the skb address on the stack still points to the old address,
which has been freed before.
Returning from qeth_hard_start_xmit with EBUSY results in
requeuing the skb. In this case it corrupts the qdisc queue
and results in kernel panic.

Signed-off-by: Frank Pavlic <[EMAIL PROTECTED]>
---

 drivers/s390/net/qeth.h  |   33 +++
 drivers/s390/net/qeth_main.c |  193 
++
 drivers/s390/net/qeth_tso.h  |2 
 3 files changed, 113 insertions(+), 115 deletions(-)

80a8bd094c70579c027f15838501759ab8f3331d
diff --git a/drivers/s390/net/qeth.h b/drivers/s390/net/qeth.h
index e8bd8c5..c04ee91 100644
--- a/drivers/s390/net/qeth.h
+++ b/drivers/s390/net/qeth.h
@@ -859,23 +859,18 @@ qeth_get_ipa_adp_type(enum qeth_link_typ
  }
 }
 
-static inline int
-qeth_realloc_headroom(struct qeth_card *card, struct sk_buff **skb, int size)
+static inline struct sk_buff *
+qeth_realloc_headroom(struct qeth_card *card, struct sk_buff *skb, int size)
 {
- struct sk_buff *new_skb = NULL;
+ struct sk_buff *new_skb = skb;
 
- if (skb_headroom(*skb) < size){
-  new_skb = skb_realloc_headroom(*skb, size);
-  if (!new_skb) {
-PRINT_ERR("qeth_prepare_skb: could "
-  "not realloc headroom for qeth_hdr "
-  "on interface %s", QETH_CARD_IFNAME(card));
-return -ENOMEM;
-}
-  kfree_skb(*skb);
-*skb = new_skb;
- }
- return 0;
+ if (skb_headroom(skb) >= size)
+  return skb;
+ new_skb = skb_realloc_headroom(skb, size);
+ if (!new_skb) 
+  PRINT_ERR("Could not realloc headroom for qeth_hdr "
+ "on interface %s", QETH_CARD_IFNAME(card));
+ return new_skb;
 }
 
 static inline struct sk_buff *
@@ -885,16 +880,15 @@ qeth_pskb_unshare(struct sk_buff *skb, i
 if (!skb_cloned(skb))
 return skb;
 nskb = skb_copy(skb, pri);
-kfree_skb(skb); /* free our shared copy */
 return nskb;
 }
 
 static inline void *
-qeth_push_skb(struct qeth_card *card, struct sk_buff **skb, int size)
+qeth_push_skb(struct qeth_card *card, struct sk_buff *skb, int size)
 {
 void *hdr;
 
- hdr = (void *) skb_push(*skb, size);
+ hdr = (void *) skb_push(skb, size);
 /*
  * sanity check, the Linux memory allocation scheme should
  * never present us cases like this one (the qdio header size plus
@@ -903,8 +897,7 @@ qeth_push_skb(struct qeth_card *card, st
 if unsigned long) hdr) & (~(PAGE_SIZE - 1))) !=
 (((unsigned long) hdr + size +
   QETH_IP_HEADER_SIZE) & (~(PAGE_SIZE - 1 {
-PRINT_ERR("qeth_prepare_skb: misaligned "
-  "packet on interface %s. Discarded.",
+PRINT_ERR("Misaligned packet on interface %s. Discarded.",
   QETH_CARD_IFNAME(card));
 return NULL;
 }
diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c
index 7a1..522fb9d 100644
--- a/drivers/s390/net/qeth_main.c
+++ b/drivers/s390/net/qeth_main.c
@@ -3919,49 +3919,59 @@ qeth_get_ip_version(struct sk_buff *skb)
  }
 }
 
-static inline int
-qeth_prepare_skb(struct qeth_card *card, struct sk_buff **skb,
-   struct qeth_hdr **hdr, int ipv)
+static inline struct qeth_hdr *
+__qeth_prepare_skb(struct qeth_card *card, struct sk_buff *skb, int ipv)
 {
- int rc = 0;
 #ifdef CONFIG_QETH_VLAN
  u16 *tag;
-#endif
-
- QETH_DBF_TEXT(trace, 6, "prepskb");
- if (card->info.type == QETH_CARD_TYPE_OSN) {
-  *hdr = (struct qeth_hdr *)(*skb)->data;
-  return rc;
- }
-rc = qeth_realloc_headroom(card, skb, sizeof(struct qeth_hdr));
-if (rc)
-return rc;
-#ifdef CONFIG_QETH_VLAN
- if (card->vlangrp && vlan_tx_tag_present(*skb) &&
+ if (card->vlangrp && vlan_tx_tag_present(skb) &&
  ((ipv == 6) || card->options.layer2) ) {
   /*
* Move the mac addresses (6 bytes src, 6 bytes dest)
* to the beginning of the new header.  We are using three
* memcpys instead of one memmove to save cycles.
*/
-  skb_push(*skb, VLAN_HLEN);
-  memcpy((*skb)->data, (*skb)->data + 4,