diff options
| author | Curt Wohlgemuth <curtw@google.com> | 2011-10-07 23:54:10 -0400 |
|---|---|---|
| committer | Wu Fengguang <fengguang.wu@intel.com> | 2011-10-30 12:33:36 -0400 |
| commit | 0e175a1835ffc979e55787774e58ec79e41957d7 (patch) | |
| tree | 6ec4b65a8de4e9d1c12d26a1079079ed81d79450 | |
| parent | ad4e38dd6a33bb3a4882c487d7abe621e583b982 (diff) | |
writeback: Add a 'reason' to wb_writeback_work
This creates a new 'reason' field in a wb_writeback_work
structure, which unambiguously identifies who initiates
writeback activity. A 'wb_reason' enumeration has been
added to writeback.h, to enumerate the possible reasons.
The 'writeback_work_class' and tracepoint event class and
'writeback_queue_io' tracepoints are updated to include the
symbolic 'reason' in all trace events.
And the 'writeback_inodes_sbXXX' family of routines has had
a wb_stats parameter added to them, so callers can specify
why writeback is being started.
Acked-by: Jan Kara <jack@suse.cz>
Signed-off-by: Curt Wohlgemuth <curtw@google.com>
Signed-off-by: Wu Fengguang <fengguang.wu@intel.com>
| -rw-r--r-- | fs/btrfs/extent-tree.c | 3 | ||||
| -rw-r--r-- | fs/buffer.c | 2 | ||||
| -rw-r--r-- | fs/ext4/inode.c | 2 | ||||
| -rw-r--r-- | fs/fs-writeback.c | 49 | ||||
| -rw-r--r-- | fs/quota/quota.c | 2 | ||||
| -rw-r--r-- | fs/sync.c | 4 | ||||
| -rw-r--r-- | fs/ubifs/budget.c | 2 | ||||
| -rw-r--r-- | include/linux/backing-dev.h | 3 | ||||
| -rw-r--r-- | include/linux/writeback.h | 32 | ||||
| -rw-r--r-- | include/trace/events/writeback.h | 14 | ||||
| -rw-r--r-- | mm/backing-dev.c | 3 | ||||
| -rw-r--r-- | mm/page-writeback.c | 3 | ||||
| -rw-r--r-- | mm/vmscan.c | 3 |
13 files changed, 88 insertions, 34 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index f5be06a2462f..c9ee0e18bbdc 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
| @@ -3340,7 +3340,8 @@ static int shrink_delalloc(struct btrfs_trans_handle *trans, | |||
| 3340 | smp_mb(); | 3340 | smp_mb(); |
| 3341 | nr_pages = min_t(unsigned long, nr_pages, | 3341 | nr_pages = min_t(unsigned long, nr_pages, |
| 3342 | root->fs_info->delalloc_bytes >> PAGE_CACHE_SHIFT); | 3342 | root->fs_info->delalloc_bytes >> PAGE_CACHE_SHIFT); |
| 3343 | writeback_inodes_sb_nr_if_idle(root->fs_info->sb, nr_pages); | 3343 | writeback_inodes_sb_nr_if_idle(root->fs_info->sb, nr_pages, |
| 3344 | WB_REASON_FS_FREE_SPACE); | ||
| 3344 | 3345 | ||
| 3345 | spin_lock(&space_info->lock); | 3346 | spin_lock(&space_info->lock); |
| 3346 | if (reserved > space_info->bytes_reserved) | 3347 | if (reserved > space_info->bytes_reserved) |
diff --git a/fs/buffer.c b/fs/buffer.c index 1a80b048ade8..f5dcee6c4cfb 100644 --- a/fs/buffer.c +++ b/fs/buffer.c | |||
| @@ -285,7 +285,7 @@ static void free_more_memory(void) | |||
| 285 | struct zone *zone; | 285 | struct zone *zone; |
| 286 | int nid; | 286 | int nid; |
| 287 | 287 | ||
| 288 | wakeup_flusher_threads(1024); | 288 | wakeup_flusher_threads(1024, WB_REASON_FREE_MORE_MEM); |
| 289 | yield(); | 289 | yield(); |
| 290 | 290 | ||
| 291 | for_each_online_node(nid) { | 291 | for_each_online_node(nid) { |
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 986e2388f031..7fa73a3b2120 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
| @@ -2241,7 +2241,7 @@ static int ext4_nonda_switch(struct super_block *sb) | |||
| 2241 | * start pushing delalloc when 1/2 of free blocks are dirty. | 2241 | * start pushing delalloc when 1/2 of free blocks are dirty. |
| 2242 | */ | 2242 | */ |
| 2243 | if (free_blocks < 2 * dirty_blocks) | 2243 | if (free_blocks < 2 * dirty_blocks) |
| 2244 | writeback_inodes_sb_if_idle(sb); | 2244 | writeback_inodes_sb_if_idle(sb, WB_REASON_FS_FREE_SPACE); |
| 2245 | 2245 | ||
| 2246 | return 0; | 2246 | return 0; |
| 2247 | } | 2247 | } |
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index c51029693600..73c3992b2bb4 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c | |||
| @@ -41,11 +41,23 @@ struct wb_writeback_work { | |||
| 41 | unsigned int for_kupdate:1; | 41 | unsigned int for_kupdate:1; |
| 42 | unsigned int range_cyclic:1; | 42 | unsigned int range_cyclic:1; |
| 43 | unsigned int for_background:1; | 43 | unsigned int for_background:1; |
| 44 | enum wb_reason reason; /* why was writeback initiated? */ | ||
| 44 | 45 | ||
| 45 | struct list_head list; /* pending work list */ | 46 | struct list_head list; /* pending work list */ |
| 46 | struct completion *done; /* set if the caller waits */ | 47 | struct completion *done; /* set if the caller waits */ |
| 47 | }; | 48 | }; |
| 48 | 49 | ||
| 50 | const char *wb_reason_name[] = { | ||
| 51 | [WB_REASON_BACKGROUND] = "background", | ||
| 52 | [WB_REASON_TRY_TO_FREE_PAGES] = "try_to_free_pages", | ||
| 53 | [WB_REASON_SYNC] = "sync", | ||
| 54 | [WB_REASON_PERIODIC] = "periodic", | ||
| 55 | [WB_REASON_LAPTOP_TIMER] = "laptop_timer", | ||
| 56 | [WB_REASON_FREE_MORE_MEM] = "free_more_memory", | ||
| 57 | [WB_REASON_FS_FREE_SPACE] = "fs_free_space", | ||
| 58 | [WB_REASON_FORKER_THREAD] = "forker_thread" | ||
| 59 | }; | ||
| 60 | |||
| 49 | /* | 61 | /* |
| 50 | * Include the creation of the trace points after defining the | 62 | * Include the creation of the trace points after defining the |
| 51 | * wb_writeback_work structure so that the definition remains local to this | 63 | * wb_writeback_work structure so that the definition remains local to this |
| @@ -115,7 +127,7 @@ static void bdi_queue_work(struct backing_dev_info *bdi, | |||
| 115 | 127 | ||
| 116 | static void | 128 | static void |
| 117 | __bdi_start_writeback(struct backing_dev_info *bdi, long nr_pages, | 129 | __bdi_start_writeback(struct backing_dev_info *bdi, long nr_pages, |
| 118 | bool range_cyclic) | 130 | bool range_cyclic, enum wb_reason reason) |
| 119 | { | 131 | { |
| 120 | struct wb_writeback_work *work; | 132 | struct wb_writeback_work *work; |
| 121 | 133 | ||
| @@ -135,6 +147,7 @@ __bdi_start_writeback(struct backing_dev_info *bdi, long nr_pages, | |||
| 135 | work->sync_mode = WB_SYNC_NONE; | 147 | work->sync_mode = WB_SYNC_NONE; |
| 136 | work->nr_pages = nr_pages; | 148 | work->nr_pages = nr_pages; |
| 137 | work->range_cyclic = range_cyclic; | 149 | work->range_cyclic = range_cyclic; |
| 150 | work->reason = reason; | ||
| 138 | 151 | ||
| 139 | bdi_queue_work(bdi, work); | 152 | bdi_queue_work(bdi, work); |
| 140 | } | 153 | } |
| @@ -150,9 +163,10 @@ __bdi_start_writeback(struct backing_dev_info *bdi, long nr_pages, | |||
| 150 | * completion. Caller need not hold sb s_umount semaphore. | 163 | * completion. Caller need not hold sb s_umount semaphore. |
| 151 | * | 164 | * |
| 152 | */ | 165 | */ |
| 153 | void bdi_start_writeback(struct backing_dev_info *bdi, long nr_pages) | 166 | void bdi_start_writeback(struct backing_dev_info *bdi, long nr_pages, |
| 167 | enum wb_reason reason) | ||
| 154 | { | 168 | { |
| 155 | __bdi_start_writeback(bdi, nr_pages, true); | 169 | __bdi_start_writeback(bdi, nr_pages, true, reason); |
| 156 | } | 170 | } |
| 157 | 171 | ||
| 158 | /** | 172 | /** |
| @@ -641,12 +655,14 @@ static long __writeback_inodes_wb(struct bdi_writeback *wb, | |||
| 641 | return wrote; | 655 | return wrote; |
| 642 | } | 656 | } |
| 643 | 657 | ||
| 644 | long writeback_inodes_wb(struct bdi_writeback *wb, long nr_pages) | 658 | long writeback_inodes_wb(struct bdi_writeback *wb, long nr_pages, |
| 659 | enum wb_reason reason) | ||
| 645 | { | 660 | { |
| 646 | struct wb_writeback_work work = { | 661 | struct wb_writeback_work work = { |
| 647 | .nr_pages = nr_pages, | 662 | .nr_pages = nr_pages, |
| 648 | .sync_mode = WB_SYNC_NONE, | 663 | .sync_mode = WB_SYNC_NONE, |
| 649 | .range_cyclic = 1, | 664 | .range_cyclic = 1, |
| 665 | .reason = reason, | ||
| 650 | }; | 666 | }; |
| 651 | 667 | ||
| 652 | spin_lock(&wb->list_lock); | 668 | spin_lock(&wb->list_lock); |
| @@ -825,6 +841,7 @@ static long wb_check_background_flush(struct bdi_writeback *wb) | |||
| 825 | .sync_mode = WB_SYNC_NONE, | 841 | .sync_mode = WB_SYNC_NONE, |
| 826 | .for_background = 1, | 842 | .for_background = 1, |
| 827 | .range_cyclic = 1, | 843 | .range_cyclic = 1, |
| 844 | .reason = WB_REASON_BACKGROUND, | ||
| 828 | }; | 845 | }; |
| 829 | 846 | ||
| 830 | return wb_writeback(wb, &work); | 847 | return wb_writeback(wb, &work); |
| @@ -858,6 +875,7 @@ static long wb_check_old_data_flush(struct bdi_writeback *wb) | |||
| 858 | .sync_mode = WB_SYNC_NONE, | 875 | .sync_mode = WB_SYNC_NONE, |
| 859 | .for_kupdate = 1, | 876 | .for_kupdate = 1, |
| 860 | .range_cyclic = 1, | 877 | .range_cyclic = 1, |
| 878 | .reason = WB_REASON_PERIODIC, | ||
| 861 | }; | 879 | }; |
| 862 | 880 | ||
| 863 | return wb_writeback(wb, &work); | 881 | return wb_writeback(wb, &work); |
| @@ -976,7 +994,7 @@ int bdi_writeback_thread(void *data) | |||
| 976 | * Start writeback of `nr_pages' pages. If `nr_pages' is zero, write back | 994 | * Start writeback of `nr_pages' pages. If `nr_pages' is zero, write back |
| 977 | * the whole world. | 995 | * the whole world. |
| 978 | */ | 996 | */ |
| 979 | void wakeup_flusher_threads(long nr_pages) | 997 | void wakeup_flusher_threads(long nr_pages, enum wb_reason reason) |
| 980 | { | 998 | { |
| 981 | struct backing_dev_info *bdi; | 999 | struct backing_dev_info *bdi; |
| 982 | 1000 | ||
| @@ -989,7 +1007,7 @@ void wakeup_flusher_threads(long nr_pages) | |||
| 989 | list_for_each_entry_rcu(bdi, &bdi_list, bdi_list) { | 1007 | list_for_each_entry_rcu(bdi, &bdi_list, bdi_list) { |
| 990 | if (!bdi_has_dirty_io(bdi)) | 1008 | if (!bdi_has_dirty_io(bdi)) |
| 991 | continue; | 1009 | continue; |
| 992 | __bdi_start_writeback(bdi, nr_pages, false); | 1010 | __bdi_start_writeback(bdi, nr_pages, false, reason); |
| 993 | } | 1011 | } |
| 994 | rcu_read_unlock(); | 1012 | rcu_read_unlock(); |
| 995 | } | 1013 | } |
| @@ -1210,7 +1228,9 @@ static void wait_sb_inodes(struct super_block *sb) | |||
| 1210 | * on how many (if any) will be written, and this function does not wait | 1228 | * on how many (if any) will be written, and this function does not wait |
| 1211 | * for IO completion of submitted IO. | 1229 | * for IO completion of submitted IO. |
| 1212 | */ | 1230 | */ |
| 1213 | void writeback_inodes_sb_nr(struct super_block *sb, unsigned long nr) | 1231 | void writeback_inodes_sb_nr(struct super_block *sb, |
| 1232 | unsigned long nr, | ||
