ia64/xen-unstable

changeset 11938:637eace6d5c6

[NET] back: Fix packet queuing so that packets are drained if the
interface is blocked for longer than 500ms. This avoids deadlock
situations where interfaces cannot be destroyed because some other
dormant interface is holding resources.

Signed-off-by: Christopher Clark <christopher.clark@cl.cam.ac.uk>
Signed-off-by: Keir Fraser <keir@xensource.com>
author kfraser@localhost.localdomain
date Mon Oct 23 11:20:37 2006 +0100 (2006-10-23)
parents d2ba4ac36168
children 6f72d00fc1ec
files linux-2.6-xen-sparse/drivers/xen/netback/common.h linux-2.6-xen-sparse/drivers/xen/netback/interface.c linux-2.6-xen-sparse/drivers/xen/netback/netback.c linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c
line diff
     1.1 --- a/linux-2.6-xen-sparse/drivers/xen/netback/common.h	Mon Oct 23 10:05:32 2006 +0100
     1.2 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/common.h	Mon Oct 23 11:20:37 2006 +0100
     1.3 @@ -92,6 +92,9 @@ typedef struct netif_st {
     1.4  	unsigned long   remaining_credit;
     1.5  	struct timer_list credit_timeout;
     1.6  
     1.7 +	/* Enforce draining of the transmit queue. */
     1.8 +	struct timer_list tx_queue_timeout;
     1.9 +
    1.10  	/* Miscellaneous private stuff. */
    1.11  	struct list_head list;  /* scheduling list */
    1.12  	atomic_t         refcnt;
    1.13 @@ -119,6 +122,8 @@ int netif_map(netif_t *netif, unsigned l
    1.14  
    1.15  void netif_xenbus_init(void);
    1.16  
    1.17 +#define netif_schedulable(dev) (netif_running(dev) && netif_carrier_ok(dev))
    1.18 +
    1.19  void netif_schedule_work(netif_t *netif);
    1.20  void netif_deschedule_work(netif_t *netif);
    1.21  
     2.1 --- a/linux-2.6-xen-sparse/drivers/xen/netback/interface.c	Mon Oct 23 10:05:32 2006 +0100
     2.2 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/interface.c	Mon Oct 23 11:20:37 2006 +0100
     2.3 @@ -44,12 +44,11 @@
     2.4   * For example, consider a packet that holds onto resources belonging to the
     2.5   * guest for which it is queued (e.g., packet received on vif1.0, destined for
     2.6   * vif1.1 which is not activated in the guest): in this situation the guest
     2.7 - * will never be destroyed, unless vif1.1 is taken down (which flushes the
     2.8 - * 'tx_queue').
     2.9 - * 
    2.10 - * Only set this parameter to non-zero value if you know what you are doing!
    2.11 + * will never be destroyed, unless vif1.1 is taken down. To avoid this, we
    2.12 + * run a timer (tx_queue_timeout) to drain the queue when the interface is
    2.13 + * blocked.
    2.14   */
    2.15 -static unsigned long netbk_queue_length = 0;
    2.16 +static unsigned long netbk_queue_length = 32;
    2.17  module_param_named(queue_length, netbk_queue_length, ulong, 0);
    2.18  
    2.19  static void __netif_up(netif_t *netif)
    2.20 @@ -62,7 +61,6 @@ static void __netif_down(netif_t *netif)
    2.21  {
    2.22  	disable_irq(netif->irq);
    2.23  	netif_deschedule_work(netif);
    2.24 -	del_timer_sync(&netif->credit_timeout);
    2.25  }
    2.26  
    2.27  static int net_open(struct net_device *dev)
    2.28 @@ -153,8 +151,11 @@ netif_t *netif_alloc(domid_t domid, unsi
    2.29  	netif->credit_bytes = netif->remaining_credit = ~0UL;
    2.30  	netif->credit_usec  = 0UL;
    2.31  	init_timer(&netif->credit_timeout);
    2.32 +	/* Initialize 'expires' now: it's used to track the credit window. */
    2.33  	netif->credit_timeout.expires = jiffies;
    2.34  
    2.35 +	init_timer(&netif->tx_queue_timeout);
    2.36 +
    2.37  	dev->hard_start_xmit = netif_be_start_xmit;
    2.38  	dev->get_stats       = netif_be_get_stats;
    2.39  	dev->open            = net_open;
    2.40 @@ -319,11 +320,23 @@ err_rx:
    2.41  	return err;
    2.42  }
    2.43  
    2.44 -static void netif_free(netif_t *netif)
    2.45 +void netif_disconnect(netif_t *netif)
    2.46  {
    2.47 +	if (netif_carrier_ok(netif->dev)) {
    2.48 +		rtnl_lock();
    2.49 +		netif_carrier_off(netif->dev);
    2.50 +		if (netif_running(netif->dev))
    2.51 +			__netif_down(netif);
    2.52 +		rtnl_unlock();
    2.53 +		netif_put(netif);
    2.54 +	}
    2.55 +
    2.56  	atomic_dec(&netif->refcnt);
    2.57  	wait_event(netif->waiting_to_free, atomic_read(&netif->refcnt) == 0);
    2.58  
    2.59 +	del_timer_sync(&netif->credit_timeout);
    2.60 +	del_timer_sync(&netif->tx_queue_timeout);
    2.61 +
    2.62  	if (netif->irq)
    2.63  		unbind_from_irqhandler(netif->irq, netif);
    2.64  	
    2.65 @@ -337,16 +350,3 @@ static void netif_free(netif_t *netif)
    2.66  
    2.67  	free_netdev(netif->dev);
    2.68  }
    2.69 -
    2.70 -void netif_disconnect(netif_t *netif)
    2.71 -{
    2.72 -	if (netif_carrier_ok(netif->dev)) {
    2.73 -		rtnl_lock();
    2.74 -		netif_carrier_off(netif->dev);
    2.75 -		if (netif_running(netif->dev))
    2.76 -			__netif_down(netif);
    2.77 -		rtnl_unlock();
    2.78 -		netif_put(netif);
    2.79 -	}
    2.80 -	netif_free(netif);
    2.81 -}
     3.1 --- a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c	Mon Oct 23 10:05:32 2006 +0100
     3.2 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c	Mon Oct 23 11:20:37 2006 +0100
     3.3 @@ -264,6 +264,13 @@ static inline int netbk_queue_full(netif
     3.4  	       ((netif->rx.rsp_prod_pvt + NET_RX_RING_SIZE - peek) < needed);
     3.5  }
     3.6  
     3.7 +static void tx_queue_callback(unsigned long data)
     3.8 +{
     3.9 +	netif_t *netif = (netif_t *)data;
    3.10 +	if (netif_schedulable(netif->dev))
    3.11 +		netif_wake_queue(netif->dev);
    3.12 +}
    3.13 +
    3.14  int netif_be_start_xmit(struct sk_buff *skb, struct net_device *dev)
    3.15  {
    3.16  	netif_t *netif = netdev_priv(dev);
    3.17 @@ -271,20 +278,13 @@ int netif_be_start_xmit(struct sk_buff *
    3.18  	BUG_ON(skb->dev != dev);
    3.19  
    3.20  	/* Drop the packet if the target domain has no receive buffers. */
    3.21 -	if (unlikely(!netif_running(dev) || !netif_carrier_ok(dev)))
    3.22 +	if (unlikely(!netif_schedulable(dev) || netbk_queue_full(netif)))
    3.23  		goto drop;
    3.24  
    3.25 -	if (unlikely(netbk_queue_full(netif))) {
    3.26 -		/* Not a BUG_ON() -- misbehaving netfront can trigger this. */
    3.27 -		if (netbk_can_queue(dev))
    3.28 -			DPRINTK("Queue full but not stopped!\n");
    3.29 -		goto drop;
    3.30 -	}
    3.31 -
    3.32 -	/* Copy the packet here if it's destined for a flipping
    3.33 -	   interface but isn't flippable (e.g. extra references to
    3.34 -	   data)
    3.35 -	*/
    3.36 +	/*
    3.37 +	 * Copy the packet here if it's destined for a flipping interface
    3.38 +	 * but isn't flippable (e.g. extra references to data).
    3.39 +	 */
    3.40  	if (!netif->copying_receiver && !is_flippable_skb(skb)) {
    3.41  		struct sk_buff *nskb = netbk_copy_skb(skb);
    3.42  		if ( unlikely(nskb == NULL) )
    3.43 @@ -305,8 +305,19 @@ int netif_be_start_xmit(struct sk_buff *
    3.44  		netif->rx.sring->req_event = netif->rx_req_cons_peek +
    3.45  			netbk_max_required_rx_slots(netif);
    3.46  		mb(); /* request notification /then/ check & stop the queue */
    3.47 -		if (netbk_queue_full(netif))
    3.48 +		if (netbk_queue_full(netif)) {
    3.49  			netif_stop_queue(dev);
    3.50 +			/*
    3.51 +			 * Schedule 500ms timeout to restart the queue, thus
    3.52 +			 * ensuring that an inactive queue will be drained.
    3.53 +			 * Packets will be immediately be dropped until more
    3.54 +			 * receive buffers become available (see
    3.55 +			 * netbk_queue_full() check above).
    3.56 +			 */
    3.57 +			netif->tx_queue_timeout.data = (unsigned long)netif;
    3.58 +			netif->tx_queue_timeout.function = tx_queue_callback;
    3.59 +			__mod_timer(&netif->tx_queue_timeout, jiffies + HZ/2);
    3.60 +		}
    3.61  	}
    3.62  
    3.63  	skb_queue_tail(&rx_queue, skb);
    3.64 @@ -706,6 +717,7 @@ static void net_rx_action(unsigned long 
    3.65  		}
    3.66  
    3.67  		if (netif_queue_stopped(netif->dev) &&
    3.68 +		    netif_schedulable(netif->dev) &&
    3.69  		    !netbk_queue_full(netif))
    3.70  			netif_wake_queue(netif->dev);
    3.71  
    3.72 @@ -763,8 +775,7 @@ static void add_to_net_schedule_list_tai
    3.73  
    3.74  	spin_lock_irq(&net_schedule_list_lock);
    3.75  	if (!__on_net_schedule_list(netif) &&
    3.76 -	    likely(netif_running(netif->dev) &&
    3.77 -		   netif_carrier_ok(netif->dev))) {
    3.78 +	    likely(netif_schedulable(netif->dev))) {
    3.79  		list_add_tail(&netif->list, &net_schedule_list);
    3.80  		netif_get(netif);
    3.81  	}
    3.82 @@ -1358,7 +1369,7 @@ irqreturn_t netif_be_int(int irq, void *
    3.83  	add_to_net_schedule_list_tail(netif);
    3.84  	maybe_schedule_tx_action();
    3.85  
    3.86 -	if (netif_queue_stopped(netif->dev) && !netbk_queue_full(netif))
    3.87 +	if (netif_schedulable(netif->dev) && !netbk_queue_full(netif))
    3.88  		netif_wake_queue(netif->dev);
    3.89  
    3.90  	return IRQ_HANDLED;
     4.1 --- a/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c	Mon Oct 23 10:05:32 2006 +0100
     4.2 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c	Mon Oct 23 11:20:37 2006 +0100
     4.3 @@ -328,7 +328,7 @@ static void connect(struct backend_info 
     4.4  
     4.5  	/* May not get a kick from the frontend, so start the tx_queue now. */
     4.6  	if (!netbk_can_queue(be->netif->dev))
     4.7 -		netif_start_queue(be->netif->dev);
     4.8 +		netif_wake_queue(be->netif->dev);
     4.9  }
    4.10  
    4.11