lkml.org 
[lkml]   [2007]   [Apr]   [23]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[PATCH 23/25] xen: Lockdep fixes for xen-netfront
    netfront contains two locking problems found by lockdep:

    1. rx_lock is a normal spinlock, and tx_lock is an irq spinlock. This
    means that in normal use, tx_lock may be taken by an interrupt routine
    while rx_lock is held. However, netif_disconnect_backend takes them
    in the order tx_lock->rx_lock, which could lead to a deadlock. Reverse
    them
    2. rx_lock can also be taken in softirq context, so it should be taken/released
    with spin_(un)lock_bh.

    Signed-off-by: Jeremy Fitzhardinge <jeremy@xensource.com>
    Cc: Chris Wright <chrisw@sous-sol.org>
    Cc: Christian Limpach <Christian.Limpach@cl.cam.ac.uk>

    ---
    drivers/net/xen-netfront.c | 30 +++++++++++++++---------------
    1 file changed, 15 insertions(+), 15 deletions(-)

    ===================================================================
    --- a/drivers/net/xen-netfront.c
    +++ b/drivers/net/xen-netfront.c
    @@ -515,14 +515,14 @@ static int network_open(struct net_devic

    memset(&np->stats, 0, sizeof(np->stats));

    - spin_lock(&np->rx_lock);
    + spin_lock_bh(&np->rx_lock);
    if (netfront_carrier_ok(np)) {
    network_alloc_rx_buffers(dev);
    np->rx.sring->rsp_event = np->rx.rsp_cons + 1;
    if (RING_HAS_UNCONSUMED_RESPONSES(&np->rx))
    netif_rx_schedule(dev);
    }
    - spin_unlock(&np->rx_lock);
    + spin_unlock_bh(&np->rx_lock);

    network_maybe_wake_tx(dev);

    @@ -1212,10 +1212,10 @@ static int netif_poll(struct net_device
    int pages_flipped = 0;
    int err;

    - spin_lock(&np->rx_lock);
    + spin_lock_bh(&np->rx_lock);

    if (unlikely(!netfront_carrier_ok(np))) {
    - spin_unlock(&np->rx_lock);
    + spin_unlock_bh(&np->rx_lock);
    return 0;
    }

    @@ -1356,7 +1356,7 @@ err:
    local_irq_restore(flags);
    }

    - spin_unlock(&np->rx_lock);
    + spin_unlock_bh(&np->rx_lock);

    return more_to_do;
    }
    @@ -1399,7 +1399,7 @@ static void netif_release_rx_bufs(struct

    skb_queue_head_init(&free_list);

    - spin_lock(&np->rx_lock);
    + spin_lock_bh(&np->rx_lock);

    for (id = 0; id < NET_RX_RING_SIZE; id++) {
    if ((ref = np->grant_rx_ref[id]) == GRANT_INVALID_REF) {
    @@ -1469,7 +1469,7 @@ static void netif_release_rx_bufs(struct
    while ((skb = __skb_dequeue(&free_list)) != NULL)
    dev_kfree_skb(skb);

    - spin_unlock(&np->rx_lock);
    + spin_unlock_bh(&np->rx_lock);
    }

    static int network_close(struct net_device *dev)
    @@ -1579,8 +1579,8 @@ static int network_connect(struct net_de
    dev_info(&dev->dev, "has %sing receive path.\n",
    np->copying_receiver ? "copy" : "flipp");

    + spin_lock_bh(&np->rx_lock);
    spin_lock_irq(&np->tx_lock);
    - spin_lock(&np->rx_lock);

    /*
    * Recovery procedure:
    @@ -1632,8 +1632,8 @@ static int network_connect(struct net_de
    network_tx_buf_gc(dev);
    network_alloc_rx_buffers(dev);

    - spin_unlock(&np->rx_lock);
    spin_unlock_irq(&np->tx_lock);
    + spin_unlock_bh(&np->rx_lock);

    return 0;
    }
    @@ -1689,7 +1689,7 @@ static ssize_t store_rxbuf_min(struct de
    if (target > RX_MAX_TARGET)
    target = RX_MAX_TARGET;

    - spin_lock(&np->rx_lock);
    + spin_lock_bh(&np->rx_lock);
    if (target > np->rx_max_target)
    np->rx_max_target = target;
    np->rx_min_target = target;
    @@ -1698,7 +1698,7 @@ static ssize_t store_rxbuf_min(struct de

    network_alloc_rx_buffers(netdev);

    - spin_unlock(&np->rx_lock);
    + spin_unlock_bh(&np->rx_lock);
    return len;
    }

    @@ -1732,7 +1732,7 @@ static ssize_t store_rxbuf_max(struct de
    if (target > RX_MAX_TARGET)
    target = RX_MAX_TARGET;

    - spin_lock(&np->rx_lock);
    + spin_lock_bh(&np->rx_lock);
    if (target < np->rx_min_target)
    np->rx_min_target = target;
    np->rx_max_target = target;
    @@ -1741,7 +1741,7 @@ static ssize_t store_rxbuf_max(struct de

    network_alloc_rx_buffers(netdev);

    - spin_unlock(&np->rx_lock);
    + spin_unlock_bh(&np->rx_lock);
    return len;
    }

    @@ -1885,11 +1885,11 @@ static void netif_disconnect_backend(str
    static void netif_disconnect_backend(struct netfront_info *info)
    {
    /* Stop old i/f to prevent errors whilst we rebuild the state. */
    + spin_lock_bh(&info->rx_lock);
    spin_lock_irq(&info->tx_lock);
    - spin_lock(&info->rx_lock);
    netfront_carrier_off(info);
    - spin_unlock(&info->rx_lock);
    spin_unlock_irq(&info->tx_lock);
    + spin_unlock_bh(&info->rx_lock);

    if (info->irq)
    unbind_from_irqhandler(info->irq, info->netdev);
    --

    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

    \
     
     \ /
      Last update: 2007-04-24 01:19    [W:3.218 / U:0.020 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site