diff options
Diffstat (limited to 'mm/backing-dev.c')
-rw-r--r-- | mm/backing-dev.c | 30 |
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 | */ | ||
366 | static 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 | |||
362 | static int bdi_forker_thread(void *ptr) | 373 | static 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; |