Skip to content

Commit

Permalink
netpoll: convert mutex into a semaphore
Browse files Browse the repository at this point in the history
Bart Van Assche recently reported a warning to me:

<IRQ>  [<ffffffff8103d79f>] warn_slowpath_common+0x7f/0xc0
[<ffffffff8103d7fa>] warn_slowpath_null+0x1a/0x20
[<ffffffff814761dd>] mutex_trylock+0x16d/0x180
[<ffffffff813968c9>] netpoll_poll_dev+0x49/0xc30
[<ffffffff8136a2d2>] ? __alloc_skb+0x82/0x2a0
[<ffffffff81397715>] netpoll_send_skb_on_dev+0x265/0x410
[<ffffffff81397c5a>] netpoll_send_udp+0x28a/0x3a0
[<ffffffffa0541843>] ? write_msg+0x53/0x110 [netconsole]
[<ffffffffa05418bf>] write_msg+0xcf/0x110 [netconsole]
[<ffffffff8103eba1>] call_console_drivers.constprop.17+0xa1/0x1c0
[<ffffffff8103fb76>] console_unlock+0x2d6/0x450
[<ffffffff8104011e>] vprintk_emit+0x1ee/0x510
[<ffffffff8146f9f6>] printk+0x4d/0x4f
[<ffffffffa0004f1d>] scsi_print_command+0x7d/0xe0 [scsi_mod]

This resulted from my commit ca99ca1 which introduced a mutex_trylock
operation in a path that could execute in interrupt context.  When mutex
debugging is enabled, the above warns the user when we are in fact
exectuting in interrupt context
interrupt context.

After some discussion, It seems that a semaphore is the proper mechanism to use
here.  While mutexes are defined to be unusable in interrupt context, no such
condition exists for semaphores (save for the fact that the non blocking api
calls, like up and down_trylock must be used when in irq context).

Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
Reported-by: Bart Van Assche <bvanassche@acm.org>
CC: Bart Van Assche <bvanassche@acm.org>
CC: David Miller <davem@davemloft.net>
CC: netdev@vger.kernel.org
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Neil Horman authored and David S. Miller committed May 1, 2013
1 parent ae6164a commit bd7c4b6
Show file tree
Hide file tree
Showing 2 changed files with 8 additions and 8 deletions.
2 changes: 1 addition & 1 deletion include/linux/netpoll.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ struct netpoll_info {

unsigned long rx_flags;
spinlock_t rx_lock;
struct mutex dev_lock;
struct semaphore dev_lock;
struct list_head rx_np; /* netpolls that registered an rx_hook */

struct sk_buff_head neigh_tx; /* list of neigh requests to reply to */
Expand Down
14 changes: 7 additions & 7 deletions net/core/netpoll.c
Original file line number Diff line number Diff line change
Expand Up @@ -206,17 +206,17 @@ static void netpoll_poll_dev(struct net_device *dev)
* the dev_open/close paths use this to block netpoll activity
* while changing device state
*/
if (!mutex_trylock(&ni->dev_lock))
if (!down_trylock(&ni->dev_lock))
return;

if (!netif_running(dev)) {
mutex_unlock(&ni->dev_lock);
up(&ni->dev_lock);
return;
}

ops = dev->netdev_ops;
if (!ops->ndo_poll_controller) {
mutex_unlock(&ni->dev_lock);
up(&ni->dev_lock);
return;
}

Expand All @@ -225,7 +225,7 @@ static void netpoll_poll_dev(struct net_device *dev)

poll_napi(dev);

mutex_unlock(&ni->dev_lock);
up(&ni->dev_lock);

if (dev->flags & IFF_SLAVE) {
if (ni) {
Expand Down Expand Up @@ -255,7 +255,7 @@ int netpoll_rx_disable(struct net_device *dev)
idx = srcu_read_lock(&netpoll_srcu);
ni = srcu_dereference(dev->npinfo, &netpoll_srcu);
if (ni)
mutex_lock(&ni->dev_lock);
down(&ni->dev_lock);
srcu_read_unlock(&netpoll_srcu, idx);
return 0;
}
Expand All @@ -267,7 +267,7 @@ void netpoll_rx_enable(struct net_device *dev)
rcu_read_lock();
ni = rcu_dereference(dev->npinfo);
if (ni)
mutex_unlock(&ni->dev_lock);
up(&ni->dev_lock);
rcu_read_unlock();
}
EXPORT_SYMBOL(netpoll_rx_enable);
Expand Down Expand Up @@ -1047,7 +1047,7 @@ int __netpoll_setup(struct netpoll *np, struct net_device *ndev, gfp_t gfp)
INIT_LIST_HEAD(&npinfo->rx_np);

spin_lock_init(&npinfo->rx_lock);
mutex_init(&npinfo->dev_lock);
sema_init(&npinfo->dev_lock, 1);
skb_queue_head_init(&npinfo->neigh_tx);
skb_queue_head_init(&npinfo->txq);
INIT_DELAYED_WORK(&npinfo->tx_work, queue_process);
Expand Down

0 comments on commit bd7c4b6

Please sign in to comment.