diff options
| author | Wim Van Sebroeck <wim@iguana.be> | 2007-05-11 19:03:13 +0000 | 
|---|---|---|
| committer | Wim Van Sebroeck <wim@iguana.be> | 2007-05-11 19:03:13 +0000 | 
| commit | 5c34202b8bf942da411b6599668a76b07449bbfd (patch) | |
| tree | 5719c361321eaddc8e4f1b0c8a7994f0e9a6fdd3 /kernel/relay.c | |
| parent | 0d4804b31f91cfbcff6d62af0bc09a893a1c8ae0 (diff) | |
| parent | 1f8a6b658a943b4f04a1fc7b3a420360202c86cd (diff) | |
Merge /pub/scm/linux/kernel/git/torvalds/linux-2.6
Diffstat (limited to 'kernel/relay.c')
| -rw-r--r-- | kernel/relay.c | 37 | 
1 files changed, 18 insertions, 19 deletions
diff --git a/kernel/relay.c b/kernel/relay.c index 577f251c7e2..4311101b0ca 100644 --- a/kernel/relay.c +++ b/kernel/relay.c @@ -310,16 +310,13 @@ static struct rchan_callbacks default_channel_callbacks = {  /**   *	wakeup_readers - wake up readers waiting on a channel - *	@work: work struct that contains the the channel buffer + *	@data: contains the channel buffer   * - *	This is the work function used to defer reader waking.  The - *	reason waking is deferred is that calling directly from write - *	causes problems if you're writing from say the scheduler. + *	This is the timer function used to defer reader waking.   */ -static void wakeup_readers(struct work_struct *work) +static void wakeup_readers(unsigned long data)  { -	struct rchan_buf *buf = -		container_of(work, struct rchan_buf, wake_readers.work); +	struct rchan_buf *buf = (struct rchan_buf *)data;  	wake_up_interruptible(&buf->read_wait);  } @@ -337,11 +334,9 @@ static void __relay_reset(struct rchan_buf *buf, unsigned int init)  	if (init) {  		init_waitqueue_head(&buf->read_wait);  		kref_init(&buf->kref); -		INIT_DELAYED_WORK(&buf->wake_readers, NULL); -	} else { -		cancel_delayed_work(&buf->wake_readers); -		flush_scheduled_work(); -	} +		setup_timer(&buf->timer, wakeup_readers, (unsigned long)buf); +	} else +		del_timer_sync(&buf->timer);  	buf->subbufs_produced = 0;  	buf->subbufs_consumed = 0; @@ -447,8 +442,7 @@ end:  static void relay_close_buf(struct rchan_buf *buf)  {  	buf->finalized = 1; -	cancel_delayed_work(&buf->wake_readers); -	flush_scheduled_work(); +	del_timer_sync(&buf->timer);  	kref_put(&buf->kref, relay_remove_buf);  } @@ -490,6 +484,7 @@ static int __cpuinit relay_hotcpu_callback(struct notifier_block *nb,  	switch(action) {  	case CPU_UP_PREPARE: +	case CPU_UP_PREPARE_FROZEN:  		mutex_lock(&relay_channels_mutex);  		list_for_each_entry(chan, &relay_channels, list) {  			if (chan->buf[hotcpu]) @@ -506,6 +501,7 @@ static int __cpuinit relay_hotcpu_callback(struct notifier_block *nb,  		mutex_unlock(&relay_channels_mutex);  		break;  	case CPU_DEAD: +	case CPU_DEAD_FROZEN:  		/* No need to flush the cpu : will be flushed upon  		 * final relay_flush() call. */  		break; @@ -608,11 +604,14 @@ size_t relay_switch_subbuf(struct rchan_buf *buf, size_t length)  		buf->dentry->d_inode->i_size += buf->chan->subbuf_size -  			buf->padding[old_subbuf];  		smp_mb(); -		if (waitqueue_active(&buf->read_wait)) { -			PREPARE_DELAYED_WORK(&buf->wake_readers, -					     wakeup_readers); -			schedule_delayed_work(&buf->wake_readers, 1); -		} +		if (waitqueue_active(&buf->read_wait)) +			/* +			 * Calling wake_up_interruptible() from here +			 * will deadlock if we happen to be logging +			 * from the scheduler (trying to re-grab +			 * rq->lock), so defer it. +			 */ +			__mod_timer(&buf->timer, jiffies + 1);  	}  	old = buf->data;  | 
