aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Zijlstra <a.p.zijlstra@chello.nl>2006-12-13 03:33:50 -0500
committerLinus Torvalds <torvalds@woody.osdl.org>2006-12-13 12:05:47 -0500
commiteff3b634d9a0cccb6ca8b431819fa415f10804dc (patch)
tree8bf2dac62ce9c4e4aa62ea5a66831ed65ef35137
parentffd22b8e08fb86692d316cdcc1a4da4d10a016c5 (diff)
[PATCH] uml: fix net_kern workqueue abuse
Fix up the work on stack and exit scope trouble by placing the work_struct in the uml_net_private data. Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Acked-by: Jeff Dike <jdike@addtoit.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--arch/um/drivers/net_kern.c15
-rw-r--r--arch/um/include/net_kern.h2
2 files changed, 11 insertions, 6 deletions
diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c
index b2e9762e13c5..afe3d427ddfa 100644
--- a/arch/um/drivers/net_kern.c
+++ b/arch/um/drivers/net_kern.c
@@ -72,9 +72,11 @@ static int uml_net_rx(struct net_device *dev)
72 return pkt_len; 72 return pkt_len;
73} 73}
74 74
75static void uml_dev_close(void* dev) 75static void uml_dev_close(struct work_struct *work)
76{ 76{
77 dev_close( (struct net_device *) dev); 77 struct uml_net_private *lp =
78 container_of(work, struct uml_net_private, work);
79 dev_close(lp->dev);
78} 80}
79 81
80irqreturn_t uml_net_interrupt(int irq, void *dev_id) 82irqreturn_t uml_net_interrupt(int irq, void *dev_id)
@@ -89,7 +91,6 @@ irqreturn_t uml_net_interrupt(int irq, void *dev_id)
89 spin_lock(&lp->lock); 91 spin_lock(&lp->lock);
90 while((err = uml_net_rx(dev)) > 0) ; 92 while((err = uml_net_rx(dev)) > 0) ;
91 if(err < 0) { 93 if(err < 0) {
92 DECLARE_WORK(close_work, uml_dev_close, dev);
93 printk(KERN_ERR 94 printk(KERN_ERR
94 "Device '%s' read returned %d, shutting it down\n", 95 "Device '%s' read returned %d, shutting it down\n",
95 dev->name, err); 96 dev->name, err);
@@ -97,9 +98,10 @@ irqreturn_t uml_net_interrupt(int irq, void *dev_id)
97 * again lp->lock. 98 * again lp->lock.
98 * And dev_close() can be safely called multiple times on the 99 * And dev_close() can be safely called multiple times on the
99 * same device, since it tests for (dev->flags & IFF_UP). So 100 * same device, since it tests for (dev->flags & IFF_UP). So
100 * there's no harm in delaying the device shutdown. */ 101 * there's no harm in delaying the device shutdown.
101 schedule_work(&close_work); 102 * Furthermore, the workqueue will not re-enqueue an already
102#error this is not permitted - close_work will go out of scope 103 * enqueued work item. */
104 schedule_work(&lp->work);
103 goto out; 105 goto out;
104 } 106 }
105 reactivate_fd(lp->fd, UM_ETH_IRQ); 107 reactivate_fd(lp->fd, UM_ETH_IRQ);
@@ -365,6 +367,7 @@ static int eth_configure(int n, void *init, char *mac,
365 /* This points to the transport private data. It's still clear, but we 367 /* This points to the transport private data. It's still clear, but we
366 * must memset it to 0 *now*. Let's help the drivers. */ 368 * must memset it to 0 *now*. Let's help the drivers. */
367 memset(lp, 0, size); 369 memset(lp, 0, size);
370 INIT_WORK(&lp->work, uml_dev_close);
368 371
369 /* sysfs register */ 372 /* sysfs register */
370 if (!driver_registered) { 373 if (!driver_registered) {
diff --git a/arch/um/include/net_kern.h b/arch/um/include/net_kern.h
index 280459fb0b26..218f8b47fdcd 100644
--- a/arch/um/include/net_kern.h
+++ b/arch/um/include/net_kern.h
@@ -11,6 +11,7 @@
11#include <linux/skbuff.h> 11#include <linux/skbuff.h>
12#include <linux/socket.h> 12#include <linux/socket.h>
13#include <linux/list.h> 13#include <linux/list.h>
14#include <linux/workqueue.h>
14 15
15struct uml_net { 16struct uml_net {
16 struct list_head list; 17 struct list_head list;
@@ -26,6 +27,7 @@ struct uml_net_private {
26 struct net_device *dev; 27 struct net_device *dev;
27 struct timer_list tl; 28 struct timer_list tl;
28 struct net_device_stats stats; 29 struct net_device_stats stats;
30 struct work_struct work;
29 int fd; 31 int fd;
30 unsigned char mac[ETH_ALEN]; 32 unsigned char mac[ETH_ALEN];
31 unsigned short (*protocol)(struct sk_buff *); 33 unsigned short (*protocol)(struct sk_buff *);