writeback: Add a 'reason' to wb_writeback_work
[linux-block.git] / mm / backing-dev.c
index d6edf8d14f9cd7fb5b9f143a7f529498ee0e9dc1..dd8916feb05e25bbbee7b81bd2c630f91d614dc2 100644 (file)
@@ -97,6 +97,7 @@ static int bdi_debug_stats_show(struct seq_file *m, void *v)
                   "BdiDirtyThresh:     %10lu kB\n"
                   "DirtyThresh:        %10lu kB\n"
                   "BackgroundThresh:   %10lu kB\n"
+                  "BdiDirtied:         %10lu kB\n"
                   "BdiWritten:         %10lu kB\n"
                   "BdiWriteBandwidth:  %10lu kBps\n"
                   "b_dirty:            %10lu\n"
@@ -109,6 +110,7 @@ static int bdi_debug_stats_show(struct seq_file *m, void *v)
                   K(bdi_thresh),
                   K(dirty_thresh),
                   K(background_thresh),
+                  (unsigned long) K(bdi_stat(bdi, BDI_DIRTIED)),
                   (unsigned long) K(bdi_stat(bdi, BDI_WRITTEN)),
                   (unsigned long) K(bdi->write_bandwidth),
                   nr_dirty,
@@ -359,6 +361,17 @@ static unsigned long bdi_longest_inactive(void)
        return max(5UL * 60 * HZ, interval);
 }
 
+/*
+ * Clear pending bit and wakeup anybody waiting for flusher thread creation or
+ * shutdown
+ */
+static void bdi_clear_pending(struct backing_dev_info *bdi)
+{
+       clear_bit(BDI_pending, &bdi->state);
+       smp_mb__after_clear_bit();
+       wake_up_bit(&bdi->state, BDI_pending);
+}
+
 static int bdi_forker_thread(void *ptr)
 {
        struct bdi_writeback *me = ptr;
@@ -390,6 +403,13 @@ static int bdi_forker_thread(void *ptr)
                }
 
                spin_lock_bh(&bdi_lock);
+               /*
+                * In the following loop we are going to check whether we have
+                * some work to do without any synchronization with tasks
+                * waking us up to do work for them. So we have to set task
+                * state already here so that we don't miss wakeups coming
+                * after we verify some condition.
+                */
                set_current_state(TASK_INTERRUPTIBLE);
 
                list_for_each_entry(bdi, &bdi_list, bdi_list) {
@@ -456,7 +476,8 @@ static int bdi_forker_thread(void *ptr)
                                 * the bdi from the thread. Hopefully 1024 is
                                 * large enough for efficient IO.
                                 */
-                               writeback_inodes_wb(&bdi->wb, 1024);
+                               writeback_inodes_wb(&bdi->wb, 1024,
+                                                   WB_REASON_FORKER_THREAD);
                        } else {
                                /*
                                 * The spinlock makes sure we do not lose
@@ -469,11 +490,13 @@ static int bdi_forker_thread(void *ptr)
                                spin_unlock_bh(&bdi->wb_lock);
                                wake_up_process(task);
                        }
+                       bdi_clear_pending(bdi);
                        break;
 
                case KILL_THREAD:
                        __set_current_state(TASK_RUNNING);
                        kthread_stop(task);
+                       bdi_clear_pending(bdi);
                        break;
 
                case NO_ACTION:
@@ -489,16 +512,8 @@ static int bdi_forker_thread(void *ptr)
                        else
                                schedule_timeout(msecs_to_jiffies(dirty_writeback_interval * 10));
                        try_to_freeze();
-                       /* Back to the main loop */
-                       continue;
+                       break;
                }
-
-               /*
-                * Clear pending bit and wakeup anybody waiting to tear us down.
-                */
-               clear_bit(BDI_pending, &bdi->state);
-               smp_mb__after_clear_bit();
-               wake_up_bit(&bdi->state, BDI_pending);
        }
 
        return 0;
@@ -672,6 +687,8 @@ int bdi_init(struct backing_dev_info *bdi)
        bdi->bw_time_stamp = jiffies;
        bdi->written_stamp = 0;
 
+       bdi->balanced_dirty_ratelimit = INIT_BW;
+       bdi->dirty_ratelimit = INIT_BW;
        bdi->write_bandwidth = INIT_BW;
        bdi->avg_write_bandwidth = INIT_BW;