Add a debug check for workqueues nested more than three deep via the direct-run-workqueue() path. --- 25-akpm/kernel/workqueue.c | 10 ++++++++++ 1 files changed, 10 insertions(+) diff -puN kernel/workqueue.c~flush_scheduled_work-recursion-detect kernel/workqueue.c --- 25/kernel/workqueue.c~flush_scheduled_work-recursion-detect 2004-03-12 17:54:32.859424968 -0800 +++ 25-akpm/kernel/workqueue.c 2004-03-12 18:11:09.939845704 -0800 @@ -47,6 +47,7 @@ struct cpu_workqueue_struct { struct workqueue_struct *wq; task_t *thread; + int run_depth; /* Detect run_workqueue() recursion depth */ } ____cacheline_aligned; /* @@ -140,6 +141,13 @@ static inline void run_workqueue(struct * done. */ spin_lock_irqsave(&cwq->lock, flags); + cwq->run_depth++; + if (cwq->run_depth > 3) { + /* morton gets to eat his hat */ + printk("%s: recursion depth exceeded: %d\n", + __FUNCTION__, cwq->run_depth); + dump_stack(); + } while (!list_empty(&cwq->worklist)) { struct work_struct *work = list_entry(cwq->worklist.next, struct work_struct, entry); @@ -157,6 +165,7 @@ static inline void run_workqueue(struct cwq->remove_sequence++; wake_up(&cwq->work_done); } + cwq->run_depth--; spin_unlock_irqrestore(&cwq->lock, flags); } @@ -286,6 +295,7 @@ struct workqueue_struct *create_workqueu wq = kmalloc(sizeof(*wq), GFP_KERNEL); if (!wq) return NULL; + memset(wq, 0, sizeof(*wq)); for (cpu = 0; cpu < NR_CPUS; cpu++) { if (!cpu_online(cpu)) _