Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 27922b4260f65d317aabda37e42bbbff > files > 2142

kernel-2.6.18-238.el5.src.rpm

From: Oleg Nesterov <oleg@redhat.com>
Date: Sun, 30 May 2010 16:19:54 -0400
Subject: [misc] workqueue: cwq instead of wq where appropriate
Message-id: <20100530161954.GC9577@redhat.com>
Patchwork-id: 25905
O-Subject: [RHEL5 PATCH 2/7] bz#596626:  workqueues: change
	queue_delayed_work/delayed_work_timer_fn to use cwq instead of wq
Bugzilla: 596626
RH-Acked-by: Stanislaw Gruszka <sgruszka@redhat.com>
RH-Acked-by: Prarit Bhargava <prarit@redhat.com>

(changes the existing code)

Currently we can't know what work->wq_data actually means, it could be
either cpu_workqueue_struct* if this work is already queued, or it is
workqueue_struct* if work->timer is pending.

Change queue_delayed_work/delayed_work_timer_fn to use cwq, not wq.
Thereafter work->wq_data always points to cpu_workqueue_struct if
queue_work/queue_delayed_work was ever called, otherwise this pointer
is not initialized: see the next patch.

Signed-off-by: Oleg Nesterov <oleg@redhat.com>

diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 25758a3..3a61c86 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -128,7 +128,9 @@ EXPORT_SYMBOL_GPL(queue_work);
 static void delayed_work_timer_fn(unsigned long __data)
 {
 	struct work_struct *work = (struct work_struct *)__data;
-	struct workqueue_struct *wq = work->wq_data;
+	struct cpu_workqueue_struct *cwq = work->wq_data;
+	struct workqueue_struct *wq = cwq->wq;
+
 	int cpu = smp_processor_id();
 
 	if (unlikely(is_single_threaded(wq)))
@@ -137,6 +139,15 @@ static void delayed_work_timer_fn(unsigned long __data)
 	__queue_work(per_cpu_ptr(wq->cpu_wq, cpu), work);
 }
 
+/* This stores cwq for the moment, for the timer_fn */
+static void set_delayed_wq_data(struct work_struct *work,
+					struct workqueue_struct *wq)
+{
+	int cpu = is_single_threaded(wq) ?
+			singlethread_cpu : raw_smp_processor_id();
+	work->wq_data = per_cpu_ptr(wq->cpu_wq, cpu);
+}
+
 /**
  * queue_delayed_work - queue work on a workqueue after delay
  * @wq: workqueue to use
@@ -155,8 +166,7 @@ int fastcall queue_delayed_work(struct workqueue_struct *wq,
 		BUG_ON(timer_pending(timer));
 		BUG_ON(!list_empty(&work->entry));
 
-		/* This stores wq for the moment, for the timer_fn */
-		work->wq_data = wq;
+		set_delayed_wq_data(work, wq);
 		timer->expires = jiffies + delay;
 		timer->data = (unsigned long)work;
 		timer->function = delayed_work_timer_fn;
@@ -186,8 +196,7 @@ int queue_delayed_work_on(int cpu, struct workqueue_struct *wq,
 		BUG_ON(timer_pending(timer));
 		BUG_ON(!list_empty(&work->entry));
 
-		/* This stores wq for the moment, for the timer_fn */
-		work->wq_data = wq;
+		set_delayed_wq_data(work, wq);
 		timer->expires = jiffies + delay;
 		timer->data = (unsigned long)work;
 		timer->function = delayed_work_timer_fn;