From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail203.messagelabs.com (mail203.messagelabs.com [216.82.254.243]) by kanga.kvack.org (Postfix) with ESMTP id D81D36B0180 for ; Fri, 2 Sep 2011 08:33:21 -0400 (EDT) Received: by vxj3 with SMTP id 3so2848350vxj.14 for ; Fri, 02 Sep 2011 05:33:20 -0700 (PDT) MIME-Version: 1.0 In-Reply-To: References: <1314963064-22109-1-git-send-email-jack@suse.cz> Date: Fri, 2 Sep 2011 18:03:19 +0530 Message-ID: Subject: Re: [PATCH v2] mm: Make logic in bdi_forker_thread() straight From: "kautuk.c @samsung.com" Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable Sender: owner-linux-mm@kvack.org List-ID: To: Jan Kara Cc: Jens Axboe , LKML , linux-mm@kvack.org, Andrew Morton , Wu Fengguang Sorry, I was wrong in this email. Please ignore. This problem will still happen as the CPU executing the wakeup_timer_fn can still get the lock and do a wake_up_process which can set the task state to TASK_RUNNING. On Fri, Sep 2, 2011 at 5:41 PM, kautuk.c @samsung.com wrote: > Sorry to butt in before Jens' review but i have one small comment: > > On Fri, Sep 2, 2011 at 5:01 PM, Jan Kara wrote: >> The logic in bdi_forker_thread() is unnecessarily convoluted by setting = task >> state there and back or calling schedule_timeout() in TASK_RUNNING state= . Also >> clearing of BDI_pending bit is placed at the and of global loop and case= s of a >> switch which mustn't reach it must call 'continue' instead of 'break' wh= ich is >> non-intuitive and thus asking for trouble. So make the logic more obviou= s. >> >> CC: Andrew Morton >> CC: Wu Fengguang >> CC: consul.kautuk@gmail.com >> Signed-off-by: Jan Kara >> --- >> =A0mm/backing-dev.c | =A0 37 ++++++++++++++++++++----------------- >> =A01 files changed, 20 insertions(+), 17 deletions(-) >> >> =A0This should be the right cleanup. Jens? >> >> diff --git a/mm/backing-dev.c b/mm/backing-dev.c >> index d6edf8d..bdf7d6b 100644 >> --- a/mm/backing-dev.c >> +++ b/mm/backing-dev.c >> @@ -359,6 +359,17 @@ static unsigned long bdi_longest_inactive(void) >> =A0 =A0 =A0 =A0return max(5UL * 60 * HZ, interval); >> =A0} >> >> +/* >> + * Clear pending bit and wakeup anybody waiting for flusher thread star= tup >> + * or teardown. >> + */ >> +static void bdi_clear_pending(struct backing_dev_info *bdi) >> +{ >> + =A0 =A0 =A0 clear_bit(BDI_pending, &bdi->state); >> + =A0 =A0 =A0 smp_mb__after_clear_bit(); >> + =A0 =A0 =A0 wake_up_bit(&bdi->state, BDI_pending); >> +} >> + >> =A0static int bdi_forker_thread(void *ptr) >> =A0{ >> =A0 =A0 =A0 =A0struct bdi_writeback *me =3D ptr; >> @@ -390,8 +401,6 @@ static int bdi_forker_thread(void *ptr) >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0} >> >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0spin_lock_bh(&bdi_lock); >> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 set_current_state(TASK_INTERRUPTIBLE); >> - >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0list_for_each_entry(bdi, &bdi_list, bdi_l= ist) { >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0bool have_dirty_io; >> >> @@ -441,13 +450,8 @@ static int bdi_forker_thread(void *ptr) >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0} >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0spin_unlock_bh(&bdi_lock); >> >> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* Keep working if default bdi still has t= hings to do */ >> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (!list_empty(&me->bdi->work_list)) >> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 __set_current_state(TASK_R= UNNING); >> - >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0switch (action) { >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0case FORK_THREAD: >> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 __set_current_state(TASK_R= UNNING); >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0task =3D kthread_create(b= di_writeback_thread, &bdi->wb, >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 = =A0 =A0 =A0 =A0 =A0"flush-%s", dev_name(bdi->dev)); >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (IS_ERR(task)) { >> @@ -469,14 +473,21 @@ static int bdi_forker_thread(void *ptr) >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0spin_unlo= ck_bh(&bdi->wb_lock); >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0wake_up_p= rocess(task); >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0} >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 bdi_clear_pending(bdi); >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0break; >> >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0case KILL_THREAD: >> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 __set_current_state(TASK_R= UNNING); >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0kthread_stop(task); >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 bdi_clear_pending(bdi); >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0break; >> >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0case NO_ACTION: >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* Keep working if default= bdi still has things to do */ > > Can we acquire and release the spinlocks as below: > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0spin_lock_bh(&me->= bdi->wb_lock) ; > >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (!list_empty(&me->bdi->= work_list)) { > > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0spin_unlock_bh(&me= ->bdi->wb_lock) ; > >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 try_to_fre= eze(); >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 break; >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 } >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 set_current_state(TASK_INT= ERRUPTIBLE); > > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0spin_unlock_bh(&me= ->bdi->wb_lock) ; > >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (!wb_has_dirty_io(me) = || !dirty_writeback_interval) >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 * There = are no dirty data. The only thing we >> @@ -489,16 +500,8 @@ static int bdi_forker_thread(void *ptr) >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0else >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0schedule_= timeout(msecs_to_jiffies(dirty_writeback_interval * 10)); >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0try_to_freeze(); >> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* Back to the main loop *= / >> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 continue; >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 break; >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0} >> - >> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* >> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* Clear pending bit and wakeup anybody = waiting to tear us down. >> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*/ >> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 clear_bit(BDI_pending, &bdi->state); >> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 smp_mb__after_clear_bit(); >> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 wake_up_bit(&bdi->state, BDI_pending); >> =A0 =A0 =A0 =A0} >> >> =A0 =A0 =A0 =A0return 0; >> -- >> 1.7.1 >> >> > > That should take care of the problem I initially mentioned due to the > wakeup_timer_fn executing > in parallel on another CPU as the task state will now be protected by > the wb_lock spinlock. > -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to majordomo@kvack.org. For more info on Linux MM, see: http://www.linux-mm.org/ . Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/ Don't email: email@kvack.org