diff options
author | Tejun Heo <tj@kernel.org> | 2013-01-11 16:06:37 -0500 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2013-01-14 09:00:36 -0500 |
commit | 9fb0a7da0c528d9bd49b597aa63b1fe2216c7203 (patch) | |
tree | 146b065709010fd41f4a48e8a494b65b965fc0e8 | |
parent | 5305cb830834549b9203ad4d009ad5483c5e293f (diff) |
writeback: add more tracepoints
Add tracepoints for page dirtying, writeback_single_inode start, inode
dirtying and writeback. For the latter two inode events, a pair of
events are defined to denote start and end of the operations (the
starting one has _start suffix and the one w/o suffix happens after
the operation is complete). These inode ops are FS specific and can
be non-trivial and having enclosing tracepoints is useful for external
tracers.
This is part of tracepoint additions to improve visiblity into
dirtying / writeback operations for io tracer and userland.
v2: writeback_dirty_inode[_start] TPs may be called for files on
pseudo FSes w/ unregistered bdi. Check whether bdi->dev is %NULL
before dereferencing.
v3: buffer dirtying moved to a block TP.
Signed-off-by: Tejun Heo <tj@kernel.org>
Reviewed-by: Jan Kara <jack@suse.cz>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
-rw-r--r-- | fs/fs-writeback.c | 16 | ||||
-rw-r--r-- | include/trace/events/writeback.h | 116 | ||||
-rw-r--r-- | mm/page-writeback.c | 2 |
3 files changed, 132 insertions, 2 deletions
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index 310972b72a66..359494ea1bde 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c | |||
@@ -318,8 +318,14 @@ static void queue_io(struct bdi_writeback *wb, struct wb_writeback_work *work) | |||
318 | 318 | ||
319 | static int write_inode(struct inode *inode, struct writeback_control *wbc) | 319 | static int write_inode(struct inode *inode, struct writeback_control *wbc) |
320 | { | 320 | { |
321 | if (inode->i_sb->s_op->write_inode && !is_bad_inode(inode)) | 321 | int ret; |
322 | return inode->i_sb->s_op->write_inode(inode, wbc); | 322 | |
323 | if (inode->i_sb->s_op->write_inode && !is_bad_inode(inode)) { | ||
324 | trace_writeback_write_inode_start(inode, wbc); | ||
325 | ret = inode->i_sb->s_op->write_inode(inode, wbc); | ||
326 | trace_writeback_write_inode(inode, wbc); | ||
327 | return ret; | ||
328 | } | ||
323 | return 0; | 329 | return 0; |
324 | } | 330 | } |
325 | 331 | ||
@@ -450,6 +456,8 @@ __writeback_single_inode(struct inode *inode, struct writeback_control *wbc) | |||
450 | 456 | ||
451 | WARN_ON(!(inode->i_state & I_SYNC)); | 457 | WARN_ON(!(inode->i_state & I_SYNC)); |
452 | 458 | ||
459 | trace_writeback_single_inode_start(inode, wbc, nr_to_write); | ||
460 | |||
453 | ret = do_writepages(mapping, wbc); | 461 | ret = do_writepages(mapping, wbc); |
454 | 462 | ||
455 | /* | 463 | /* |
@@ -1150,8 +1158,12 @@ void __mark_inode_dirty(struct inode *inode, int flags) | |||
1150 | * dirty the inode itself | 1158 | * dirty the inode itself |
1151 | */ | 1159 | */ |
1152 | if (flags & (I_DIRTY_SYNC | I_DIRTY_DATASYNC)) { | 1160 | if (flags & (I_DIRTY_SYNC | I_DIRTY_DATASYNC)) { |
1161 | trace_writeback_dirty_inode_start(inode, flags); | ||
1162 | |||
1153 | if (sb->s_op->dirty_inode) | 1163 | if (sb->s_op->dirty_inode) |
1154 | sb->s_op->dirty_inode(inode, flags); | 1164 | sb->s_op->dirty_inode(inode, flags); |
1165 | |||
1166 | trace_writeback_dirty_inode(inode, flags); | ||
1155 | } | 1167 | } |
1156 | 1168 | ||
1157 | /* | 1169 | /* |
diff --git a/include/trace/events/writeback.h b/include/trace/events/writeback.h index b453d92c2253..6a16fd2e70ed 100644 --- a/include/trace/events/writeback.h +++ b/include/trace/events/writeback.h | |||
@@ -32,6 +32,115 @@ | |||
32 | 32 | ||
33 | struct wb_writeback_work; | 33 | struct wb_writeback_work; |
34 | 34 | ||
35 | TRACE_EVENT(writeback_dirty_page, | ||
36 | |||
37 | TP_PROTO(struct page *page, struct address_space *mapping), | ||
38 | |||
39 | TP_ARGS(page, mapping), | ||
40 | |||
41 | TP_STRUCT__entry ( | ||
42 | __array(char, name, 32) | ||
43 | __field(unsigned long, ino) | ||
44 | __field(pgoff_t, index) | ||
45 | ), | ||
46 | |||
47 | TP_fast_assign( | ||
48 | strncpy(__entry->name, | ||
49 | mapping ? dev_name(mapping->backing_dev_info->dev) : "(unknown)", 32); | ||
50 | __entry->ino = mapping ? mapping->host->i_ino : 0; | ||
51 | __entry->index = page->index; | ||
52 | ), | ||
53 | |||
54 | TP_printk("bdi %s: ino=%lu index=%lu", | ||
55 | __entry->name, | ||
56 | __entry->ino, | ||
57 | __entry->index | ||
58 | ) | ||
59 | ); | ||
60 | |||
61 | DECLARE_EVENT_CLASS(writeback_dirty_inode_template, | ||
62 | |||
63 | TP_PROTO(struct inode *inode, int flags), | ||
64 | |||
65 | TP_ARGS(inode, flags), | ||
66 | |||
67 | TP_STRUCT__entry ( | ||
68 | __array(char, name, 32) | ||
69 | __field(unsigned long, ino) | ||
70 | __field(unsigned long, flags) | ||
71 | ), | ||
72 | |||
73 | TP_fast_assign( | ||
74 | struct backing_dev_info *bdi = inode->i_mapping->backing_dev_info; | ||
75 | |||
76 | /* may be called for files on pseudo FSes w/ unregistered bdi */ | ||
77 | strncpy(__entry->name, | ||
78 | bdi->dev ? dev_name(bdi->dev) : "(unknown)", 32); | ||
79 | __entry->ino = inode->i_ino; | ||
80 | __entry->flags = flags; | ||
81 | ), | ||
82 | |||
83 | TP_printk("bdi %s: ino=%lu flags=%s", | ||
84 | __entry->name, | ||
85 | __entry->ino, | ||
86 | show_inode_state(__entry->flags) | ||
87 | ) | ||
88 | ); | ||
89 | |||
90 | DEFINE_EVENT(writeback_dirty_inode_template, writeback_dirty_inode_start, | ||
91 | |||
92 | TP_PROTO(struct inode *inode, int flags), | ||
93 | |||
94 | TP_ARGS(inode, flags) | ||
95 | ); | ||
96 | |||
97 | DEFINE_EVENT(writeback_dirty_inode_template, writeback_dirty_inode, | ||
98 | |||
99 | TP_PROTO(struct inode *inode, int flags), | ||
100 | |||
101 | TP_ARGS(inode, flags) | ||
102 | ); | ||
103 | |||
104 | DECLARE_EVENT_CLASS(writeback_write_inode_template, | ||
105 | |||
106 | TP_PROTO(struct inode *inode, struct writeback_control *wbc), | ||
107 | |||
108 | TP_ARGS(inode, wbc), | ||
109 | |||
110 | TP_STRUCT__entry ( | ||
111 | __array(char, name, 32) | ||
112 | __field(unsigned long, ino) | ||
113 | __field(int, sync_mode) | ||
114 | ), | ||
115 | |||
116 | TP_fast_assign( | ||
117 | strncpy(__entry->name, | ||
118 | dev_name(inode->i_mapping->backing_dev_info->dev), 32); | ||
119 | __entry->ino = inode->i_ino; | ||
120 | __entry->sync_mode = wbc->sync_mode; | ||
121 | ), | ||
122 | |||
123 | TP_printk("bdi %s: ino=%lu sync_mode=%d", | ||
124 | __entry->name, | ||
125 | __entry->ino, | ||
126 | __entry->sync_mode | ||
127 | ) | ||
128 | ); | ||
129 | |||
130 | DEFINE_EVENT(writeback_write_inode_template, writeback_write_inode_start, | ||
131 | |||
132 | TP_PROTO(struct inode *inode, struct writeback_control *wbc), | ||
133 | |||
134 | TP_ARGS(inode, wbc) | ||
135 | ); | ||
136 | |||
137 | DEFINE_EVENT(writeback_write_inode_template, writeback_write_inode, | ||
138 | |||
139 | TP_PROTO(struct inode *inode, struct writeback_control *wbc), | ||
140 | |||
141 | TP_ARGS(inode, wbc) | ||
142 | ); | ||
143 | |||
35 | DECLARE_EVENT_CLASS(writeback_work_class, | 144 | DECLARE_EVENT_CLASS(writeback_work_class, |
36 | TP_PROTO(struct backing_dev_info *bdi, struct wb_writeback_work *work), | 145 | TP_PROTO(struct backing_dev_info *bdi, struct wb_writeback_work *work), |
37 | TP_ARGS(bdi, work), | 146 | TP_ARGS(bdi, work), |
@@ -479,6 +588,13 @@ DECLARE_EVENT_CLASS(writeback_single_inode_template, | |||
479 | ) | 588 | ) |
480 | ); | 589 | ); |
481 | 590 | ||
591 | DEFINE_EVENT(writeback_single_inode_template, writeback_single_inode_start, | ||
592 | TP_PROTO(struct inode *inode, | ||
593 | struct writeback_control *wbc, | ||
594 | unsigned long nr_to_write), | ||
595 | TP_ARGS(inode, wbc, nr_to_write) | ||
596 | ); | ||
597 | |||
482 | DEFINE_EVENT(writeback_single_inode_template, writeback_single_inode, | 598 | DEFINE_EVENT(writeback_single_inode_template, writeback_single_inode, |
483 | TP_PROTO(struct inode *inode, | 599 | TP_PROTO(struct inode *inode, |
484 | struct writeback_control *wbc, | 600 | struct writeback_control *wbc, |
diff --git a/mm/page-writeback.c b/mm/page-writeback.c index 0713bfbf0954..3734cefd4de4 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c | |||
@@ -1982,6 +1982,8 @@ int __set_page_dirty_no_writeback(struct page *page) | |||
1982 | */ | 1982 | */ |
1983 | void account_page_dirtied(struct page *page, struct address_space *mapping) | 1983 | void account_page_dirtied(struct page *page, struct address_space *mapping) |
1984 | { | 1984 | { |
1985 | trace_writeback_dirty_page(page, mapping); | ||
1986 | |||
1985 | if (mapping_cap_account_dirty(mapping)) { | 1987 | if (mapping_cap_account_dirty(mapping)) { |
1986 | __inc_zone_page_state(page, NR_FILE_DIRTY); | 1988 | __inc_zone_page_state(page, NR_FILE_DIRTY); |
1987 | __inc_zone_page_state(page, NR_DIRTIED); | 1989 | __inc_zone_page_state(page, NR_DIRTIED); |