diff options
-rw-r--r-- | fs/fs-writeback.c | 38 | ||||
-rw-r--r-- | include/trace/events/writeback.h | 91 | ||||
-rw-r--r-- | mm/backing-dev.c | 3 |
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 | */ | ||
36 | int 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 | */ | ||
60 | int 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) | |||
65 | static void bdi_queue_work(struct backing_dev_info *bdi, | 74 | static 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 | |||
10 | struct wb_writeback_work; | ||
11 | |||
12 | DECLARE_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) \ | ||
45 | DEFINE_EVENT(writeback_work_class, name, \ | ||
46 | TP_PROTO(struct backing_dev_info *bdi, struct wb_writeback_work *work), \ | ||
47 | TP_ARGS(bdi, work)) | ||
48 | DEFINE_WRITEBACK_WORK_EVENT(writeback_nothread); | ||
49 | DEFINE_WRITEBACK_WORK_EVENT(writeback_queue); | ||
50 | DEFINE_WRITEBACK_WORK_EVENT(writeback_exec); | ||
51 | |||
52 | TRACE_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 | |||
64 | DECLARE_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) \ | ||
78 | DEFINE_EVENT(writeback_class, name, \ | ||
79 | TP_PROTO(struct backing_dev_info *bdi), \ | ||
80 | TP_ARGS(bdi)) | ||
81 | |||
82 | DEFINE_WRITEBACK_EVENT(writeback_nowork); | ||
83 | DEFINE_WRITEBACK_EVENT(writeback_bdi_register); | ||
84 | DEFINE_WRITEBACK_EVENT(writeback_bdi_unregister); | ||
85 | DEFINE_WRITEBACK_EVENT(writeback_thread_start); | ||
86 | DEFINE_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 | ||
14 | static atomic_long_t bdi_seq = ATOMIC_LONG_INIT(0); | 15 | static 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); | ||
521 | exit: | 523 | exit: |
522 | return ret; | 524 | return ret; |
523 | } | 525 | } |
@@ -578,6 +580,7 @@ static void bdi_prune_sb(struct backing_dev_info *bdi) | |||
578 | void bdi_unregister(struct backing_dev_info *bdi) | 580 | void 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)) |