[PATCH] uml: fix spinlock recursion and sleep-inside-spinlock in error path
In this error path, when the interface has had a problem, we call dev_close(), which is disallowed for two reasons: *) takes again the UML internal spinlock, inside the ->stop method of this device *) can be called in process context only, while we're in interrupt context. I've also thought that calling dev_close() may be a wrong policy to follow, but it's not up to me to decide that. However, we may end up with multiple dev_close() queued on the same device. But the initial test for (dev->flags & IFF_UP) makes this harmless, though - and dev_close() is supposed to care about races with itself. So there's no harm in delaying the shutdown, IMHO. Something to mark the interface as "going to shutdown" would be appreciated, but dev_deactivate has the same problems as dev_close(), so we can't use it either. Signed-off-by: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it> Cc: Jeff Dike <jdike@addtoit.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
Родитель
e56a78855a
Коммит
71c8d4c3aa
|
@ -68,6 +68,11 @@ static int uml_net_rx(struct net_device *dev)
|
|||
return pkt_len;
|
||||
}
|
||||
|
||||
static void uml_dev_close(void* dev)
|
||||
{
|
||||
dev_close( (struct net_device *) dev);
|
||||
}
|
||||
|
||||
irqreturn_t uml_net_interrupt(int irq, void *dev_id, struct pt_regs *regs)
|
||||
{
|
||||
struct net_device *dev = dev_id;
|
||||
|
@ -80,15 +85,21 @@ irqreturn_t uml_net_interrupt(int irq, void *dev_id, struct pt_regs *regs)
|
|||
spin_lock(&lp->lock);
|
||||
while((err = uml_net_rx(dev)) > 0) ;
|
||||
if(err < 0) {
|
||||
DECLARE_WORK(close_work, uml_dev_close, dev);
|
||||
printk(KERN_ERR
|
||||
"Device '%s' read returned %d, shutting it down\n",
|
||||
dev->name, err);
|
||||
dev_close(dev);
|
||||
/* dev_close can't be called in interrupt context, and takes
|
||||
* again lp->lock.
|
||||
* And dev_close() can be safely called multiple times on the
|
||||
* same device, since it tests for (dev->flags & IFF_UP). So
|
||||
* there's no harm in delaying the device shutdown. */
|
||||
schedule_work(&close_work);
|
||||
goto out;
|
||||
}
|
||||
reactivate_fd(lp->fd, UM_ETH_IRQ);
|
||||
|
||||
out:
|
||||
out:
|
||||
spin_unlock(&lp->lock);
|
||||
return(IRQ_HANDLED);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче