diff options
-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, | ||
1233 | enum wb_reason reason) | ||
1214 | { | 1234 | { |
1215 | DECLARE_COMPLETION_ONSTACK(done); | 1235 | DECLARE_COMPLETION_ONSTACK(done); |
1216 | struct wb_writeback_work work = { | 1236 | struct wb_writeback_work work = { |
@@ -1219,6 +1239,7 @@ void writeback_inodes_sb_nr(struct super_block *sb, unsigned long nr) | |||
1219 | .tagged_writepages = 1, | 1239 | .tagged_writepages = 1, |
1220 | .done = &done, | 1240 | .done = &done, |
1221 | .nr_pages = nr, | 1241 | .nr_pages = nr, |
1242 | .reason = reason, | ||
1222 | }; | 1243 | }; |
1223 | 1244 | ||
1224 | WARN_ON(!rwsem_is_locked(&sb->s_umount)); | 1245 | WARN_ON(!rwsem_is_locked(&sb->s_umount)); |
@@ -1235,9 +1256,9 @@ EXPORT_SYMBOL(writeback_inodes_sb_nr); | |||
1235 | * on how many (if any) will be written, and this function does not wait | 1256 | * on how many (if any) will be written, and this function does not wait |
1236 | * for IO completion of submitted IO. | 1257 | * for IO completion of submitted IO. |
1237 | */ | 1258 | */ |
1238 | void writeback_inodes_sb(struct super_block *sb) | 1259 | void writeback_inodes_sb(struct super_block *sb, enum wb_reason reason) |
1239 | { | 1260 | { |
1240 | return writeback_inodes_sb_nr(sb, get_nr_dirty_pages()); | 1261 | return writeback_inodes_sb_nr(sb, get_nr_dirty_pages(), reason); |
1241 | } | 1262 | } |
1242 | EXPORT_SYMBOL(writeback_inodes_sb); | 1263 | EXPORT_SYMBOL(writeback_inodes_sb); |
1243 | 1264 | ||
@@ -1248,11 +1269,11 @@ EXPORT_SYMBOL(writeback_inodes_sb); | |||
1248 | * Invoke writeback_inodes_sb if no writeback is currently underway. | 1269 | * Invoke writeback_inodes_sb if no writeback is currently underway. |
1249 | * Returns 1 if writeback was started, 0 if not. | 1270 | * Returns 1 if writeback was started, 0 if not. |
1250 | */ | 1271 | */ |
1251 | int writeback_inodes_sb_if_idle(struct super_block *sb) | 1272 | int writeback_inodes_sb_if_idle(struct super_block *sb, enum wb_reason reason) |
1252 | { | 1273 | { |
1253 | if (!writeback_in_progress(sb->s_bdi)) { | 1274 | if (!writeback_in_progress(sb->s_bdi)) { |
1254 | down_read(&sb->s_umount); | 1275 | down_read(&sb->s_umount); |
1255 | writeback_inodes_sb(sb); | 1276 | writeback_inodes_sb(sb, reason); |
1256 | up_read(&sb->s_umount); | 1277 | up_read(&sb->s_umount); |
1257 | return 1; | 1278 | return 1; |
1258 | } else | 1279 | } else |
@@ -1269,11 +1290,12 @@ EXPORT_SYMBOL(writeback_inodes_sb_if_idle); | |||
1269 | * Returns 1 if writeback was started, 0 if not. | 1290 | * Returns 1 if writeback was started, 0 if not. |
1270 | */ | 1291 | */ |
1271 | int writeback_inodes_sb_nr_if_idle(struct super_block *sb, | 1292 | int writeback_inodes_sb_nr_if_idle(struct super_block *sb, |
1272 | unsigned long nr) | 1293 | unsigned long nr, |
1294 | enum wb_reason reason) | ||
1273 | { | 1295 | { |
1274 | if (!writeback_in_progress(sb->s_bdi)) { | 1296 | if (!writeback_in_progress(sb->s_bdi)) { |
1275 | down_read(&sb->s_umount); | 1297 | down_read(&sb->s_umount); |
1276 | writeback_inodes_sb_nr(sb, nr); | 1298 | writeback_inodes_sb_nr(sb, nr, reason); |
1277 | up_read(&sb->s_umount); | 1299 | up_read(&sb->s_umount); |
1278 | return 1; | 1300 | return 1; |
1279 | } else | 1301 | } else |
@@ -1297,6 +1319,7 @@ void sync_inodes_sb(struct super_block *sb) | |||
1297 | .nr_pages = LONG_MAX, | 1319 | .nr_pages = LONG_MAX, |
1298 | .range_cyclic = 0, | 1320 | .range_cyclic = 0, |
1299 | .done = &done, | 1321 | .done = &done, |
1322 | .reason = WB_REASON_SYNC, | ||
1300 | }; | 1323 | }; |
1301 | 1324 | ||
1302 | WARN_ON(!rwsem_is_locked(&sb->s_umount)); | 1325 | WARN_ON(!rwsem_is_locked(&sb->s_umount)); |
diff --git a/fs/quota/quota.c b/fs/quota/quota.c index 10b6be3ca280..4bae57fc603b 100644 --- a/fs/quota/quota.c +++ b/fs/quota/quota.c | |||
@@ -286,7 +286,7 @@ static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id, | |||
286 | /* caller already holds s_umount */ | 286 | /* caller already holds s_umount */ |
287 | if (sb->s_flags & MS_RDONLY) | 287 | if (sb->s_flags & MS_RDONLY) |
288 | return -EROFS; | 288 | return -EROFS; |
289 | writeback_inodes_sb(sb); | 289 | writeback_inodes_sb(sb, WB_REASON_SYNC); |
290 | return 0; | 290 | return 0; |
291 | default: | 291 | default: |
292 | return -EINVAL; | 292 | return -EINVAL; |
@@ -43,7 +43,7 @@ static int __sync_filesystem(struct super_block *sb, int wait) | |||
43 | if (wait) | 43 | if (wait) |
44 | sync_inodes_sb(sb); | 44 | sync_inodes_sb(sb); |
45 | else | 45 | else |
46 | writeback_inodes_sb(sb); | 46 | writeback_inodes_sb(sb, WB_REASON_SYNC); |
47 | 47 | ||
48 | if (sb->s_op->sync_fs) | 48 | if (sb->s_op->sync_fs) |
49 | sb->s_op->sync_fs(sb, wait); | 49 | sb->s_op->sync_fs(sb, wait); |
@@ -98,7 +98,7 @@ static void sync_filesystems(int wait) | |||
98 | */ | 98 | */ |
99 | SYSCALL_DEFINE0(sync) | 99 | SYSCALL_DEFINE0(sync) |
100 | { | 100 | { |
101 | wakeup_flusher_threads(0); | 101 | wakeup_flusher_threads(0, WB_REASON_SYNC); |
102 | sync_filesystems(0); | 102 | sync_filesystems(0); |
103 | sync_filesystems(1); | 103 | sync_filesystems(1); |
104 | if (unlikely(laptop_mode)) | 104 | if (unlikely(laptop_mode)) |
diff --git a/fs/ubifs/budget.c b/fs/ubifs/budget.c index 315de66e52b2..bc4f94b28706 100644 --- a/fs/ubifs/budget.c +++ b/fs/ubifs/budget.c | |||
@@ -63,7 +63,7 @@ | |||
63 | static void shrink_liability(struct ubifs_info *c, int nr_to_write) | 63 | static void shrink_liability(struct ubifs_info *c, int nr_to_write) |
64 | { | 64 | { |
65 | down_read(&c->vfs_sb->s_umount); | 65 | down_read(&c->vfs_sb->s_umount); |
66 | writeback_inodes_sb(c->vfs_sb); | 66 | writeback_inodes_sb(c->vfs_sb, WB_REASON_FS_FREE_SPACE); |
67 | up_read(&c->vfs_sb->s_umount); | 67 | up_read(&c->vfs_sb->s_umount); |
68 | } | 68 | } |
69 | 69 | ||
diff --git a/include/linux/backing-dev.h b/include/linux/backing-dev.h index c3b92010d894..b1038bd686ac 100644 --- a/include/linux/backing-dev.h +++ b/include/linux/backing-dev.h | |||
@@ -118,7 +118,8 @@ int bdi_register(struct backing_dev_info *bdi, struct device *parent, | |||
118 | int bdi_register_dev(struct backing_dev_info *bdi, dev_t dev); | 118 | int bdi_register_dev(struct backing_dev_info *bdi, dev_t dev); |
119 | void bdi_unregister(struct backing_dev_info *bdi); | 119 | void bdi_unregister(struct backing_dev_info *bdi); |
120 | int bdi_setup_and_register(struct backing_dev_info *, char *, unsigned int); | 120 | int bdi_setup_and_register(struct backing_dev_info *, char *, unsigned int); |
121 | void bdi_start_writeback(struct backing_dev_info *bdi, long nr_pages); | 121 | void bdi_start_writeback(struct backing_dev_info *bdi, long nr_pages, |
122 | enum wb_reason reason); | ||
122 | void bdi_start_background_writeback(struct backing_dev_info *bdi); | 123 | void bdi_start_background_writeback(struct backing_dev_info *bdi); |
123 | int bdi_writeback_thread(void *data); | 124 | int bdi_writeback_thread(void *data); |
124 | int bdi_has_dirty_io(struct backing_dev_info *bdi); | 125 | int bdi_has_dirty_io(struct backing_dev_info *bdi); |
diff --git a/include/linux/writeback.h b/include/linux/writeback.h index ddb4652cb337..a378c295851f 100644 --- a/include/linux/writeback.h +++ b/include/linux/writeback.h | |||
@@ -39,6 +39,23 @@ enum writeback_sync_modes { | |||
39 | }; | 39 | }; |
40 | 40 | ||
41 | /* | 41 | /* |
42 | * why some writeback work was initiated | ||
43 | */ | ||
44 | enum wb_reason { | ||
45 | WB_REASON_BACKGROUND, | ||
46 | WB_REASON_TRY_TO_FREE_PAGES, | ||
47 | WB_REASON_SYNC, | ||
48 | WB_REASON_PERIODIC, | ||
49 | WB_REASON_LAPTOP_TIMER, | ||
50 | WB_REASON_FREE_MORE_MEM, | ||
51 | WB_REASON_FS_FREE_SPACE, | ||
52 | WB_REASON_FORKER_THREAD, | ||
53 | |||
54 | WB_REASON_MAX, | ||
55 | }; | ||
56 | extern const char *wb_reason_name[]; | ||
57 | |||
58 | /* | ||
42 | * A control structure which tells the writeback code what to do. These are | 59 | * A control structure which tells the writeback code what to do. These are |
43 | * always on the stack, and hence need no locking. They are always initialised | 60 | * always on the stack, and hence need no locking. They are always initialised |
44 | * in a manner such that unspecified fields are set to zero. | 61 | * in a manner such that unspecified fields are set to zero. |
@@ -69,14 +86,17 @@ struct writeback_control { | |||
69 | */ | 86 | */ |
70 | struct bdi_writeback; | 87 | struct bdi_writeback; |
71 | int inode_wait(void *); | 88 | int inode_wait(void *); |
72 | void writeback_inodes_sb(struct super_block *); | 89 | void writeback_inodes_sb(struct super_block *, enum wb_reason reason); |
73 | void writeback_inodes_sb_nr(struct super_block *, unsigned long nr); | 90 | void writeback_inodes_sb_nr(struct super_block *, unsigned long nr, |
74 | int writeback_inodes_sb_if_idle(struct super_block *); | 91 | enum wb_reason reason); |
75 | int writeback_inodes_sb_nr_if_idle(struct super_block *, unsigned long nr); | 92 | int writeback_inodes_sb_if_idle(struct super_block *, enum wb_reason reason); |
93 | int writeback_inodes_sb_nr_if_idle(struct super_block *, unsigned long nr, | ||
94 | enum wb_reason reason); | ||
76 | void sync_inodes_sb(struct super_block *); | 95 | void sync_inodes_sb(struct super_block *); |
77 | long writeback_inodes_wb(struct bdi_writeback *wb, long nr_pages); | 96 | long writeback_inodes_wb(struct bdi_writeback *wb, long nr_pages, |
97 | enum wb_reason reason); | ||
78 | long wb_do_writeback(struct bdi_writeback *wb, int force_wait); | 98 | long wb_do_writeback(struct bdi_writeback *wb, int force_wait); |
79 | void wakeup_flusher_threads(long nr_pages); | 99 | void wakeup_flusher_threads(long nr_pages, enum wb_reason reason); |
80 | 100 | ||
81 | /* writeback.h requires fs.h; it, too, is not included from here. */ | 101 | /* writeback.h requires fs.h; it, too, is not included from here. */ |
82 | static inline void wait_on_inode(struct inode *inode) | 102 | static inline void wait_on_inode(struct inode *inode) |
diff --git a/include/trace/events/writeback.h b/include/trace/events/writeback.h index 1261db3916cc..b99caa8b780c 100644 --- a/include/trace/events/writeback.h +++ b/include/trace/events/writeback.h | |||
@@ -34,6 +34,7 @@ DECLARE_EVENT_CLASS(writeback_work_class, | |||
34 | __field(int, for_kupdate) | 34 | __field(int, for_kupdate) |
35 | __field(int, range_cyclic) | 35 | __field(int, range_cyclic) |
36 | __field(int, for_background) | 36 | __field(int, for_background) |
37 | __field(int, reason) | ||
37 | ), | 38 | ), |
38 | TP_fast_assign( | 39 | TP_fast_assign( |
39 | strncpy(__entry->name, dev_name(bdi->dev), 32); | 40 | strncpy(__entry->name, dev_name(bdi->dev), 32); |
@@ -43,16 +44,18 @@ DECLARE_EVENT_CLASS(writeback_work_class, | |||
43 | __entry->for_kupdate = work->for_kupdate; | 44 | __entry->for_kupdate = work->for_kupdate; |
44 | __entry->range_cyclic = work->range_cyclic; | 45 | __entry->range_cyclic = work->range_cyclic; |
45 | __entry->for_background = work->for_background; | 46 | __entry->for_background = work->for_background; |
47 | __entry->reason = work->reason; | ||
46 | ), | 48 | ), |
47 | TP_printk("bdi %s: sb_dev %d:%d nr_pages=%ld sync_mode=%d " | 49 | TP_printk("bdi %s: sb_dev %d:%d nr_pages=%ld sync_mode=%d " |
48 | "kupdate=%d range_cyclic=%d background=%d", | 50 | "kupdate=%d range_cyclic=%d background=%d reason=%s", |
49 | __entry->name, | 51 | __entry->name, |
50 | MAJOR(__entry->sb_dev), MINOR(__entry->sb_dev), | 52 | MAJOR(__entry->sb_dev), MINOR(__entry->sb_dev), |
51 | __entry->nr_pages, | 53 | __entry->nr_pages, |
52 | __entry->sync_mode, | 54 | __entry->sync_mode, |
53 | __entry->for_kupdate, | 55 | __entry->for_kupdate, |
54 | __entry->range_cyclic, | 56 | __entry->range_cyclic, |
55 | __entry->for_background | 57 | __entry->for_background, |
58 | wb_reason_name[__entry->reason] | ||
56 | ) | 59 | ) |
57 | ); | 60 | ); |
58 | #define DEFINE_WRITEBACK_WORK_EVENT(name) \ | 61 | #define DEFINE_WRITEBACK_WORK_EVENT(name) \ |
@@ -165,6 +168,7 @@ TRACE_EVENT(writeback_queue_io, | |||
165 | __field(unsigned long, older) | 168 | __field(unsigned long, older) |
166 | __field(long, age) | 169 | __field(long, age) |
167 | __field(int, moved) | 170 | __field(int, moved) |
171 | __field(int, reason) | ||
168 | ), | 172 | ), |
169 | TP_fast_assign( | 173 | TP_fast_assign( |
170 | unsigned long *older_than_this = work->older_than_this; | 174 | unsigned long *older_than_this = work->older_than_this; |
@@ -173,12 +177,14 @@ TRACE_EVENT(writeback_queue_io, | |||
173 | __entry->age = older_than_this ? | 177 | __entry->age = older_than_this ? |
174 | (jiffies - *older_than_this) * 1000 / HZ : -1; | 178 | (jiffies - *older_than_this) * 1000 / HZ : -1; |
175 | __entry->moved = moved; | 179 | __entry->moved = moved; |
180 | __entry->reason = work->reason; | ||
176 | ), | 181 | ), |
177 | TP_printk("bdi %s: older=%lu age=%ld enqueue=%d", | 182 | TP_printk("bdi %s: older=%lu age=%ld enqueue=%d reason=%s", |
178 | __entry->name, | 183 | __entry->name, |
179 | __entry->older, /* older_than_this in jiffies */ | 184 | __entry->older, /* older_than_this in jiffies */ |
180 | __entry->age, /* older_than_this in relative milliseconds */ | 185 | __entry->age, /* older_than_this in relative milliseconds */ |
181 | __entry->moved) | 186 | __entry->moved, |
187 | wb_reason_name[__entry->reason]) | ||
182 | ); | 188 | ); |
183 | 189 | ||
184 | TRACE_EVENT(global_dirty_state, | 190 | TRACE_EVENT(global_dirty_state, |
diff --git a/mm/backing-dev.c b/mm/backing-dev.c index 5dcaa3c756d1..dd8916feb05e 100644 --- a/mm/backing-dev.c +++ b/mm/backing-dev.c | |||
@@ -476,7 +476,8 @@ static int bdi_forker_thread(void *ptr) | |||
476 | * the bdi from the thread. Hopefully 1024 is | 476 | * the bdi from the thread. Hopefully 1024 is |
477 | * large enough for efficient IO. | 477 | * large enough for efficient IO. |
478 | */ | 478 | */ |
479 | writeback_inodes_wb(&bdi->wb, 1024); | 479 | writeback_inodes_wb(&bdi->wb, 1024, |
480 | WB_REASON_FORKER_THREAD); | ||
480 | } else { | 481 | } else { |
481 | /* | 482 | /* |
482 | * The spinlock makes sure we do not lose | 483 | * The spinlock makes sure we do not lose |
diff --git a/mm/page-writeback.c b/mm/page-writeback.c index 45d36f7dc169..650846b61584 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c | |||
@@ -1301,7 +1301,8 @@ void laptop_mode_timer_fn(unsigned long data) | |||
1301 | * threshold | 1301 | * threshold |
1302 | */ | 1302 | */ |
1303 | if (bdi_has_dirty_io(&q->backing_dev_info)) | 1303 | if (bdi_has_dirty_io(&q->backing_dev_info)) |
1304 | bdi_start_writeback(&q->backing_dev_info, nr_pages); | 1304 | bdi_start_writeback(&q->backing_dev_info, nr_pages, |
1305 | WB_REASON_LAPTOP_TIMER); | ||
1305 | } | 1306 | } |
1306 | 1307 | ||
1307 | /* | 1308 | /* |
diff --git a/mm/vmscan.c b/mm/vmscan.c index b55699cd9067..c735bd770d3d 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c | |||
@@ -2181,7 +2181,8 @@ static unsigned long do_try_to_free_pages(struct zonelist *zonelist, | |||
2181 | */ | 2181 | */ |
2182 | writeback_threshold = sc->nr_to_reclaim + sc->nr_to_reclaim / 2; | 2182 | writeback_threshold = sc->nr_to_reclaim + sc->nr_to_reclaim / 2; |
2183 | if (total_scanned > writeback_threshold) { | 2183 | if (total_scanned > writeback_threshold) { |
2184 | wakeup_flusher_threads(laptop_mode ? 0 : total_scanned); | 2184 | wakeup_flusher_threads(laptop_mode ? 0 : total_scanned, |
2185 | WB_REASON_TRY_TO_FREE_PAGES); | ||
2185 | sc->may_writepage = 1; | 2186 | sc->may_writepage = 1; |
2186 | } | 2187 | } |
2187 | 2188 | ||