aboutsummaryrefslogtreecommitdiffstats
path: root/mm/backing-dev.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/backing-dev.c')
-rw-r--r--mm/backing-dev.c30
1 files changed, 21 insertions, 9 deletions
diff --git a/mm/backing-dev.c b/mm/backing-dev.c
index d6edf8d14f9c..a87da524a4a0 100644
--- a/mm/backing-dev.c
+++ b/mm/backing-dev.c
@@ -359,6 +359,17 @@ static unsigned long bdi_longest_inactive(void)
359 return max(5UL * 60 * HZ, interval); 359 return max(5UL * 60 * HZ, interval);
360} 360}
361 361
362/*
363 * Clear pending bit and wakeup anybody waiting for flusher thread creation or
364 * shutdown
365 */
366static void bdi_clear_pending(struct backing_dev_info *bdi)
367{
368 clear_bit(BDI_pending, &bdi->state);
369 smp_mb__after_clear_bit();
370 wake_up_bit(&bdi->state, BDI_pending);
371}
372
362static int bdi_forker_thread(void *ptr) 373static int bdi_forker_thread(void *ptr)
363{ 374{
364 struct bdi_writeback *me = ptr; 375 struct bdi_writeback *me = ptr;
@@ -390,6 +401,13 @@ static int bdi_forker_thread(void *ptr)
390 } 401 }
391 402
392 spin_lock_bh(&bdi_lock); 403 spin_lock_bh(&bdi_lock);
404 /*
405 * In the following loop we are going to check whether we have
406 * some work to do without any synchronization with tasks
407 * waking us up to do work for them. So we have to set task
408 * state already here so that we don't miss wakeups coming
409 * after we verify some condition.
410 */
393 set_current_state(TASK_INTERRUPTIBLE); 411 set_current_state(TASK_INTERRUPTIBLE);
394 412
395 list_for_each_entry(bdi, &bdi_list, bdi_list) { 413 list_for_each_entry(bdi, &bdi_list, bdi_list) {
@@ -469,11 +487,13 @@ static int bdi_forker_thread(void *ptr)
469 spin_unlock_bh(&bdi->wb_lock); 487 spin_unlock_bh(&bdi->wb_lock);
470 wake_up_process(task); 488 wake_up_process(task);
471 } 489 }
490 bdi_clear_pending(bdi);
472 break; 491 break;
473 492
474 case KILL_THREAD: 493 case KILL_THREAD:
475 __set_current_state(TASK_RUNNING); 494 __set_current_state(TASK_RUNNING);
476 kthread_stop(task); 495 kthread_stop(task);
496 bdi_clear_pending(bdi);
477 break; 497 break;
478 498
479 case NO_ACTION: 499 case NO_ACTION:
@@ -489,16 +509,8 @@ static int bdi_forker_thread(void *ptr)
489 else 509 else
490 schedule_timeout(msecs_to_jiffies(dirty_writeback_interval * 10)); 510 schedule_timeout(msecs_to_jiffies(dirty_writeback_interval * 10));
491 try_to_freeze(); 511 try_to_freeze();
492 /* Back to the main loop */ 512 break;
493 continue;
494 } 513 }
495
496 /*
497 * Clear pending bit and wakeup anybody waiting to tear us down.
498 */
499 clear_bit(BDI_pending, &bdi->state);
500 smp_mb__after_clear_bit();
501 wake_up_bit(&bdi->state, BDI_pending);
502 } 514 }
503 515
504 return 0; 516 return 0;