aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/fs-writeback.c38
-rw-r--r--include/trace/events/writeback.h91
-rw-r--r--mm/backing-dev.c3
3 files changed, 124 insertions, 8 deletions
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index c8471b3ddccf..73acab4dc2b7 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -26,15 +26,9 @@
26#include <linux/blkdev.h> 26#include <linux/blkdev.h>
27#include <linux/backing-dev.h> 27#include <linux/backing-dev.h>
28#include <linux/buffer_head.h> 28#include <linux/buffer_head.h>
29#include <linux/tracepoint.h>
29#include "internal.h" 30#include "internal.h"
30 31
31#define inode_to_bdi(inode) ((inode)->i_mapping->backing_dev_info)
32
33/*
34 * We don't actually have pdflush, but this one is exported though /proc...
35 */
36int nr_pdflush_threads;
37
38/* 32/*
39 * Passed into wb_writeback(), essentially a subset of writeback_control 33 * Passed into wb_writeback(), essentially a subset of writeback_control
40 */ 34 */
@@ -50,6 +44,21 @@ struct wb_writeback_work {
50 struct completion *done; /* set if the caller waits */ 44 struct completion *done; /* set if the caller waits */
51}; 45};
52 46
47/*
48 * Include the creation of the trace points after defining the
49 * wb_writeback_work structure so that the definition remains local to this
50 * file.
51 */
52#define CREATE_TRACE_POINTS
53#include <trace/events/writeback.h>
54
55#define inode_to_bdi(inode) ((inode)->i_mapping->backing_dev_info)
56
57/*
58 * We don't actually have pdflush, but this one is exported though /proc...
59 */
60int nr_pdflush_threads;
61
53/** 62/**
54 * writeback_in_progress - determine whether there is writeback in progress 63 * writeback_in_progress - determine whether there is writeback in progress
55 * @bdi: the device's backing_dev_info structure. 64 * @bdi: the device's backing_dev_info structure.
@@ -65,6 +74,8 @@ int writeback_in_progress(struct backing_dev_info *bdi)
65static void bdi_queue_work(struct backing_dev_info *bdi, 74static void bdi_queue_work(struct backing_dev_info *bdi,
66 struct wb_writeback_work *work) 75 struct wb_writeback_work *work)
67{ 76{
77 trace_writeback_queue(bdi, work);
78
68 spin_lock(&bdi->wb_lock); 79 spin_lock(&bdi->wb_lock);
69 list_add_tail(&work->list, &bdi->work_list); 80 list_add_tail(&work->list, &bdi->work_list);
70 spin_unlock(&bdi->wb_lock); 81 spin_unlock(&bdi->wb_lock);
@@ -74,6 +85,7 @@ static void bdi_queue_work(struct backing_dev_info *bdi,
74 * it gets created and wakes up, we'll run this work. 85 * it gets created and wakes up, we'll run this work.
75 */ 86 */
76 if (unlikely(!bdi->wb.task)) { 87 if (unlikely(!bdi->wb.task)) {
88 trace_writeback_nothread(bdi, work);
77 wake_up_process(default_backing_dev_info.wb.task); 89 wake_up_process(default_backing_dev_info.wb.task);
78 } else { 90 } else {
79 struct bdi_writeback *wb = &bdi->wb; 91 struct bdi_writeback *wb = &bdi->wb;
@@ -95,8 +107,10 @@ __bdi_start_writeback(struct backing_dev_info *bdi, long nr_pages,
95 */ 107 */
96 work = kzalloc(sizeof(*work), GFP_ATOMIC); 108 work = kzalloc(sizeof(*work), GFP_ATOMIC);
97 if (!work) { 109 if (!work) {
98 if (bdi->wb.task) 110 if (bdi->wb.task) {
111 trace_writeback_nowork(bdi);
99 wake_up_process(bdi->wb.task); 112 wake_up_process(bdi->wb.task);
113 }
100 return; 114 return;
101 } 115 }
102 116
@@ -751,6 +765,8 @@ long wb_do_writeback(struct bdi_writeback *wb, int force_wait)
751 if (force_wait) 765 if (force_wait)
752 work->sync_mode = WB_SYNC_ALL; 766 work->sync_mode = WB_SYNC_ALL;
753 767
768 trace_writeback_exec(bdi, work);
769
754 wrote += wb_writeback(wb, work); 770 wrote += wb_writeback(wb, work);
755 771
756 /* 772 /*
@@ -805,9 +821,13 @@ int bdi_writeback_thread(void *data)
805 smp_mb__after_clear_bit(); 821 smp_mb__after_clear_bit();
806 wake_up_bit(&bdi->state, BDI_pending); 822 wake_up_bit(&bdi->state, BDI_pending);
807 823
824 trace_writeback_thread_start(bdi);
825
808 while (!kthread_should_stop()) { 826 while (!kthread_should_stop()) {
809 pages_written = wb_do_writeback(wb, 0); 827 pages_written = wb_do_writeback(wb, 0);
810 828
829 trace_writeback_pages_written(pages_written);
830
811 if (pages_written) 831 if (pages_written)
812 last_active = jiffies; 832 last_active = jiffies;
813 else if (wait_jiffies != -1UL) { 833 else if (wait_jiffies != -1UL) {
@@ -845,6 +865,8 @@ int bdi_writeback_thread(void *data)
845 */ 865 */
846 if (!list_empty(&bdi->work_list)) 866 if (!list_empty(&bdi->work_list))
847 wb_do_writeback(wb, 1); 867 wb_do_writeback(wb, 1);
868
869 trace_writeback_thread_stop(bdi);
848 return 0; 870 return 0;
849} 871}
850 872
diff --git a/include/trace/events/writeback.h b/include/trace/events/writeback.h
new file mode 100644
index 000000000000..562fcae10d9d
--- /dev/null
+++ b/include/trace/events/writeback.h
@@ -0,0 +1,91 @@
1#undef TRACE_SYSTEM
2#define TRACE_SYSTEM writeback
3
4#if !defined(_TRACE_WRITEBACK_H) || defined(TRACE_HEADER_MULTI_READ)
5#define _TRACE_WRITEBACK_H
6
7#include <linux/backing-dev.h>
8#include <linux/writeback.h>
9
10struct wb_writeback_work;
11
12DECLARE_EVENT_CLASS(writeback_work_class,
13 TP_PROTO(struct backing_dev_info *bdi, struct wb_writeback_work *work),
14 TP_ARGS(bdi, work),
15 TP_STRUCT__entry(
16 __array(char, name, 32)
17 __field(long, nr_pages)
18 __field(dev_t, sb_dev)
19 __field(int, sync_mode)
20 __field(int, for_kupdate)
21 __field(int, range_cyclic)
22 __field(int, for_background)
23 ),
24 TP_fast_assign(
25 strncpy(__entry->name, dev_name(bdi->dev), 32);
26 __entry->nr_pages = work->nr_pages;
27 __entry->sb_dev = work->sb ? work->sb->s_dev : 0;
28 __entry->sync_mode = work->sync_mode;
29 __entry->for_kupdate = work->for_kupdate;
30 __entry->range_cyclic = work->range_cyclic;
31 __entry->for_background = work->for_background;
32 ),
33 TP_printk("bdi %s: sb_dev %d:%d nr_pages=%ld sync_mode=%d "
34 "kupdate=%d range_cyclic=%d background=%d",
35 __entry->name,
36 MAJOR(__entry->sb_dev), MINOR(__entry->sb_dev),
37 __entry->nr_pages,
38 __entry->sync_mode,
39 __entry->for_kupdate,
40 __entry->range_cyclic,
41 __entry->for_background
42 )
43);
44#define DEFINE_WRITEBACK_WORK_EVENT(name) \
45DEFINE_EVENT(writeback_work_class, name, \
46 TP_PROTO(struct backing_dev_info *bdi, struct wb_writeback_work *work), \
47 TP_ARGS(bdi, work))
48DEFINE_WRITEBACK_WORK_EVENT(writeback_nothread);
49DEFINE_WRITEBACK_WORK_EVENT(writeback_queue);
50DEFINE_WRITEBACK_WORK_EVENT(writeback_exec);
51
52TRACE_EVENT(writeback_pages_written,
53 TP_PROTO(long pages_written),
54 TP_ARGS(pages_written),
55 TP_STRUCT__entry(
56 __field(long, pages)
57 ),
58 TP_fast_assign(
59 __entry->pages = pages_written;
60 ),
61 TP_printk("%ld", __entry->pages)
62);
63
64DECLARE_EVENT_CLASS(writeback_class,
65 TP_PROTO(struct backing_dev_info *bdi),
66 TP_ARGS(bdi),
67 TP_STRUCT__entry(
68 __array(char, name, 32)
69 ),
70 TP_fast_assign(
71 strncpy(__entry->name, dev_name(bdi->dev), 32);
72 ),
73 TP_printk("bdi %s",
74 __entry->name
75 )
76);
77#define DEFINE_WRITEBACK_EVENT(name) \
78DEFINE_EVENT(writeback_class, name, \
79 TP_PROTO(struct backing_dev_info *bdi), \
80 TP_ARGS(bdi))
81
82DEFINE_WRITEBACK_EVENT(writeback_nowork);
83DEFINE_WRITEBACK_EVENT(writeback_bdi_register);
84DEFINE_WRITEBACK_EVENT(writeback_bdi_unregister);
85DEFINE_WRITEBACK_EVENT(writeback_thread_start);
86DEFINE_WRITEBACK_EVENT(writeback_thread_stop);
87
88#endif /* _TRACE_WRITEBACK_H */
89
90/* This part must be outside protection */
91#include <trace/define_trace.h>
diff --git a/mm/backing-dev.c b/mm/backing-dev.c
index bceac647e4d1..ac78a3336181 100644
--- a/mm/backing-dev.c
+++ b/mm/backing-dev.c
@@ -10,6 +10,7 @@
10#include <linux/module.h> 10#include <linux/module.h>
11#include <linux/writeback.h> 11#include <linux/writeback.h>
12#include <linux/device.h> 12#include <linux/device.h>
13#include <trace/events/writeback.h>
13 14
14static atomic_long_t bdi_seq = ATOMIC_LONG_INIT(0); 15static atomic_long_t bdi_seq = ATOMIC_LONG_INIT(0);
15 16
@@ -518,6 +519,7 @@ int bdi_register(struct backing_dev_info *bdi, struct device *parent,
518 519
519 bdi_debug_register(bdi, dev_name(dev)); 520 bdi_debug_register(bdi, dev_name(dev));
520 set_bit(BDI_registered, &bdi->state); 521 set_bit(BDI_registered, &bdi->state);
522 trace_writeback_bdi_register(bdi);
521exit: 523exit:
522 return ret; 524 return ret;
523} 525}
@@ -578,6 +580,7 @@ static void bdi_prune_sb(struct backing_dev_info *bdi)
578void bdi_unregister(struct backing_dev_info *bdi) 580void bdi_unregister(struct backing_dev_info *bdi)
579{ 581{
580 if (bdi->dev) { 582 if (bdi->dev) {
583 trace_writeback_bdi_unregister(bdi);
581 bdi_prune_sb(bdi); 584 bdi_prune_sb(bdi);
582 585
583 if (!bdi_cap_flush_forker(bdi)) 586 if (!bdi_cap_flush_forker(bdi))