aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTom Zanussi <zanussi@comcast.net>2007-05-09 05:34:01 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-09 15:30:51 -0400
commit7c9cb38302e78d24e37f7d8a2ea7eed4ae5f2fa7 (patch)
treeb65be3c42762e85f3611fe5298d203f7f901da02
parentd0758bc334780d70266c1d1b974ed26f740a0819 (diff)
relay: use plain timer instead of delayed work
relay doesn't need to use schedule_delayed_work() for waking readers when a simple timer will do. Signed-off-by: Tom Zanussi <zanussi@comcast.net> Cc: Satyam Sharma <satyam.sharma@gmail.com> Cc: Oleg Nesterov <oleg@tv-sign.ru> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--include/linux/relay.h3
-rw-r--r--kernel/relay.c35
2 files changed, 18 insertions, 20 deletions
diff --git a/include/linux/relay.h b/include/linux/relay.h
index 759a0f97bec2..6cd8c4425fc7 100644
--- a/include/linux/relay.h
+++ b/include/linux/relay.h
@@ -12,6 +12,7 @@
12 12
13#include <linux/types.h> 13#include <linux/types.h>
14#include <linux/sched.h> 14#include <linux/sched.h>
15#include <linux/timer.h>
15#include <linux/wait.h> 16#include <linux/wait.h>
16#include <linux/list.h> 17#include <linux/list.h>
17#include <linux/fs.h> 18#include <linux/fs.h>
@@ -38,7 +39,7 @@ struct rchan_buf
38 size_t subbufs_consumed; /* count of sub-buffers consumed */ 39 size_t subbufs_consumed; /* count of sub-buffers consumed */
39 struct rchan *chan; /* associated channel */ 40 struct rchan *chan; /* associated channel */
40 wait_queue_head_t read_wait; /* reader wait queue */ 41 wait_queue_head_t read_wait; /* reader wait queue */
41 struct delayed_work wake_readers; /* reader wake-up work struct */ 42 struct timer_list timer; /* reader wake-up timer */
42 struct dentry *dentry; /* channel file dentry */ 43 struct dentry *dentry; /* channel file dentry */
43 struct kref kref; /* channel buffer refcount */ 44 struct kref kref; /* channel buffer refcount */
44 struct page **page_array; /* array of current buffer pages */ 45 struct page **page_array; /* array of current buffer pages */
diff --git a/kernel/relay.c b/kernel/relay.c
index 577f251c7e28..e804589c863c 100644
--- a/kernel/relay.c
+++ b/kernel/relay.c
@@ -310,16 +310,13 @@ static struct rchan_callbacks default_channel_callbacks = {
310 310
311/** 311/**
312 * wakeup_readers - wake up readers waiting on a channel 312 * wakeup_readers - wake up readers waiting on a channel
313 * @work: work struct that contains the the channel buffer 313 * @data: contains the the channel buffer
314 * 314 *
315 * This is the work function used to defer reader waking. The 315 * This is the timer function used to defer reader waking.
316 * reason waking is deferred is that calling directly from write
317 * causes problems if you're writing from say the scheduler.
318 */ 316 */
319static void wakeup_readers(struct work_struct *work) 317static void wakeup_readers(unsigned long data)
320{ 318{
321 struct rchan_buf *buf = 319 struct rchan_buf *buf = (struct rchan_buf *)data;
322 container_of(work, struct rchan_buf, wake_readers.work);
323 wake_up_interruptible(&buf->read_wait); 320 wake_up_interruptible(&buf->read_wait);
324} 321}
325 322
@@ -337,11 +334,9 @@ static void __relay_reset(struct rchan_buf *buf, unsigned int init)
337 if (init) { 334 if (init) {
338 init_waitqueue_head(&buf->read_wait); 335 init_waitqueue_head(&buf->read_wait);
339 kref_init(&buf->kref); 336 kref_init(&buf->kref);
340 INIT_DELAYED_WORK(&buf->wake_readers, NULL); 337 setup_timer(&buf->timer, wakeup_readers, (unsigned long)buf);
341 } else { 338 } else
342 cancel_delayed_work(&buf->wake_readers); 339 del_timer_sync(&buf->timer);
343 flush_scheduled_work();
344 }
345 340
346 buf->subbufs_produced = 0; 341 buf->subbufs_produced = 0;
347 buf->subbufs_consumed = 0; 342 buf->subbufs_consumed = 0;
@@ -447,8 +442,7 @@ end:
447static void relay_close_buf(struct rchan_buf *buf) 442static void relay_close_buf(struct rchan_buf *buf)
448{ 443{
449 buf->finalized = 1; 444 buf->finalized = 1;
450 cancel_delayed_work(&buf->wake_readers); 445 del_timer_sync(&buf->timer);
451 flush_scheduled_work();
452 kref_put(&buf->kref, relay_remove_buf); 446 kref_put(&buf->kref, relay_remove_buf);
453} 447}
454 448
@@ -608,11 +602,14 @@ size_t relay_switch_subbuf(struct rchan_buf *buf, size_t length)
608 buf->dentry->d_inode->i_size += buf->chan->subbuf_size - 602 buf->dentry->d_inode->i_size += buf->chan->subbuf_size -
609 buf->padding[old_subbuf]; 603 buf->padding[old_subbuf];
610 smp_mb(); 604 smp_mb();
611 if (waitqueue_active(&buf->read_wait)) { 605 if (waitqueue_active(&buf->read_wait))
612 PREPARE_DELAYED_WORK(&buf->wake_readers, 606 /*
613 wakeup_readers); 607 * Calling wake_up_interruptible() from here
614 schedule_delayed_work(&buf->wake_readers, 1); 608 * will deadlock if we happen to be logging
615 } 609 * from the scheduler (trying to re-grab
610 * rq->lock), so defer it.
611 */
612 __mod_timer(&buf->timer, jiffies + 1);
616 } 613 }
617 614
618 old = buf->data; 615 old = buf->data;