disk_parser.js revision 4849cead45edf85cf2a61526c0b716eb637f74ba
14849cead45edf85cf2a61526c0b716eb637f74baJeff Brown// Copyright (c) 2013 The Chromium Authors. All rights reserved.
24849cead45edf85cf2a61526c0b716eb637f74baJeff Brown// Use of this source code is governed by a BSD-style license that can be
34849cead45edf85cf2a61526c0b716eb637f74baJeff Brown// found in the LICENSE file.
44849cead45edf85cf2a61526c0b716eb637f74baJeff Brown
54849cead45edf85cf2a61526c0b716eb637f74baJeff Brown/**
64849cead45edf85cf2a61526c0b716eb637f74baJeff Brown * @fileoverview Parses filesystem and block device events in the Linux event
74849cead45edf85cf2a61526c0b716eb637f74baJeff Brown * trace format.
84849cead45edf85cf2a61526c0b716eb637f74baJeff Brown */
94849cead45edf85cf2a61526c0b716eb637f74baJeff Brownbase.require('importer.linux_perf.parser');
104849cead45edf85cf2a61526c0b716eb637f74baJeff Brownbase.exportTo('tracing.importer.linux_perf', function() {
114849cead45edf85cf2a61526c0b716eb637f74baJeff Brown
124849cead45edf85cf2a61526c0b716eb637f74baJeff Brown  var Parser = tracing.importer.linux_perf.Parser;
134849cead45edf85cf2a61526c0b716eb637f74baJeff Brown
144849cead45edf85cf2a61526c0b716eb637f74baJeff Brown  /**
154849cead45edf85cf2a61526c0b716eb637f74baJeff Brown   * Parses linux filesystem and block device trace events.
164849cead45edf85cf2a61526c0b716eb637f74baJeff Brown   * @constructor
174849cead45edf85cf2a61526c0b716eb637f74baJeff Brown   */
184849cead45edf85cf2a61526c0b716eb637f74baJeff Brown  function DiskParser(importer) {
194849cead45edf85cf2a61526c0b716eb637f74baJeff Brown    Parser.call(this, importer);
204849cead45edf85cf2a61526c0b716eb637f74baJeff Brown
214849cead45edf85cf2a61526c0b716eb637f74baJeff Brown    importer.registerEventHandler('ext4_sync_file_enter',
224849cead45edf85cf2a61526c0b716eb637f74baJeff Brown        DiskParser.prototype.ext4SyncFileEnterEvent.bind(this));
234849cead45edf85cf2a61526c0b716eb637f74baJeff Brown    importer.registerEventHandler('ext4_sync_file_exit',
244849cead45edf85cf2a61526c0b716eb637f74baJeff Brown        DiskParser.prototype.ext4SyncFileExitEvent.bind(this));
254849cead45edf85cf2a61526c0b716eb637f74baJeff Brown    importer.registerEventHandler('block_rq_issue',
264849cead45edf85cf2a61526c0b716eb637f74baJeff Brown        DiskParser.prototype.blockRqIssueEvent.bind(this));
274849cead45edf85cf2a61526c0b716eb637f74baJeff Brown    importer.registerEventHandler('block_rq_complete',
284849cead45edf85cf2a61526c0b716eb637f74baJeff Brown        DiskParser.prototype.blockRqCompleteEvent.bind(this));
294849cead45edf85cf2a61526c0b716eb637f74baJeff Brown  }
304849cead45edf85cf2a61526c0b716eb637f74baJeff Brown
314849cead45edf85cf2a61526c0b716eb637f74baJeff Brown  DiskParser.prototype = {
324849cead45edf85cf2a61526c0b716eb637f74baJeff Brown    __proto__: Parser.prototype,
334849cead45edf85cf2a61526c0b716eb637f74baJeff Brown
344849cead45edf85cf2a61526c0b716eb637f74baJeff Brown    openAsyncSlice: function(ts, category, threadName, pid, key, name) {
354849cead45edf85cf2a61526c0b716eb637f74baJeff Brown      var kthread = this.importer.getOrCreateKernelThread(
364849cead45edf85cf2a61526c0b716eb637f74baJeff Brown          category + ':' + threadName, pid);
374849cead45edf85cf2a61526c0b716eb637f74baJeff Brown      var slice = new tracing.AsyncSlice(
384849cead45edf85cf2a61526c0b716eb637f74baJeff Brown          category, name, tracing.getStringColorId(name), ts);
394849cead45edf85cf2a61526c0b716eb637f74baJeff Brown      slice.startThread = kthread.thread;
404849cead45edf85cf2a61526c0b716eb637f74baJeff Brown
414849cead45edf85cf2a61526c0b716eb637f74baJeff Brown      if (!kthread.openAsyncSlices) {
424849cead45edf85cf2a61526c0b716eb637f74baJeff Brown        kthread.openAsyncSlices = { };
434849cead45edf85cf2a61526c0b716eb637f74baJeff Brown      }
444849cead45edf85cf2a61526c0b716eb637f74baJeff Brown      kthread.openAsyncSlices[key] = slice;
454849cead45edf85cf2a61526c0b716eb637f74baJeff Brown    },
464849cead45edf85cf2a61526c0b716eb637f74baJeff Brown
474849cead45edf85cf2a61526c0b716eb637f74baJeff Brown    closeAsyncSlice: function(ts, category, threadName, pid, key, args) {
484849cead45edf85cf2a61526c0b716eb637f74baJeff Brown      var kthread = this.importer.getOrCreateKernelThread(
494849cead45edf85cf2a61526c0b716eb637f74baJeff Brown          category + ':' + threadName, pid);
504849cead45edf85cf2a61526c0b716eb637f74baJeff Brown      if (kthread.openAsyncSlices) {
514849cead45edf85cf2a61526c0b716eb637f74baJeff Brown        var slice = kthread.openAsyncSlices[key];
524849cead45edf85cf2a61526c0b716eb637f74baJeff Brown        if (slice) {
534849cead45edf85cf2a61526c0b716eb637f74baJeff Brown          slice.duration = ts - slice.start;
544849cead45edf85cf2a61526c0b716eb637f74baJeff Brown          slice.args = args;
554849cead45edf85cf2a61526c0b716eb637f74baJeff Brown          slice.endThread = kthread.thread;
564849cead45edf85cf2a61526c0b716eb637f74baJeff Brown          slice.subSlices = [new tracing.Slice(category, slice.title,
574849cead45edf85cf2a61526c0b716eb637f74baJeff Brown              slice.colorId, slice.start, slice.args, slice.duration)];
584849cead45edf85cf2a61526c0b716eb637f74baJeff Brown          kthread.thread.asyncSlices.push(slice);
594849cead45edf85cf2a61526c0b716eb637f74baJeff Brown          delete kthread.openAsyncSlices[key];
604849cead45edf85cf2a61526c0b716eb637f74baJeff Brown        }
614849cead45edf85cf2a61526c0b716eb637f74baJeff Brown      }
624849cead45edf85cf2a61526c0b716eb637f74baJeff Brown    },
634849cead45edf85cf2a61526c0b716eb637f74baJeff Brown
644849cead45edf85cf2a61526c0b716eb637f74baJeff Brown    /**
654849cead45edf85cf2a61526c0b716eb637f74baJeff Brown     * Parses events and sets up state in the importer.
664849cead45edf85cf2a61526c0b716eb637f74baJeff Brown     */
674849cead45edf85cf2a61526c0b716eb637f74baJeff Brown    ext4SyncFileEnterEvent: function(eventName, cpuNumber, pid, ts, eventBase) {
684849cead45edf85cf2a61526c0b716eb637f74baJeff Brown      var event = /dev (\d+,\d+) ino (\d+) parent (\d+) datasync (\d+)/.
694849cead45edf85cf2a61526c0b716eb637f74baJeff Brown          exec(eventBase.details);
704849cead45edf85cf2a61526c0b716eb637f74baJeff Brown      if (!event)
714849cead45edf85cf2a61526c0b716eb637f74baJeff Brown        return false;
724849cead45edf85cf2a61526c0b716eb637f74baJeff Brown
734849cead45edf85cf2a61526c0b716eb637f74baJeff Brown      var device = event[1];
744849cead45edf85cf2a61526c0b716eb637f74baJeff Brown      var inode = parseInt(event[2]);
754849cead45edf85cf2a61526c0b716eb637f74baJeff Brown      var datasync = event[4] == 1;
764849cead45edf85cf2a61526c0b716eb637f74baJeff Brown      var key = device + '-' + inode;
774849cead45edf85cf2a61526c0b716eb637f74baJeff Brown      var action = datasync ? 'fdatasync' : 'fsync';
784849cead45edf85cf2a61526c0b716eb637f74baJeff Brown      this.openAsyncSlice(ts, 'ext4', eventBase.threadName, eventBase.pid,
794849cead45edf85cf2a61526c0b716eb637f74baJeff Brown          key, action);
804849cead45edf85cf2a61526c0b716eb637f74baJeff Brown      return true;
814849cead45edf85cf2a61526c0b716eb637f74baJeff Brown    },
824849cead45edf85cf2a61526c0b716eb637f74baJeff Brown
834849cead45edf85cf2a61526c0b716eb637f74baJeff Brown    ext4SyncFileExitEvent: function(eventName, cpuNumber, pid, ts, eventBase) {
844849cead45edf85cf2a61526c0b716eb637f74baJeff Brown      var event = /dev (\d+,\d+) ino (\d+) ret (\d+)/.exec(eventBase.details);
854849cead45edf85cf2a61526c0b716eb637f74baJeff Brown      if (!event)
864849cead45edf85cf2a61526c0b716eb637f74baJeff Brown        return false;
874849cead45edf85cf2a61526c0b716eb637f74baJeff Brown
884849cead45edf85cf2a61526c0b716eb637f74baJeff Brown      var device = event[1];
894849cead45edf85cf2a61526c0b716eb637f74baJeff Brown      var inode = parseInt(event[2]);
904849cead45edf85cf2a61526c0b716eb637f74baJeff Brown      var error = parseInt(event[3]);
914849cead45edf85cf2a61526c0b716eb637f74baJeff Brown      var key = device + '-' + inode;
924849cead45edf85cf2a61526c0b716eb637f74baJeff Brown      this.closeAsyncSlice(ts, 'ext4', eventBase.threadName, eventBase.pid,
934849cead45edf85cf2a61526c0b716eb637f74baJeff Brown          key, {
944849cead45edf85cf2a61526c0b716eb637f74baJeff Brown          device: device,
954849cead45edf85cf2a61526c0b716eb637f74baJeff Brown          inode: inode,
964849cead45edf85cf2a61526c0b716eb637f74baJeff Brown          error: error
974849cead45edf85cf2a61526c0b716eb637f74baJeff Brown      });
984849cead45edf85cf2a61526c0b716eb637f74baJeff Brown      return true;
994849cead45edf85cf2a61526c0b716eb637f74baJeff Brown    },
1004849cead45edf85cf2a61526c0b716eb637f74baJeff Brown
1014849cead45edf85cf2a61526c0b716eb637f74baJeff Brown    blockRqIssueEvent: function(eventName, cpuNumber, pid, ts, eventBase) {
1024849cead45edf85cf2a61526c0b716eb637f74baJeff Brown      var event = new RegExp('(\\d+,\\d+) (F)?([DWRN])(F)?(A)?(S)?(M)? ' +
1034849cead45edf85cf2a61526c0b716eb637f74baJeff Brown          '\\d+ \\(.*\\) (\\d+) \\+ (\\d+) \\[.*\\]').exec(eventBase.details);
1044849cead45edf85cf2a61526c0b716eb637f74baJeff Brown      if (!event)
1054849cead45edf85cf2a61526c0b716eb637f74baJeff Brown        return false;
1064849cead45edf85cf2a61526c0b716eb637f74baJeff Brown
1074849cead45edf85cf2a61526c0b716eb637f74baJeff Brown      var action;
1084849cead45edf85cf2a61526c0b716eb637f74baJeff Brown      switch (event[3]) {
1094849cead45edf85cf2a61526c0b716eb637f74baJeff Brown        case 'D':
1104849cead45edf85cf2a61526c0b716eb637f74baJeff Brown          action = 'discard';
1114849cead45edf85cf2a61526c0b716eb637f74baJeff Brown          break;
1124849cead45edf85cf2a61526c0b716eb637f74baJeff Brown        case 'W':
1134849cead45edf85cf2a61526c0b716eb637f74baJeff Brown          action = 'write';
1144849cead45edf85cf2a61526c0b716eb637f74baJeff Brown          break;
1154849cead45edf85cf2a61526c0b716eb637f74baJeff Brown        case 'R':
1164849cead45edf85cf2a61526c0b716eb637f74baJeff Brown          action = 'read';
1174849cead45edf85cf2a61526c0b716eb637f74baJeff Brown          break;
1184849cead45edf85cf2a61526c0b716eb637f74baJeff Brown        case 'N':
1194849cead45edf85cf2a61526c0b716eb637f74baJeff Brown          action = 'none';
1204849cead45edf85cf2a61526c0b716eb637f74baJeff Brown          break;
1214849cead45edf85cf2a61526c0b716eb637f74baJeff Brown        default:
1224849cead45edf85cf2a61526c0b716eb637f74baJeff Brown          action = 'unknown';
1234849cead45edf85cf2a61526c0b716eb637f74baJeff Brown          break;
1244849cead45edf85cf2a61526c0b716eb637f74baJeff Brown      }
1254849cead45edf85cf2a61526c0b716eb637f74baJeff Brown
1264849cead45edf85cf2a61526c0b716eb637f74baJeff Brown      if (event[2]) {
1274849cead45edf85cf2a61526c0b716eb637f74baJeff Brown        action += ' flush';
1284849cead45edf85cf2a61526c0b716eb637f74baJeff Brown      }
1294849cead45edf85cf2a61526c0b716eb637f74baJeff Brown      if (event[4] == 'F') {
1304849cead45edf85cf2a61526c0b716eb637f74baJeff Brown        action += ' fua';
1314849cead45edf85cf2a61526c0b716eb637f74baJeff Brown      }
1324849cead45edf85cf2a61526c0b716eb637f74baJeff Brown      if (event[5] == 'A') {
1334849cead45edf85cf2a61526c0b716eb637f74baJeff Brown        action += ' ahead';
1344849cead45edf85cf2a61526c0b716eb637f74baJeff Brown      }
1354849cead45edf85cf2a61526c0b716eb637f74baJeff Brown      if (event[6] == 'S') {
1364849cead45edf85cf2a61526c0b716eb637f74baJeff Brown        action += ' sync';
1374849cead45edf85cf2a61526c0b716eb637f74baJeff Brown      }
1384849cead45edf85cf2a61526c0b716eb637f74baJeff Brown      if (event[7] == 'M') {
1394849cead45edf85cf2a61526c0b716eb637f74baJeff Brown        action += ' meta';
1404849cead45edf85cf2a61526c0b716eb637f74baJeff Brown      }
1414849cead45edf85cf2a61526c0b716eb637f74baJeff Brown      var device = event[1];
1424849cead45edf85cf2a61526c0b716eb637f74baJeff Brown      var sector = parseInt(event[8]);
1434849cead45edf85cf2a61526c0b716eb637f74baJeff Brown      var numSectors = parseInt(event[9]);
1444849cead45edf85cf2a61526c0b716eb637f74baJeff Brown      var key = device + '-' + sector + '-' + numSectors;
1454849cead45edf85cf2a61526c0b716eb637f74baJeff Brown      this.openAsyncSlice(ts, 'block', eventBase.threadName, eventBase.pid,
1464849cead45edf85cf2a61526c0b716eb637f74baJeff Brown          key, action);
1474849cead45edf85cf2a61526c0b716eb637f74baJeff Brown      return true;
1484849cead45edf85cf2a61526c0b716eb637f74baJeff Brown    },
1494849cead45edf85cf2a61526c0b716eb637f74baJeff Brown
1504849cead45edf85cf2a61526c0b716eb637f74baJeff Brown    blockRqCompleteEvent: function(eventName, cpuNumber, pid, ts, eventBase) {
1514849cead45edf85cf2a61526c0b716eb637f74baJeff Brown      var event = new RegExp('(\\d+,\\d+) (F)?([DWRN])(F)?(A)?(S)?(M)? ' +
1524849cead45edf85cf2a61526c0b716eb637f74baJeff Brown          '\\(.*\\) (\\d+) \\+ (\\d+) \\[(.*)\\]').exec(eventBase.details);
1534849cead45edf85cf2a61526c0b716eb637f74baJeff Brown      if (!event)
1544849cead45edf85cf2a61526c0b716eb637f74baJeff Brown        return false;
1554849cead45edf85cf2a61526c0b716eb637f74baJeff Brown
1564849cead45edf85cf2a61526c0b716eb637f74baJeff Brown      var device = event[1];
1574849cead45edf85cf2a61526c0b716eb637f74baJeff Brown      var sector = parseInt(event[8]);
1584849cead45edf85cf2a61526c0b716eb637f74baJeff Brown      var numSectors = parseInt(event[9]);
1594849cead45edf85cf2a61526c0b716eb637f74baJeff Brown      var error = parseInt(event[10]);
1604849cead45edf85cf2a61526c0b716eb637f74baJeff Brown      var key = device + '-' + sector + '-' + numSectors;
1614849cead45edf85cf2a61526c0b716eb637f74baJeff Brown      this.closeAsyncSlice(ts, 'block', eventBase.threadName, eventBase.pid,
1624849cead45edf85cf2a61526c0b716eb637f74baJeff Brown          key, {
1634849cead45edf85cf2a61526c0b716eb637f74baJeff Brown          device: device,
1644849cead45edf85cf2a61526c0b716eb637f74baJeff Brown          sector: sector,
1654849cead45edf85cf2a61526c0b716eb637f74baJeff Brown          numSectors: numSectors,
1664849cead45edf85cf2a61526c0b716eb637f74baJeff Brown          error: error
1674849cead45edf85cf2a61526c0b716eb637f74baJeff Brown      });
1684849cead45edf85cf2a61526c0b716eb637f74baJeff Brown      return true;
1694849cead45edf85cf2a61526c0b716eb637f74baJeff Brown    },
1704849cead45edf85cf2a61526c0b716eb637f74baJeff Brown  };
1714849cead45edf85cf2a61526c0b716eb637f74baJeff Brown
1724849cead45edf85cf2a61526c0b716eb637f74baJeff Brown  Parser.registerSubtype(DiskParser);
1734849cead45edf85cf2a61526c0b716eb637f74baJeff Brown
1744849cead45edf85cf2a61526c0b716eb637f74baJeff Brown  return {
1754849cead45edf85cf2a61526c0b716eb637f74baJeff Brown    DiskParser: DiskParser
1764849cead45edf85cf2a61526c0b716eb637f74baJeff Brown  };
1774849cead45edf85cf2a61526c0b716eb637f74baJeff Brown});
178