On Mon, Jun 12, 2006 at 10:51:21AM -0500, Matt Mackall wrote:
> On Mon, Jun 12, 2006 at 11:40:29AM -0400, Neil Horman wrote:
> > Hey there-
> >     the netpoll system currently has a rx to tx path via:
> > netpoll_rx
> >  __netpoll_rx
> >   arp_reply
> >    netpoll_send_skb
> >     dev->hard_start_tx
> > 
> >     This rx->tx loop places network drivers at risk of
> > inadvertently causing a deadlock or BUG halt by recursively trying
> > to acquire a spinlock that is used in both their rx and tx paths
> > (this problem was origionally reported to me in the 3c59x driver,
> > which shares a spinlock between the boomerang_interrupt and
> > boomerang_start_xmit routines).
> 
> Grumble.
> 
> > This patch breaks this loop, by queueing arp frames, so that they
> > can be responded to after all receive operations have been
> > completed. Tested by myself and the reported with successful
> > results.
> 
> Tested how? kgdb?
> 
Specifically It was tested with netdump.  Heres the BZ with details:
https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=194055


> > +   if (likely(npi))
> > +           while ((skb = skb_dequeue(&npi->arp_tx)) != NULL)
> > +                   arp_reply(skb);
> > +
> 
> Assignment inside tests is frowned upon. I'd prefer pulling this out
> to its own function too.
> 
Sure, no problem.  New patch attached with suggested modifications made

Regards
Neil

Signed-off-by: Neil Horman <[EMAIL PROTECTED]>

 include/linux/netpoll.h |    1 +
 net/core/netpoll.c      |   27 +++++++++++++++++++++++++--
 2 files changed, 26 insertions(+), 2 deletions(-)


--- linux-2.6/include/linux/netpoll.h.orig      2006-06-12 09:11:01.000000000 
-0400
+++ linux-2.6/include/linux/netpoll.h   2006-06-12 09:34:17.000000000 -0400
@@ -31,6 +31,7 @@ struct netpoll_info {
        int rx_flags;
        spinlock_t rx_lock;
        struct netpoll *rx_np; /* netpoll that registered an rx_hook */
+       struct sk_buff_head arp_tx; /* list of arp requests to reply to */
 };
 
 void netpoll_poll(struct netpoll *np);
--- linux-2.6/net/core/netpoll.c.orig   2006-06-12 09:11:01.000000000 -0400
+++ linux-2.6/net/core/netpoll.c        2006-06-12 13:43:25.000000000 -0400
@@ -54,6 +54,7 @@ static atomic_t trapped;
                                sizeof(struct iphdr) + sizeof(struct ethhdr))
 
 static void zap_completion_queue(void);
+static void arp_reply(struct sk_buff *skb);
 
 static void queue_process(void *p)
 {
@@ -153,8 +154,25 @@ static void poll_napi(struct netpoll *np
        }
 }
 
+static void service_arp_queue(struct netpoll_info *npi)
+{
+       struct sk_buff *skb;
+
+       if(unlikely(!npi))
+               return;
+
+       skb = skb_dequeue(&npi->arp_tx);
+
+       while (skb != NULL) {
+               arp_reply(skb);
+               skb = skb_dequeue(&npi->arp_tx);                
+       }
+       return;
+}
+
 void netpoll_poll(struct netpoll *np)
 {
+
        if(!np->dev || !netif_running(np->dev) || !np->dev->poll_controller)
                return;
 
@@ -163,6 +181,8 @@ void netpoll_poll(struct netpoll *np)
        if (np->dev->poll)
                poll_napi(np);
 
+       service_arp_queue(np->dev->npinfo);
+
        zap_completion_queue();
 }
 
@@ -449,7 +469,9 @@ int __netpoll_rx(struct sk_buff *skb)
        int proto, len, ulen;
        struct iphdr *iph;
        struct udphdr *uh;
-       struct netpoll *np = skb->dev->npinfo->rx_np;
+       struct netpoll_info *npi = skb->dev->npinfo;
+       struct netpoll *np = npi->rx_np;
+
 
        if (!np)
                goto out;
@@ -459,7 +481,7 @@ int __netpoll_rx(struct sk_buff *skb)
        /* check if netpoll clients need ARP */
        if (skb->protocol == __constant_htons(ETH_P_ARP) &&
            atomic_read(&trapped)) {
-               arp_reply(skb);
+               skb_queue_tail(&npi->arp_tx, skb);
                return 1;
        }
 
@@ -654,6 +676,7 @@ int netpoll_setup(struct netpoll *np)
                npinfo->poll_owner = -1;
                npinfo->tries = MAX_RETRIES;
                spin_lock_init(&npinfo->rx_lock);
+               skb_queue_head_init(&npinfo->arp_tx);
        } else
                npinfo = ndev->npinfo;
 
-- 
/***************************************************
 *Neil Horman
 *Software Engineer
 *gpg keyid: 1024D / 0x92A74FA1 - http://pgp.mit.edu
 ***************************************************/
-
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

Reply via email to