diff options
Diffstat (limited to 'kernel/relay.c')
-rw-r--r-- | kernel/relay.c | 35 |
1 files changed, 16 insertions, 19 deletions
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 | */ |
319 | static void wakeup_readers(struct work_struct *work) | 317 | static 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: | |||
447 | static void relay_close_buf(struct rchan_buf *buf) | 442 | static 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; |