aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/fs-writeback.c54
-rw-r--r--mm/backing-dev.c69
2 files changed, 70 insertions, 53 deletions
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index 9f5cab75c157..905f3ea38488 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -78,21 +78,17 @@ static void bdi_queue_work(struct backing_dev_info *bdi,
78 78
79 spin_lock(&bdi->wb_lock); 79 spin_lock(&bdi->wb_lock);
80 list_add_tail(&work->list, &bdi->work_list); 80 list_add_tail(&work->list, &bdi->work_list);
81 spin_unlock(&bdi->wb_lock); 81 if (bdi->wb.task) {
82 82 wake_up_process(bdi->wb.task);
83 /* 83 } else {
84 * If the default thread isn't there, make sure we add it. When 84 /*
85 * it gets created and wakes up, we'll run this work. 85 * The bdi thread isn't there, wake up the forker thread which
86 */ 86 * will create and run it.
87 if (unlikely(!bdi->wb.task)) { 87 */
88 trace_writeback_nothread(bdi, work); 88 trace_writeback_nothread(bdi, work);
89 wake_up_process(default_backing_dev_info.wb.task); 89 wake_up_process(default_backing_dev_info.wb.task);
90 } else {
91 struct bdi_writeback *wb = &bdi->wb;
92
93 if (wb->task)
94 wake_up_process(wb->task);
95 } 90 }
91 spin_unlock(&bdi->wb_lock);
96} 92}
97 93
98static void 94static void
@@ -800,7 +796,6 @@ int bdi_writeback_thread(void *data)
800{ 796{
801 struct bdi_writeback *wb = data; 797 struct bdi_writeback *wb = data;
802 struct backing_dev_info *bdi = wb->bdi; 798 struct backing_dev_info *bdi = wb->bdi;
803 unsigned long wait_jiffies = -1UL;
804 long pages_written; 799 long pages_written;
805 800
806 current->flags |= PF_FLUSHER | PF_SWAPWRITE; 801 current->flags |= PF_FLUSHER | PF_SWAPWRITE;
@@ -812,13 +807,6 @@ int bdi_writeback_thread(void *data)
812 */ 807 */
813 set_user_nice(current, 0); 808 set_user_nice(current, 0);
814 809
815 /*
816 * Clear pending bit and wakeup anybody waiting to tear us down
817 */
818 clear_bit(BDI_pending, &bdi->state);
819 smp_mb__after_clear_bit();
820 wake_up_bit(&bdi->state, BDI_pending);
821
822 trace_writeback_thread_start(bdi); 810 trace_writeback_thread_start(bdi);
823 811
824 while (!kthread_should_stop()) { 812 while (!kthread_should_stop()) {
@@ -828,18 +816,6 @@ int bdi_writeback_thread(void *data)
828 816
829 if (pages_written) 817 if (pages_written)
830 wb->last_active = jiffies; 818 wb->last_active = jiffies;
831 else if (wait_jiffies != -1UL) {
832 unsigned long max_idle;
833
834 /*
835 * Longest period of inactivity that we tolerate. If we
836 * see dirty data again later, the thread will get
837 * recreated automatically.
838 */
839 max_idle = max(5UL * 60 * HZ, wait_jiffies);
840 if (time_after(jiffies, max_idle + wb->last_active))
841 break;
842 }
843 819
844 set_current_state(TASK_INTERRUPTIBLE); 820 set_current_state(TASK_INTERRUPTIBLE);
845 if (!list_empty(&bdi->work_list)) { 821 if (!list_empty(&bdi->work_list)) {
@@ -847,21 +823,15 @@ int bdi_writeback_thread(void *data)
847 continue; 823 continue;
848 } 824 }
849 825
850 if (dirty_writeback_interval) { 826 if (dirty_writeback_interval)
851 wait_jiffies = msecs_to_jiffies(dirty_writeback_interval * 10); 827 schedule_timeout(msecs_to_jiffies(dirty_writeback_interval * 10));
852 schedule_timeout(wait_jiffies); 828 else
853 } else
854 schedule(); 829 schedule();
855 830
856 try_to_freeze(); 831 try_to_freeze();
857 } 832 }
858 833
859 wb->task = NULL; 834 /* Flush any work that raced with us exiting */
860
861 /*
862 * Flush any work that raced with us exiting. No new work
863 * will be added, since this bdi isn't discoverable anymore.
864 */
865 if (!list_empty(&bdi->work_list)) 835 if (!list_empty(&bdi->work_list))
866 wb_do_writeback(wb, 1); 836 wb_do_writeback(wb, 1);
867 837
diff --git a/mm/backing-dev.c b/mm/backing-dev.c
index e104e32c2ee8..9c1c199f88ce 100644
--- a/mm/backing-dev.c
+++ b/mm/backing-dev.c
@@ -316,6 +316,18 @@ static void sync_supers_timer_fn(unsigned long unused)
316 bdi_arm_supers_timer(); 316 bdi_arm_supers_timer();
317} 317}
318 318
319/*
320 * Calculate the longest interval (jiffies) bdi threads are allowed to be
321 * inactive.
322 */
323static unsigned long bdi_longest_inactive(void)
324{
325 unsigned long interval;
326
327 interval = msecs_to_jiffies(dirty_writeback_interval * 10);
328 return max(5UL * 60 * HZ, interval);
329}
330
319static int bdi_forker_thread(void *ptr) 331static int bdi_forker_thread(void *ptr)
320{ 332{
321 struct bdi_writeback *me = ptr; 333 struct bdi_writeback *me = ptr;
@@ -329,11 +341,12 @@ static int bdi_forker_thread(void *ptr)
329 set_user_nice(current, 0); 341 set_user_nice(current, 0);
330 342
331 for (;;) { 343 for (;;) {
332 struct task_struct *task; 344 struct task_struct *task = NULL;
333 struct backing_dev_info *bdi; 345 struct backing_dev_info *bdi;
334 enum { 346 enum {
335 NO_ACTION, /* Nothing to do */ 347 NO_ACTION, /* Nothing to do */
336 FORK_THREAD, /* Fork bdi thread */ 348 FORK_THREAD, /* Fork bdi thread */
349 KILL_THREAD, /* Kill inactive bdi thread */
337 } action = NO_ACTION; 350 } action = NO_ACTION;
338 351
339 /* 352 /*
@@ -346,10 +359,6 @@ static int bdi_forker_thread(void *ptr)
346 spin_lock_bh(&bdi_lock); 359 spin_lock_bh(&bdi_lock);
347 set_current_state(TASK_INTERRUPTIBLE); 360 set_current_state(TASK_INTERRUPTIBLE);
348 361
349 /*
350 * Check if any existing bdi's have dirty data without
351 * a thread registered. If so, set that up.
352 */
353 list_for_each_entry(bdi, &bdi_list, bdi_list) { 362 list_for_each_entry(bdi, &bdi_list, bdi_list) {
354 bool have_dirty_io; 363 bool have_dirty_io;
355 364
@@ -376,6 +385,25 @@ static int bdi_forker_thread(void *ptr)
376 action = FORK_THREAD; 385 action = FORK_THREAD;
377 break; 386 break;
378 } 387 }
388
389 spin_lock(&bdi->wb_lock);
390 /*
391 * If there is no work to do and the bdi thread was
392 * inactive long enough - kill it. The wb_lock is taken
393 * to make sure no-one adds more work to this bdi and
394 * wakes the bdi thread up.
395 */
396 if (bdi->wb.task && !have_dirty_io &&
397 time_after(jiffies, bdi->wb.last_active +
398 bdi_longest_inactive())) {
399 task = bdi->wb.task;
400 bdi->wb.task = NULL;
401 spin_unlock(&bdi->wb_lock);
402 set_bit(BDI_pending, &bdi->state);
403 action = KILL_THREAD;
404 break;
405 }
406 spin_unlock(&bdi->wb_lock);
379 } 407 }
380 spin_unlock_bh(&bdi_lock); 408 spin_unlock_bh(&bdi_lock);
381 409
@@ -394,8 +422,20 @@ static int bdi_forker_thread(void *ptr)
394 * the bdi from the thread. 422 * the bdi from the thread.
395 */ 423 */
396 bdi_flush_io(bdi); 424 bdi_flush_io(bdi);
397 } else 425 } else {
426 /*
427 * The spinlock makes sure we do not lose
428 * wake-ups when racing with 'bdi_queue_work()'.
429 */
430 spin_lock(&bdi->wb_lock);
398 bdi->wb.task = task; 431 bdi->wb.task = task;
432 spin_unlock(&bdi->wb_lock);
433 }
434 break;
435
436 case KILL_THREAD:
437 __set_current_state(TASK_RUNNING);
438 kthread_stop(task);
399 break; 439 break;
400 440
401 case NO_ACTION: 441 case NO_ACTION:
@@ -407,6 +447,13 @@ static int bdi_forker_thread(void *ptr)
407 /* Back to the main loop */ 447 /* Back to the main loop */
408 continue; 448 continue;
409 } 449 }
450
451 /*
452 * Clear pending bit and wakeup anybody waiting to tear us down.
453 */
454 clear_bit(BDI_pending, &bdi->state);
455 smp_mb__after_clear_bit();
456 wake_up_bit(&bdi->state, BDI_pending);
410 } 457 }
411 458
412 return 0; 459 return 0;
@@ -490,15 +537,15 @@ static void bdi_wb_shutdown(struct backing_dev_info *bdi)
490 return; 537 return;
491 538
492 /* 539 /*
493 * If setup is pending, wait for that to complete first 540 * Make sure nobody finds us on the bdi_list anymore
494 */ 541 */
495 wait_on_bit(&bdi->state, BDI_pending, bdi_sched_wait, 542 bdi_remove_from_list(bdi);
496 TASK_UNINTERRUPTIBLE);
497 543
498 /* 544 /*
499 * Make sure nobody finds us on the bdi_list anymore 545 * If setup is pending, wait for that to complete first
500 */ 546 */
501 bdi_remove_from_list(bdi); 547 wait_on_bit(&bdi->state, BDI_pending, bdi_sched_wait,
548 TASK_UNINTERRUPTIBLE);
502 549
503 /* 550 /*
504 * Finally, kill the kernel thread. We don't need to be RCU 551 * Finally, kill the kernel thread. We don't need to be RCU