3 Copyright (c) 2013 The Chromium Authors. All rights reserved.
4 Use of this source code is governed by a BSD-style license that can be
5 found in the LICENSE file.
8 <link rel="import" href="/tracing/importer/linux_perf/parser.html">
14 * @fileoverview Parses filesystem and block device events in the Linux event
17 tvcm.exportTo('tracing.importer.linux_perf', function() {
19 var Parser = tracing.importer.linux_perf.Parser;
22 * Parses linux filesystem and block device trace events.
25 function DiskParser(importer) {
26 Parser.call(this, importer);
28 importer.registerEventHandler('f2fs_write_begin',
29 DiskParser.prototype.f2fsWriteBeginEvent.bind(this));
30 importer.registerEventHandler('f2fs_write_end',
31 DiskParser.prototype.f2fsWriteEndEvent.bind(this));
32 importer.registerEventHandler('f2fs_sync_file_enter',
33 DiskParser.prototype.f2fsSyncFileEnterEvent.bind(this));
34 importer.registerEventHandler('f2fs_sync_file_exit',
35 DiskParser.prototype.f2fsSyncFileExitEvent.bind(this));
36 importer.registerEventHandler('ext4_sync_file_enter',
37 DiskParser.prototype.ext4SyncFileEnterEvent.bind(this));
38 importer.registerEventHandler('ext4_sync_file_exit',
39 DiskParser.prototype.ext4SyncFileExitEvent.bind(this));
40 importer.registerEventHandler('ext4_da_write_begin',
41 DiskParser.prototype.ext4WriteBeginEvent.bind(this));
42 importer.registerEventHandler('ext4_da_write_end',
43 DiskParser.prototype.ext4WriteEndEvent.bind(this));
44 importer.registerEventHandler('block_rq_issue',
45 DiskParser.prototype.blockRqIssueEvent.bind(this));
46 importer.registerEventHandler('block_rq_complete',
47 DiskParser.prototype.blockRqCompleteEvent.bind(this));
50 DiskParser.prototype = {
51 __proto__: Parser.prototype,
53 openAsyncSlice: function(ts, category, threadName, pid, key, name) {
54 var kthread = this.importer.getOrCreateKernelThread(
55 category + ':' + threadName, pid);
56 var slice = new tracing.trace_model.AsyncSlice(
57 category, name, tvcm.ui.getStringColorId(name), ts);
58 slice.startThread = kthread.thread;
60 if (!kthread.openAsyncSlices) {
61 kthread.openAsyncSlices = { };
63 kthread.openAsyncSlices[key] = slice;
66 closeAsyncSlice: function(ts, category, threadName, pid, key, args) {
67 var kthread = this.importer.getOrCreateKernelThread(
68 category + ':' + threadName, pid);
69 if (kthread.openAsyncSlices) {
70 var slice = kthread.openAsyncSlices[key];
72 slice.duration = ts - slice.start;
74 slice.endThread = kthread.thread;
76 new tracing.trace_model.Slice(category, slice.title,
77 slice.colorId, slice.start, slice.args, slice.duration)
79 kthread.thread.asyncSliceGroup.push(slice);
80 delete kthread.openAsyncSlices[key];
86 * Parses events and sets up state in the importer.
88 f2fsWriteBeginEvent: function(eventName, cpuNumber, pid, ts, eventBase) {
89 var event = /dev = \((\d+,\d+)\), ino (\d+), pos (\d+), len (\d+), flags (\d+)/.
90 exec(eventBase.details);
93 var device = event[1];
94 var inode = parseInt(event[2]);
95 var pos = parseInt(event[3]);
96 var len = parseInt(event[4]);
97 var key = device + '-' + inode + '-' + pos + '-' + len;
98 this.openAsyncSlice(ts, "f2fs", eventBase.threadName, eventBase.pid,
103 f2fsWriteEndEvent: function(eventName, cpuNumber, pid, ts, eventBase) {
104 var event = /dev = \((\d+,\d+)\), ino (\d+), pos (\d+), len (\d+), copied (\d+)/.
105 exec(eventBase.details);
109 var device = event[1];
110 var inode = parseInt(event[2]);
111 var pos = parseInt(event[3]);
112 var len = parseInt(event[4]);
113 var error = parseInt(event[5]) !== len;
114 var key = device + '-' + inode + '-' + pos + '-' + len;
115 this.closeAsyncSlice(ts, 'f2fs', eventBase.threadName, eventBase.pid,
124 ext4WriteBeginEvent: function(eventName, cpuNumber, pid, ts, eventBase) {
125 var event = /dev (\d+,\d+) ino (\d+) pos (\d+) len (\d+) flags (\d+)/.
126 exec(eventBase.details);
129 var device = event[1];
130 var inode = parseInt(event[2]);
131 var pos = parseInt(event[3]);
132 var len = parseInt(event[4]);
133 var key = device + '-' + inode + '-' + pos + '-' + len;
134 this.openAsyncSlice(ts, "ext4", eventBase.threadName, eventBase.pid,
139 ext4WriteEndEvent: function(eventName, cpuNumber, pid, ts, eventBase) {
140 var event = /dev (\d+,\d+) ino (\d+) pos (\d+) len (\d+) copied (\d+)/.
141 exec(eventBase.details);
145 var device = event[1];
146 var inode = parseInt(event[2]);
147 var pos = parseInt(event[3]);
148 var len = parseInt(event[4]);
149 var error = parseInt(event[5]) !== len;
150 var key = device + '-' + inode + '-' + pos + '-' + len;
151 this.closeAsyncSlice(ts, 'ext4', eventBase.threadName, eventBase.pid,
160 f2fsSyncFileEnterEvent: function(eventName, cpuNumber, pid, ts, eventBase) {
161 var event = new RegExp(
162 'dev = \\((\\d+,\\d+)\\), ino = (\\d+), pino = (\\d+), i_mode = (\\S+), ' +
163 'i_size = (\\d+), i_nlink = (\\d+), i_blocks = (\\d+), i_advise = (\\d+)').
164 exec(eventBase.details);
168 var device = event[1];
169 var inode = parseInt(event[2]);
170 var key = device + '-' + inode;
171 this.openAsyncSlice(ts, 'f2fs', eventBase.threadName, eventBase.pid,
176 f2fsSyncFileExitEvent: function(eventName, cpuNumber, pid, ts, eventBase) {
177 var event = new RegExp('dev = \\((\\d+,\\d+)\\), ino = (\\d+), checkpoint is (\\S+), ' +
178 'datasync = (\\d+), ret = (\\d+)').
179 exec(eventBase.details.replace("not needed", "not_needed"));
183 var device = event[1];
184 var inode = parseInt(event[2]);
185 var error = parseInt(event[5]);
186 var key = device + '-' + inode;
187 this.closeAsyncSlice(ts, 'f2fs', eventBase.threadName, eventBase.pid,
196 ext4SyncFileEnterEvent: function(eventName, cpuNumber, pid, ts, eventBase) {
197 var event = /dev (\d+,\d+) ino (\d+) parent (\d+) datasync (\d+)/.
198 exec(eventBase.details);
202 var device = event[1];
203 var inode = parseInt(event[2]);
204 var datasync = event[4] == 1;
205 var key = device + '-' + inode;
206 var action = datasync ? 'fdatasync' : 'fsync';
207 this.openAsyncSlice(ts, 'ext4', eventBase.threadName, eventBase.pid,
212 ext4SyncFileExitEvent: function(eventName, cpuNumber, pid, ts, eventBase) {
213 var event = /dev (\d+,\d+) ino (\d+) ret (\d+)/.exec(eventBase.details);
217 var device = event[1];
218 var inode = parseInt(event[2]);
219 var error = parseInt(event[3]);
220 var key = device + '-' + inode;
221 this.closeAsyncSlice(ts, 'ext4', eventBase.threadName, eventBase.pid,
230 blockRqIssueEvent: function(eventName, cpuNumber, pid, ts, eventBase) {
231 var event = new RegExp('(\\d+,\\d+) (F)?([DWRN])(F)?(A)?(S)?(M)? ' +
232 '\\d+ \\(.*\\) (\\d+) \\+ (\\d+) \\[.*\\]').exec(eventBase.details);
258 if (event[4] == 'F') {
261 if (event[5] == 'A') {
264 if (event[6] == 'S') {
267 if (event[7] == 'M') {
270 var device = event[1];
271 var sector = parseInt(event[8]);
272 var numSectors = parseInt(event[9]);
273 var key = device + '-' + sector + '-' + numSectors;
274 this.openAsyncSlice(ts, 'block', eventBase.threadName, eventBase.pid,
279 blockRqCompleteEvent: function(eventName, cpuNumber, pid, ts, eventBase) {
280 var event = new RegExp('(\\d+,\\d+) (F)?([DWRN])(F)?(A)?(S)?(M)? ' +
281 '\\(.*\\) (\\d+) \\+ (\\d+) \\[(.*)\\]').exec(eventBase.details);
285 var device = event[1];
286 var sector = parseInt(event[8]);
287 var numSectors = parseInt(event[9]);
288 var error = parseInt(event[10]);
289 var key = device + '-' + sector + '-' + numSectors;
290 this.closeAsyncSlice(ts, 'block', eventBase.threadName, eventBase.pid,
294 numSectors: numSectors,
301 Parser.registerSubtype(DiskParser);
304 DiskParser: DiskParser