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 tv.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 asyncSliceConstructor =
57 tracing.trace_model.AsyncSlice.getConstructor(
59 var slice = new asyncSliceConstructor(
60 category, name, tv.ui.getStringColorId(name), ts);
61 slice.startThread = kthread.thread;
63 if (!kthread.openAsyncSlices) {
64 kthread.openAsyncSlices = { };
66 kthread.openAsyncSlices[key] = slice;
69 closeAsyncSlice: function(ts, category, threadName, pid, key, args) {
70 var kthread = this.importer.getOrCreateKernelThread(
71 category + ':' + threadName, pid);
72 if (kthread.openAsyncSlices) {
73 var slice = kthread.openAsyncSlices[key];
75 slice.duration = ts - slice.start;
77 slice.endThread = kthread.thread;
79 new tracing.trace_model.Slice(category, slice.title,
80 slice.colorId, slice.start, slice.args, slice.duration)
82 kthread.thread.asyncSliceGroup.push(slice);
83 delete kthread.openAsyncSlices[key];
89 * Parses events and sets up state in the importer.
91 f2fsWriteBeginEvent: function(eventName, cpuNumber, pid, ts, eventBase) {
92 var event = /dev = \((\d+,\d+)\), ino (\d+), pos (\d+), len (\d+), flags (\d+)/.
93 exec(eventBase.details);
96 var device = event[1];
97 var inode = parseInt(event[2]);
98 var pos = parseInt(event[3]);
99 var len = parseInt(event[4]);
100 var key = device + '-' + inode + '-' + pos + '-' + len;
101 this.openAsyncSlice(ts, "f2fs", eventBase.threadName, eventBase.pid,
106 f2fsWriteEndEvent: function(eventName, cpuNumber, pid, ts, eventBase) {
107 var event = /dev = \((\d+,\d+)\), ino (\d+), pos (\d+), len (\d+), copied (\d+)/.
108 exec(eventBase.details);
112 var device = event[1];
113 var inode = parseInt(event[2]);
114 var pos = parseInt(event[3]);
115 var len = parseInt(event[4]);
116 var error = parseInt(event[5]) !== len;
117 var key = device + '-' + inode + '-' + pos + '-' + len;
118 this.closeAsyncSlice(ts, 'f2fs', eventBase.threadName, eventBase.pid,
127 ext4WriteBeginEvent: function(eventName, cpuNumber, pid, ts, eventBase) {
128 var event = /dev (\d+,\d+) ino (\d+) pos (\d+) len (\d+) flags (\d+)/.
129 exec(eventBase.details);
132 var device = event[1];
133 var inode = parseInt(event[2]);
134 var pos = parseInt(event[3]);
135 var len = parseInt(event[4]);
136 var key = device + '-' + inode + '-' + pos + '-' + len;
137 this.openAsyncSlice(ts, "ext4", eventBase.threadName, eventBase.pid,
142 ext4WriteEndEvent: function(eventName, cpuNumber, pid, ts, eventBase) {
143 var event = /dev (\d+,\d+) ino (\d+) pos (\d+) len (\d+) copied (\d+)/.
144 exec(eventBase.details);
148 var device = event[1];
149 var inode = parseInt(event[2]);
150 var pos = parseInt(event[3]);
151 var len = parseInt(event[4]);
152 var error = parseInt(event[5]) !== len;
153 var key = device + '-' + inode + '-' + pos + '-' + len;
154 this.closeAsyncSlice(ts, 'ext4', eventBase.threadName, eventBase.pid,
163 f2fsSyncFileEnterEvent: function(eventName, cpuNumber, pid, ts, eventBase) {
164 var event = new RegExp(
165 'dev = \\((\\d+,\\d+)\\), ino = (\\d+), pino = (\\d+), i_mode = (\\S+), ' +
166 'i_size = (\\d+), i_nlink = (\\d+), i_blocks = (\\d+), i_advise = (\\d+)').
167 exec(eventBase.details);
171 var device = event[1];
172 var inode = parseInt(event[2]);
173 var key = device + '-' + inode;
174 this.openAsyncSlice(ts, 'f2fs', eventBase.threadName, eventBase.pid,
179 f2fsSyncFileExitEvent: function(eventName, cpuNumber, pid, ts, eventBase) {
180 var event = new RegExp('dev = \\((\\d+,\\d+)\\), ino = (\\d+), checkpoint is (\\S+), ' +
181 'datasync = (\\d+), ret = (\\d+)').
182 exec(eventBase.details.replace("not needed", "not_needed"));
186 var device = event[1];
187 var inode = parseInt(event[2]);
188 var error = parseInt(event[5]);
189 var key = device + '-' + inode;
190 this.closeAsyncSlice(ts, 'f2fs', eventBase.threadName, eventBase.pid,
199 ext4SyncFileEnterEvent: function(eventName, cpuNumber, pid, ts, eventBase) {
200 var event = /dev (\d+,\d+) ino (\d+) parent (\d+) datasync (\d+)/.
201 exec(eventBase.details);
205 var device = event[1];
206 var inode = parseInt(event[2]);
207 var datasync = event[4] == 1;
208 var key = device + '-' + inode;
209 var action = datasync ? 'fdatasync' : 'fsync';
210 this.openAsyncSlice(ts, 'ext4', eventBase.threadName, eventBase.pid,
215 ext4SyncFileExitEvent: function(eventName, cpuNumber, pid, ts, eventBase) {
216 var event = /dev (\d+,\d+) ino (\d+) ret (\d+)/.exec(eventBase.details);
220 var device = event[1];
221 var inode = parseInt(event[2]);
222 var error = parseInt(event[3]);
223 var key = device + '-' + inode;
224 this.closeAsyncSlice(ts, 'ext4', eventBase.threadName, eventBase.pid,
233 blockRqIssueEvent: function(eventName, cpuNumber, pid, ts, eventBase) {
234 var event = new RegExp('(\\d+,\\d+) (F)?([DWRN])(F)?(A)?(S)?(M)? ' +
235 '\\d+ \\(.*\\) (\\d+) \\+ (\\d+) \\[.*\\]').exec(eventBase.details);
261 if (event[4] == 'F') {
264 if (event[5] == 'A') {
267 if (event[6] == 'S') {
270 if (event[7] == 'M') {
273 var device = event[1];
274 var sector = parseInt(event[8]);
275 var numSectors = parseInt(event[9]);
276 var key = device + '-' + sector + '-' + numSectors;
277 this.openAsyncSlice(ts, 'block', eventBase.threadName, eventBase.pid,
282 blockRqCompleteEvent: function(eventName, cpuNumber, pid, ts, eventBase) {
283 var event = new RegExp('(\\d+,\\d+) (F)?([DWRN])(F)?(A)?(S)?(M)? ' +
284 '\\(.*\\) (\\d+) \\+ (\\d+) \\[(.*)\\]').exec(eventBase.details);
288 var device = event[1];
289 var sector = parseInt(event[8]);
290 var numSectors = parseInt(event[9]);
291 var error = parseInt(event[10]);
292 var key = device + '-' + sector + '-' + numSectors;
293 this.closeAsyncSlice(ts, 'block', eventBase.threadName, eventBase.pid,
297 numSectors: numSectors,
304 Parser.registerSubtype(DiskParser);
307 DiskParser: DiskParser