1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
8 * @fileoverview Parses filesystem and block device events in the Linux event
11 tvcm.require('tracing.importer.linux_perf.parser');
12 tvcm.exportTo('tracing.importer.linux_perf', function() {
14 var Parser = tracing.importer.linux_perf.Parser;
17 * Parses linux filesystem and block device trace events.
20 function DiskParser(importer) {
21 Parser.call(this, importer);
23 importer.registerEventHandler('ext4_sync_file_enter',
24 DiskParser.prototype.ext4SyncFileEnterEvent.bind(this));
25 importer.registerEventHandler('ext4_sync_file_exit',
26 DiskParser.prototype.ext4SyncFileExitEvent.bind(this));
27 importer.registerEventHandler('block_rq_issue',
28 DiskParser.prototype.blockRqIssueEvent.bind(this));
29 importer.registerEventHandler('block_rq_complete',
30 DiskParser.prototype.blockRqCompleteEvent.bind(this));
33 DiskParser.prototype = {
34 __proto__: Parser.prototype,
36 openAsyncSlice: function(ts, category, threadName, pid, key, name) {
37 var kthread = this.importer.getOrCreateKernelThread(
38 category + ':' + threadName, pid);
39 var slice = new tracing.trace_model.AsyncSlice(
40 category, name, tracing.getStringColorId(name), ts);
41 slice.startThread = kthread.thread;
43 if (!kthread.openAsyncSlices) {
44 kthread.openAsyncSlices = { };
46 kthread.openAsyncSlices[key] = slice;
49 closeAsyncSlice: function(ts, category, threadName, pid, key, args) {
50 var kthread = this.importer.getOrCreateKernelThread(
51 category + ':' + threadName, pid);
52 if (kthread.openAsyncSlices) {
53 var slice = kthread.openAsyncSlices[key];
55 slice.duration = ts - slice.start;
57 slice.endThread = kthread.thread;
59 new tracing.trace_model.Slice(category, slice.title,
60 slice.colorId, slice.start, slice.args, slice.duration)
62 kthread.thread.asyncSliceGroup.push(slice);
63 delete kthread.openAsyncSlices[key];
69 * Parses events and sets up state in the importer.
71 ext4SyncFileEnterEvent: function(eventName, cpuNumber, pid, ts, eventBase) {
72 var event = /dev (\d+,\d+) ino (\d+) parent (\d+) datasync (\d+)/.
73 exec(eventBase.details);
77 var device = event[1];
78 var inode = parseInt(event[2]);
79 var datasync = event[4] == 1;
80 var key = device + '-' + inode;
81 var action = datasync ? 'fdatasync' : 'fsync';
82 this.openAsyncSlice(ts, 'ext4', eventBase.threadName, eventBase.pid,
87 ext4SyncFileExitEvent: function(eventName, cpuNumber, pid, ts, eventBase) {
88 var event = /dev (\d+,\d+) ino (\d+) ret (\d+)/.exec(eventBase.details);
92 var device = event[1];
93 var inode = parseInt(event[2]);
94 var error = parseInt(event[3]);
95 var key = device + '-' + inode;
96 this.closeAsyncSlice(ts, 'ext4', eventBase.threadName, eventBase.pid,
105 blockRqIssueEvent: function(eventName, cpuNumber, pid, ts, eventBase) {
106 var event = new RegExp('(\\d+,\\d+) (F)?([DWRN])(F)?(A)?(S)?(M)? ' +
107 '\\d+ \\(.*\\) (\\d+) \\+ (\\d+) \\[.*\\]').exec(eventBase.details);
133 if (event[4] == 'F') {
136 if (event[5] == 'A') {
139 if (event[6] == 'S') {
142 if (event[7] == 'M') {
145 var device = event[1];
146 var sector = parseInt(event[8]);
147 var numSectors = parseInt(event[9]);
148 var key = device + '-' + sector + '-' + numSectors;
149 this.openAsyncSlice(ts, 'block', eventBase.threadName, eventBase.pid,
154 blockRqCompleteEvent: function(eventName, cpuNumber, pid, ts, eventBase) {
155 var event = new RegExp('(\\d+,\\d+) (F)?([DWRN])(F)?(A)?(S)?(M)? ' +
156 '\\(.*\\) (\\d+) \\+ (\\d+) \\[(.*)\\]').exec(eventBase.details);
160 var device = event[1];
161 var sector = parseInt(event[8]);
162 var numSectors = parseInt(event[9]);
163 var error = parseInt(event[10]);
164 var key = device + '-' + sector + '-' + numSectors;
165 this.closeAsyncSlice(ts, 'block', eventBase.threadName, eventBase.pid,
169 numSectors: numSectors,
176 Parser.registerSubtype(DiskParser);
179 DiskParser: DiskParser