trace_processor: support f2fs_iostat_latency ftrace event

Show periodic f2fs related I/O latency info to better understand system
I/O behaviors.

Bug: 233936593
Change-Id: Ia0afc92fc5637cac6b2422c563313e2baa0adefb
diff --git a/protos/perfetto/trace/ftrace/f2fs.proto b/protos/perfetto/trace/ftrace/f2fs.proto
index efb241e..0e59384 100644
--- a/protos/perfetto/trace/ftrace/f2fs.proto
+++ b/protos/perfetto/trace/ftrace/f2fs.proto
@@ -258,3 +258,33 @@
   optional uint64 fs_nio = 22;
   optional uint64 fs_nrio = 23;
 }
+message F2fsIostatLatencyFtraceEvent {
+  optional uint32 d_rd_avg = 1;
+  optional uint32 d_rd_cnt = 2;
+  optional uint32 d_rd_peak = 3;
+  optional uint32 d_wr_as_avg = 4;
+  optional uint32 d_wr_as_cnt = 5;
+  optional uint32 d_wr_as_peak = 6;
+  optional uint32 d_wr_s_avg = 7;
+  optional uint32 d_wr_s_cnt = 8;
+  optional uint32 d_wr_s_peak = 9;
+  optional uint64 dev = 10;
+  optional uint32 m_rd_avg = 11;
+  optional uint32 m_rd_cnt = 12;
+  optional uint32 m_rd_peak = 13;
+  optional uint32 m_wr_as_avg = 14;
+  optional uint32 m_wr_as_cnt = 15;
+  optional uint32 m_wr_as_peak = 16;
+  optional uint32 m_wr_s_avg = 17;
+  optional uint32 m_wr_s_cnt = 18;
+  optional uint32 m_wr_s_peak = 19;
+  optional uint32 n_rd_avg = 20;
+  optional uint32 n_rd_cnt = 21;
+  optional uint32 n_rd_peak = 22;
+  optional uint32 n_wr_as_avg = 23;
+  optional uint32 n_wr_as_cnt = 24;
+  optional uint32 n_wr_as_peak = 25;
+  optional uint32 n_wr_s_avg = 26;
+  optional uint32 n_wr_s_cnt = 27;
+  optional uint32 n_wr_s_peak = 28;
+}
diff --git a/protos/perfetto/trace/ftrace/ftrace_event.proto b/protos/perfetto/trace/ftrace/ftrace_event.proto
index 0a3d90a..fffb18d 100644
--- a/protos/perfetto/trace/ftrace/ftrace_event.proto
+++ b/protos/perfetto/trace/ftrace/ftrace_event.proto
@@ -520,5 +520,6 @@
     DmaFenceWaitStartFtraceEvent dma_fence_wait_start = 417;
     DmaFenceWaitEndFtraceEvent dma_fence_wait_end = 418;
     F2fsIostatFtraceEvent f2fs_iostat = 419;
+    F2fsIostatLatencyFtraceEvent f2fs_iostat_latency = 420;
   }
 }
diff --git a/protos/perfetto/trace/perfetto_trace.proto b/protos/perfetto/trace/perfetto_trace.proto
index de18393..7d60276 100644
--- a/protos/perfetto/trace/perfetto_trace.proto
+++ b/protos/perfetto/trace/perfetto_trace.proto
@@ -4776,6 +4776,36 @@
   optional uint64 fs_nio = 22;
   optional uint64 fs_nrio = 23;
 }
+message F2fsIostatLatencyFtraceEvent {
+  optional uint32 d_rd_avg = 1;
+  optional uint32 d_rd_cnt = 2;
+  optional uint32 d_rd_peak = 3;
+  optional uint32 d_wr_as_avg = 4;
+  optional uint32 d_wr_as_cnt = 5;
+  optional uint32 d_wr_as_peak = 6;
+  optional uint32 d_wr_s_avg = 7;
+  optional uint32 d_wr_s_cnt = 8;
+  optional uint32 d_wr_s_peak = 9;
+  optional uint64 dev = 10;
+  optional uint32 m_rd_avg = 11;
+  optional uint32 m_rd_cnt = 12;
+  optional uint32 m_rd_peak = 13;
+  optional uint32 m_wr_as_avg = 14;
+  optional uint32 m_wr_as_cnt = 15;
+  optional uint32 m_wr_as_peak = 16;
+  optional uint32 m_wr_s_avg = 17;
+  optional uint32 m_wr_s_cnt = 18;
+  optional uint32 m_wr_s_peak = 19;
+  optional uint32 n_rd_avg = 20;
+  optional uint32 n_rd_cnt = 21;
+  optional uint32 n_rd_peak = 22;
+  optional uint32 n_wr_as_avg = 23;
+  optional uint32 n_wr_as_cnt = 24;
+  optional uint32 n_wr_as_peak = 25;
+  optional uint32 n_wr_s_avg = 26;
+  optional uint32 n_wr_s_cnt = 27;
+  optional uint32 n_wr_s_peak = 28;
+}
 
 // End of protos/perfetto/trace/ftrace/f2fs.proto
 
@@ -6560,6 +6590,7 @@
     DmaFenceWaitStartFtraceEvent dma_fence_wait_start = 417;
     DmaFenceWaitEndFtraceEvent dma_fence_wait_end = 418;
     F2fsIostatFtraceEvent f2fs_iostat = 419;
+    F2fsIostatLatencyFtraceEvent f2fs_iostat_latency = 420;
   }
 }
 
diff --git a/src/tools/ftrace_proto_gen/event_list b/src/tools/ftrace_proto_gen/event_list
index 75e2eae..05984fd 100644
--- a/src/tools/ftrace_proto_gen/event_list
+++ b/src/tools/ftrace_proto_gen/event_list
@@ -414,3 +414,4 @@
 dma_fence/dma_fence_wait_start
 dma_fence/dma_fence_wait_end
 f2fs/f2fs_iostat
+f2fs/f2fs_iostat_latency
diff --git a/src/trace_processor/importers/ftrace/ftrace_descriptors.cc b/src/trace_processor/importers/ftrace/ftrace_descriptors.cc
index 5a44dab..74425f2 100644
--- a/src/trace_processor/importers/ftrace/ftrace_descriptors.cc
+++ b/src/trace_processor/importers/ftrace/ftrace_descriptors.cc
@@ -24,7 +24,7 @@
 namespace trace_processor {
 namespace {
 
-std::array<MessageDescriptor, 420> descriptors{{
+std::array<MessageDescriptor, 421> descriptors{{
     {nullptr, 0, {}},
     {nullptr, 0, {}},
     {nullptr, 0, {}},
@@ -4535,6 +4535,41 @@
             {"fs_nrio", ProtoSchemaType::kUint64},
         },
     },
+    {
+        "f2fs_iostat_latency",
+        28,
+        {
+            {},
+            {"d_rd_avg", ProtoSchemaType::kUint32},
+            {"d_rd_cnt", ProtoSchemaType::kUint32},
+            {"d_rd_peak", ProtoSchemaType::kUint32},
+            {"d_wr_as_avg", ProtoSchemaType::kUint32},
+            {"d_wr_as_cnt", ProtoSchemaType::kUint32},
+            {"d_wr_as_peak", ProtoSchemaType::kUint32},
+            {"d_wr_s_avg", ProtoSchemaType::kUint32},
+            {"d_wr_s_cnt", ProtoSchemaType::kUint32},
+            {"d_wr_s_peak", ProtoSchemaType::kUint32},
+            {"dev", ProtoSchemaType::kUint64},
+            {"m_rd_avg", ProtoSchemaType::kUint32},
+            {"m_rd_cnt", ProtoSchemaType::kUint32},
+            {"m_rd_peak", ProtoSchemaType::kUint32},
+            {"m_wr_as_avg", ProtoSchemaType::kUint32},
+            {"m_wr_as_cnt", ProtoSchemaType::kUint32},
+            {"m_wr_as_peak", ProtoSchemaType::kUint32},
+            {"m_wr_s_avg", ProtoSchemaType::kUint32},
+            {"m_wr_s_cnt", ProtoSchemaType::kUint32},
+            {"m_wr_s_peak", ProtoSchemaType::kUint32},
+            {"n_rd_avg", ProtoSchemaType::kUint32},
+            {"n_rd_cnt", ProtoSchemaType::kUint32},
+            {"n_rd_peak", ProtoSchemaType::kUint32},
+            {"n_wr_as_avg", ProtoSchemaType::kUint32},
+            {"n_wr_as_cnt", ProtoSchemaType::kUint32},
+            {"n_wr_as_peak", ProtoSchemaType::kUint32},
+            {"n_wr_s_avg", ProtoSchemaType::kUint32},
+            {"n_wr_s_cnt", ProtoSchemaType::kUint32},
+            {"n_wr_s_peak", ProtoSchemaType::kUint32},
+        },
+    },
 }};
 
 }  // namespace
diff --git a/src/trace_processor/importers/ftrace/ftrace_parser.cc b/src/trace_processor/importers/ftrace/ftrace_parser.cc
index 46bba22..a735be2 100644
--- a/src/trace_processor/importers/ftrace/ftrace_parser.cc
+++ b/src/trace_processor/importers/ftrace/ftrace_parser.cc
@@ -753,6 +753,10 @@
         iostat_tracker_.ParseF2fsIostat(ts, data);
         break;
       }
+      case FtraceEvent::kF2fsIostatLatencyFieldNumber: {
+        iostat_tracker_.ParseF2fsIostatLatency(ts, data);
+        break;
+      }
       default:
         break;
     }
diff --git a/src/trace_processor/importers/ftrace/iostat_tracker.cc b/src/trace_processor/importers/ftrace/iostat_tracker.cc
index 1158c99..27e5762 100644
--- a/src/trace_processor/importers/ftrace/iostat_tracker.cc
+++ b/src/trace_processor/importers/ftrace/iostat_tracker.cc
@@ -23,6 +23,7 @@
 namespace trace_processor {
 
 static constexpr char kF2fsIostatTag[] = "f2fs_iostat";
+static constexpr char kF2fsIostatLatencyTag[] = "f2fs_iostat_latency";
 
 IostatTracker::IostatTracker(TraceProcessorContext* context)
     : context_(context) {}
@@ -72,5 +73,50 @@
   push_counter("other_fs_discard", evt.fs_discard());
 }
 
+void IostatTracker::ParseF2fsIostatLatency(int64_t timestamp,
+                                           protozero::ConstBytes blob) {
+  protos::pbzero::F2fsIostatLatencyFtraceEvent::Decoder evt(blob.data,
+                                                            blob.size);
+  std::string tagPrefix =
+      std::string(kF2fsIostatLatencyTag) + "." + GetDeviceName(evt.dev());
+  auto push_counter = [this, timestamp, tagPrefix](const char* counter_name,
+                                                   uint64_t value) {
+    std::string track_name = tagPrefix + "." + std::string(counter_name);
+    StringId string_id = context_->storage->InternString(track_name.c_str());
+    TrackId track =
+        context_->track_tracker->InternGlobalCounterTrack(string_id);
+    context_->event_tracker->PushCounter(timestamp, static_cast<double>(value),
+                                         track);
+  };
+
+  push_counter("read_data_peak", evt.d_rd_peak());
+  push_counter("read_data_avg", evt.d_rd_avg());
+  push_counter("read_data_cnt", evt.d_rd_cnt());
+  push_counter("read_node_peak", evt.n_rd_peak());
+  push_counter("read_node_avg", evt.n_rd_avg());
+  push_counter("read_node_cnt", evt.n_rd_cnt());
+  push_counter("read_meta_peak", evt.m_rd_peak());
+  push_counter("read_meta_avg", evt.m_rd_avg());
+  push_counter("read_meta_cnt", evt.m_rd_cnt());
+  push_counter("write_sync_data_peak", evt.d_wr_s_peak());
+  push_counter("write_sync_data_avg", evt.d_wr_s_avg());
+  push_counter("write_sync_data_cnt", evt.d_wr_s_cnt());
+  push_counter("write_sync_node_peak", evt.n_wr_s_peak());
+  push_counter("write_sync_node_avg", evt.n_wr_s_avg());
+  push_counter("write_sync_node_cnt", evt.n_wr_s_cnt());
+  push_counter("write_sync_meta_peak", evt.m_wr_s_peak());
+  push_counter("write_sync_meta_avg", evt.m_wr_s_avg());
+  push_counter("write_sync_meta_cnt", evt.m_wr_s_cnt());
+  push_counter("write_async_data_peak", evt.d_wr_as_peak());
+  push_counter("write_async_data_avg", evt.d_wr_as_avg());
+  push_counter("write_async_data_cnt", evt.d_wr_as_cnt());
+  push_counter("write_async_node_peak", evt.n_wr_as_peak());
+  push_counter("write_async_node_avg", evt.n_wr_as_avg());
+  push_counter("write_async_node_cnt", evt.n_wr_as_cnt());
+  push_counter("write_async_meta_peak", evt.m_wr_as_peak());
+  push_counter("write_async_meta_avg", evt.m_wr_as_avg());
+  push_counter("write_async_meta_cnt", evt.m_wr_as_cnt());
+}
+
 }  // namespace trace_processor
 }  // namespace perfetto
diff --git a/src/trace_processor/importers/ftrace/iostat_tracker.h b/src/trace_processor/importers/ftrace/iostat_tracker.h
index 7c46719..f56ae9a 100644
--- a/src/trace_processor/importers/ftrace/iostat_tracker.h
+++ b/src/trace_processor/importers/ftrace/iostat_tracker.h
@@ -30,6 +30,7 @@
   explicit IostatTracker(TraceProcessorContext*);
 
   void ParseF2fsIostat(int64_t timestamp, protozero::ConstBytes blob);
+  void ParseF2fsIostatLatency(int64_t timestamp, protozero::ConstBytes blob);
 
  private:
   TraceProcessorContext* const context_;
diff --git a/src/traced/probes/ftrace/event_info.cc b/src/traced/probes/ftrace/event_info.cc
index 3819936..be42505 100644
--- a/src/traced/probes/ftrace/event_info.cc
+++ b/src/traced/probes/ftrace/event_info.cc
@@ -4304,6 +4304,97 @@
        kUnsetFtraceId,
        419,
        kUnsetSize},
+      {"f2fs_iostat_latency",
+       "f2fs",
+       {
+           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
+            "d_rd_avg", 1, ProtoSchemaType::kUint32,
+            TranslationStrategy::kInvalidTranslationStrategy},
+           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
+            "d_rd_cnt", 2, ProtoSchemaType::kUint32,
+            TranslationStrategy::kInvalidTranslationStrategy},
+           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
+            "d_rd_peak", 3, ProtoSchemaType::kUint32,
+            TranslationStrategy::kInvalidTranslationStrategy},
+           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
+            "d_wr_as_avg", 4, ProtoSchemaType::kUint32,
+            TranslationStrategy::kInvalidTranslationStrategy},
+           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
+            "d_wr_as_cnt", 5, ProtoSchemaType::kUint32,
+            TranslationStrategy::kInvalidTranslationStrategy},
+           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
+            "d_wr_as_peak", 6, ProtoSchemaType::kUint32,
+            TranslationStrategy::kInvalidTranslationStrategy},
+           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
+            "d_wr_s_avg", 7, ProtoSchemaType::kUint32,
+            TranslationStrategy::kInvalidTranslationStrategy},
+           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
+            "d_wr_s_cnt", 8, ProtoSchemaType::kUint32,
+            TranslationStrategy::kInvalidTranslationStrategy},
+           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
+            "d_wr_s_peak", 9, ProtoSchemaType::kUint32,
+            TranslationStrategy::kInvalidTranslationStrategy},
+           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
+            "dev", 10, ProtoSchemaType::kUint64,
+            TranslationStrategy::kInvalidTranslationStrategy},
+           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
+            "m_rd_avg", 11, ProtoSchemaType::kUint32,
+            TranslationStrategy::kInvalidTranslationStrategy},
+           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
+            "m_rd_cnt", 12, ProtoSchemaType::kUint32,
+            TranslationStrategy::kInvalidTranslationStrategy},
+           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
+            "m_rd_peak", 13, ProtoSchemaType::kUint32,
+            TranslationStrategy::kInvalidTranslationStrategy},
+           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
+            "m_wr_as_avg", 14, ProtoSchemaType::kUint32,
+            TranslationStrategy::kInvalidTranslationStrategy},
+           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
+            "m_wr_as_cnt", 15, ProtoSchemaType::kUint32,
+            TranslationStrategy::kInvalidTranslationStrategy},
+           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
+            "m_wr_as_peak", 16, ProtoSchemaType::kUint32,
+            TranslationStrategy::kInvalidTranslationStrategy},
+           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
+            "m_wr_s_avg", 17, ProtoSchemaType::kUint32,
+            TranslationStrategy::kInvalidTranslationStrategy},
+           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
+            "m_wr_s_cnt", 18, ProtoSchemaType::kUint32,
+            TranslationStrategy::kInvalidTranslationStrategy},
+           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
+            "m_wr_s_peak", 19, ProtoSchemaType::kUint32,
+            TranslationStrategy::kInvalidTranslationStrategy},
+           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
+            "n_rd_avg", 20, ProtoSchemaType::kUint32,
+            TranslationStrategy::kInvalidTranslationStrategy},
+           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
+            "n_rd_cnt", 21, ProtoSchemaType::kUint32,
+            TranslationStrategy::kInvalidTranslationStrategy},
+           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
+            "n_rd_peak", 22, ProtoSchemaType::kUint32,
+            TranslationStrategy::kInvalidTranslationStrategy},
+           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
+            "n_wr_as_avg", 23, ProtoSchemaType::kUint32,
+            TranslationStrategy::kInvalidTranslationStrategy},
+           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
+            "n_wr_as_cnt", 24, ProtoSchemaType::kUint32,
+            TranslationStrategy::kInvalidTranslationStrategy},
+           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
+            "n_wr_as_peak", 25, ProtoSchemaType::kUint32,
+            TranslationStrategy::kInvalidTranslationStrategy},
+           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
+            "n_wr_s_avg", 26, ProtoSchemaType::kUint32,
+            TranslationStrategy::kInvalidTranslationStrategy},
+           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
+            "n_wr_s_cnt", 27, ProtoSchemaType::kUint32,
+            TranslationStrategy::kInvalidTranslationStrategy},
+           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
+            "n_wr_s_peak", 28, ProtoSchemaType::kUint32,
+            TranslationStrategy::kInvalidTranslationStrategy},
+       },
+       kUnsetFtraceId,
+       420,
+       kUnsetSize},
       {"fastrpc_dma_stat",
        "fastrpc",
        {
diff --git a/src/traced/probes/ftrace/test/data/synthetic/events/f2fs/f2fs_iostat_latency/format b/src/traced/probes/ftrace/test/data/synthetic/events/f2fs/f2fs_iostat_latency/format
new file mode 100644
index 0000000..9b55367
--- /dev/null
+++ b/src/traced/probes/ftrace/test/data/synthetic/events/f2fs/f2fs_iostat_latency/format
@@ -0,0 +1,38 @@
+name: f2fs_iostat_latency
+ID: 574
+format:
+	field:unsigned short common_type;	offset:0;	size:2;	signed:0;
+	field:unsigned char common_flags;	offset:2;	size:1;	signed:0;
+	field:unsigned char common_preempt_count;	offset:3;	size:1;	signed:0;
+	field:int common_pid;	offset:4;	size:4;	signed:1;
+
+	field:dev_t dev;	offset:8;	size:4;	signed:0;
+	field:unsigned int d_rd_peak;	offset:12;	size:4;	signed:0;
+	field:unsigned int d_rd_avg;	offset:16;	size:4;	signed:0;
+	field:unsigned int d_rd_cnt;	offset:20;	size:4;	signed:0;
+	field:unsigned int n_rd_peak;	offset:24;	size:4;	signed:0;
+	field:unsigned int n_rd_avg;	offset:28;	size:4;	signed:0;
+	field:unsigned int n_rd_cnt;	offset:32;	size:4;	signed:0;
+	field:unsigned int m_rd_peak;	offset:36;	size:4;	signed:0;
+	field:unsigned int m_rd_avg;	offset:40;	size:4;	signed:0;
+	field:unsigned int m_rd_cnt;	offset:44;	size:4;	signed:0;
+	field:unsigned int d_wr_s_peak;	offset:48;	size:4;	signed:0;
+	field:unsigned int d_wr_s_avg;	offset:52;	size:4;	signed:0;
+	field:unsigned int d_wr_s_cnt;	offset:56;	size:4;	signed:0;
+	field:unsigned int n_wr_s_peak;	offset:60;	size:4;	signed:0;
+	field:unsigned int n_wr_s_avg;	offset:64;	size:4;	signed:0;
+	field:unsigned int n_wr_s_cnt;	offset:68;	size:4;	signed:0;
+	field:unsigned int m_wr_s_peak;	offset:72;	size:4;	signed:0;
+	field:unsigned int m_wr_s_avg;	offset:76;	size:4;	signed:0;
+	field:unsigned int m_wr_s_cnt;	offset:80;	size:4;	signed:0;
+	field:unsigned int d_wr_as_peak;	offset:84;	size:4;	signed:0;
+	field:unsigned int d_wr_as_avg;	offset:88;	size:4;	signed:0;
+	field:unsigned int d_wr_as_cnt;	offset:92;	size:4;	signed:0;
+	field:unsigned int n_wr_as_peak;	offset:96;	size:4;	signed:0;
+	field:unsigned int n_wr_as_avg;	offset:100;	size:4;	signed:0;
+	field:unsigned int n_wr_as_cnt;	offset:104;	size:4;	signed:0;
+	field:unsigned int m_wr_as_peak;	offset:108;	size:4;	signed:0;
+	field:unsigned int m_wr_as_avg;	offset:112;	size:4;	signed:0;
+	field:unsigned int m_wr_as_cnt;	offset:116;	size:4;	signed:0;
+
+print fmt: "dev = (%d,%d), iotype [peak lat.(ms)/avg lat.(ms)/count], rd_data [%u/%u/%u], rd_node [%u/%u/%u], rd_meta [%u/%u/%u], wr_sync_data [%u/%u/%u], wr_sync_node [%u/%u/%u], wr_sync_meta [%u/%u/%u], wr_async_data [%u/%u/%u], wr_async_node [%u/%u/%u], wr_async_meta [%u/%u/%u]", ((unsigned int) ((REC->dev) >> 20)), ((unsigned int) ((REC->dev) & ((1U << 20) - 1))), REC->d_rd_peak, REC->d_rd_avg, REC->d_rd_cnt, REC->n_rd_peak, REC->n_rd_avg, REC->n_rd_cnt, REC->m_rd_peak, REC->m_rd_avg, REC->m_rd_cnt, REC->d_wr_s_peak, REC->d_wr_s_avg, REC->d_wr_s_cnt, REC->n_wr_s_peak, REC->n_wr_s_avg, REC->n_wr_s_cnt, REC->m_wr_s_peak, REC->m_wr_s_avg, REC->m_wr_s_cnt, REC->d_wr_as_peak, REC->d_wr_as_avg, REC->d_wr_as_cnt, REC->n_wr_as_peak, REC->n_wr_as_avg, REC->n_wr_as_cnt, REC->m_wr_as_peak, REC->m_wr_as_avg, REC->m_wr_as_cnt
diff --git a/test/trace_processor/fs/f2fs_iostat_latency.out b/test/trace_processor/fs/f2fs_iostat_latency.out
new file mode 100644
index 0000000..0d5ecae
--- /dev/null
+++ b/test/trace_processor/fs/f2fs_iostat_latency.out
@@ -0,0 +1,136 @@
+"name","ts","value"
+"f2fs_iostat_latency.[254:32].read_data_avg",1629349027,0.000000
+"f2fs_iostat_latency.[254:32].read_data_avg",1638349595,0.000000
+"f2fs_iostat_latency.[254:32].read_data_cnt",1629349027,143.000000
+"f2fs_iostat_latency.[254:32].read_data_cnt",1638349595,135.000000
+"f2fs_iostat_latency.[254:32].read_data_peak",1629349027,4.000000
+"f2fs_iostat_latency.[254:32].read_data_peak",1638349595,4.000000
+"f2fs_iostat_latency.[254:32].read_meta_avg",1629349027,2.000000
+"f2fs_iostat_latency.[254:32].read_meta_avg",1638349595,1.000000
+"f2fs_iostat_latency.[254:32].read_meta_cnt",1629349027,4.000000
+"f2fs_iostat_latency.[254:32].read_meta_cnt",1638349595,5.000000
+"f2fs_iostat_latency.[254:32].read_meta_peak",1629349027,4.000000
+"f2fs_iostat_latency.[254:32].read_meta_peak",1638349595,4.000000
+"f2fs_iostat_latency.[254:32].read_node_avg",1629349027,1.000000
+"f2fs_iostat_latency.[254:32].read_node_avg",1638349595,0.000000
+"f2fs_iostat_latency.[254:32].read_node_cnt",1629349027,121.000000
+"f2fs_iostat_latency.[254:32].read_node_cnt",1638349595,0.000000
+"f2fs_iostat_latency.[254:32].read_node_peak",1629349027,3.000000
+"f2fs_iostat_latency.[254:32].read_node_peak",1638349595,0.000000
+"f2fs_iostat_latency.[254:32].write_async_data_avg",1629349027,2.000000
+"f2fs_iostat_latency.[254:32].write_async_data_avg",1638349595,3.000000
+"f2fs_iostat_latency.[254:32].write_async_data_cnt",1629349027,929.000000
+"f2fs_iostat_latency.[254:32].write_async_data_cnt",1638349595,631.000000
+"f2fs_iostat_latency.[254:32].write_async_data_peak",1629349027,16.000000
+"f2fs_iostat_latency.[254:32].write_async_data_peak",1638349595,12.000000
+"f2fs_iostat_latency.[254:32].write_async_meta_avg",1629349027,0.000000
+"f2fs_iostat_latency.[254:32].write_async_meta_avg",1638349595,0.000000
+"f2fs_iostat_latency.[254:32].write_async_meta_cnt",1629349027,0.000000
+"f2fs_iostat_latency.[254:32].write_async_meta_cnt",1638349595,0.000000
+"f2fs_iostat_latency.[254:32].write_async_meta_peak",1629349027,0.000000
+"f2fs_iostat_latency.[254:32].write_async_meta_peak",1638349595,0.000000
+"f2fs_iostat_latency.[254:32].write_async_node_avg",1629349027,1.000000
+"f2fs_iostat_latency.[254:32].write_async_node_avg",1638349595,0.000000
+"f2fs_iostat_latency.[254:32].write_async_node_cnt",1629349027,23.000000
+"f2fs_iostat_latency.[254:32].write_async_node_cnt",1638349595,0.000000
+"f2fs_iostat_latency.[254:32].write_async_node_peak",1629349027,5.000000
+"f2fs_iostat_latency.[254:32].write_async_node_peak",1638349595,0.000000
+"f2fs_iostat_latency.[254:32].write_sync_data_avg",1629349027,2.000000
+"f2fs_iostat_latency.[254:32].write_sync_data_avg",1638349595,2.000000
+"f2fs_iostat_latency.[254:32].write_sync_data_cnt",1629349027,2705.000000
+"f2fs_iostat_latency.[254:32].write_sync_data_cnt",1638349595,3092.000000
+"f2fs_iostat_latency.[254:32].write_sync_data_peak",1629349027,20.000000
+"f2fs_iostat_latency.[254:32].write_sync_data_peak",1638349595,12.000000
+"f2fs_iostat_latency.[254:32].write_sync_meta_avg",1629349027,1.000000
+"f2fs_iostat_latency.[254:32].write_sync_meta_avg",1638349595,1.000000
+"f2fs_iostat_latency.[254:32].write_sync_meta_cnt",1629349027,1471.000000
+"f2fs_iostat_latency.[254:32].write_sync_meta_cnt",1638349595,1856.000000
+"f2fs_iostat_latency.[254:32].write_sync_meta_peak",1629349027,20.000000
+"f2fs_iostat_latency.[254:32].write_sync_meta_peak",1638349595,40.000000
+"f2fs_iostat_latency.[254:32].write_sync_node_avg",1629349027,0.000000
+"f2fs_iostat_latency.[254:32].write_sync_node_avg",1638349595,1.000000
+"f2fs_iostat_latency.[254:32].write_sync_node_cnt",1629349027,411.000000
+"f2fs_iostat_latency.[254:32].write_sync_node_cnt",1638349595,392.000000
+"f2fs_iostat_latency.[254:32].write_sync_node_peak",1629349027,20.000000
+"f2fs_iostat_latency.[254:32].write_sync_node_peak",1638349595,36.000000
+"f2fs_iostat_latency.[254:46].read_data_avg",1626347346,0.000000
+"f2fs_iostat_latency.[254:46].read_data_avg",1632350255,0.000000
+"f2fs_iostat_latency.[254:46].read_data_avg",1635348134,0.000000
+"f2fs_iostat_latency.[254:46].read_data_cnt",1626347346,84.000000
+"f2fs_iostat_latency.[254:46].read_data_cnt",1632350255,108.000000
+"f2fs_iostat_latency.[254:46].read_data_cnt",1635348134,127.000000
+"f2fs_iostat_latency.[254:46].read_data_peak",1626347346,4.000000
+"f2fs_iostat_latency.[254:46].read_data_peak",1632350255,4.000000
+"f2fs_iostat_latency.[254:46].read_data_peak",1635348134,4.000000
+"f2fs_iostat_latency.[254:46].read_meta_avg",1626347346,2.000000
+"f2fs_iostat_latency.[254:46].read_meta_avg",1632350255,0.000000
+"f2fs_iostat_latency.[254:46].read_meta_avg",1635348134,2.000000
+"f2fs_iostat_latency.[254:46].read_meta_cnt",1626347346,4.000000
+"f2fs_iostat_latency.[254:46].read_meta_cnt",1632350255,5.000000
+"f2fs_iostat_latency.[254:46].read_meta_cnt",1635348134,4.000000
+"f2fs_iostat_latency.[254:46].read_meta_peak",1626347346,4.000000
+"f2fs_iostat_latency.[254:46].read_meta_peak",1632350255,4.000000
+"f2fs_iostat_latency.[254:46].read_meta_peak",1635348134,4.000000
+"f2fs_iostat_latency.[254:46].read_node_avg",1626347346,0.000000
+"f2fs_iostat_latency.[254:46].read_node_avg",1632350255,0.000000
+"f2fs_iostat_latency.[254:46].read_node_avg",1635348134,0.000000
+"f2fs_iostat_latency.[254:46].read_node_cnt",1626347346,0.000000
+"f2fs_iostat_latency.[254:46].read_node_cnt",1632350255,0.000000
+"f2fs_iostat_latency.[254:46].read_node_cnt",1635348134,0.000000
+"f2fs_iostat_latency.[254:46].read_node_peak",1626347346,0.000000
+"f2fs_iostat_latency.[254:46].read_node_peak",1632350255,0.000000
+"f2fs_iostat_latency.[254:46].read_node_peak",1635348134,0.000000
+"f2fs_iostat_latency.[254:46].write_async_data_avg",1626347346,3.000000
+"f2fs_iostat_latency.[254:46].write_async_data_avg",1632350255,2.000000
+"f2fs_iostat_latency.[254:46].write_async_data_avg",1635348134,2.000000
+"f2fs_iostat_latency.[254:46].write_async_data_cnt",1626347346,800.000000
+"f2fs_iostat_latency.[254:46].write_async_data_cnt",1632350255,531.000000
+"f2fs_iostat_latency.[254:46].write_async_data_cnt",1635348134,790.000000
+"f2fs_iostat_latency.[254:46].write_async_data_peak",1626347346,16.000000
+"f2fs_iostat_latency.[254:46].write_async_data_peak",1632350255,12.000000
+"f2fs_iostat_latency.[254:46].write_async_data_peak",1635348134,36.000000
+"f2fs_iostat_latency.[254:46].write_async_meta_avg",1626347346,0.000000
+"f2fs_iostat_latency.[254:46].write_async_meta_avg",1632350255,1.000000
+"f2fs_iostat_latency.[254:46].write_async_meta_avg",1635348134,0.000000
+"f2fs_iostat_latency.[254:46].write_async_meta_cnt",1626347346,0.000000
+"f2fs_iostat_latency.[254:46].write_async_meta_cnt",1632350255,34.000000
+"f2fs_iostat_latency.[254:46].write_async_meta_cnt",1635348134,0.000000
+"f2fs_iostat_latency.[254:46].write_async_meta_peak",1626347346,0.000000
+"f2fs_iostat_latency.[254:46].write_async_meta_peak",1632350255,5.000000
+"f2fs_iostat_latency.[254:46].write_async_meta_peak",1635348134,0.000000
+"f2fs_iostat_latency.[254:46].write_async_node_avg",1626347346,0.000000
+"f2fs_iostat_latency.[254:46].write_async_node_avg",1632350255,0.000000
+"f2fs_iostat_latency.[254:46].write_async_node_avg",1635348134,0.000000
+"f2fs_iostat_latency.[254:46].write_async_node_cnt",1626347346,0.000000
+"f2fs_iostat_latency.[254:46].write_async_node_cnt",1632350255,0.000000
+"f2fs_iostat_latency.[254:46].write_async_node_cnt",1635348134,0.000000
+"f2fs_iostat_latency.[254:46].write_async_node_peak",1626347346,0.000000
+"f2fs_iostat_latency.[254:46].write_async_node_peak",1632350255,0.000000
+"f2fs_iostat_latency.[254:46].write_async_node_peak",1635348134,0.000000
+"f2fs_iostat_latency.[254:46].write_sync_data_avg",1626347346,2.000000
+"f2fs_iostat_latency.[254:46].write_sync_data_avg",1632350255,2.000000
+"f2fs_iostat_latency.[254:46].write_sync_data_avg",1635348134,1.000000
+"f2fs_iostat_latency.[254:46].write_sync_data_cnt",1626347346,2398.000000
+"f2fs_iostat_latency.[254:46].write_sync_data_cnt",1632350255,3034.000000
+"f2fs_iostat_latency.[254:46].write_sync_data_cnt",1635348134,3019.000000
+"f2fs_iostat_latency.[254:46].write_sync_data_peak",1626347346,24.000000
+"f2fs_iostat_latency.[254:46].write_sync_data_peak",1632350255,36.000000
+"f2fs_iostat_latency.[254:46].write_sync_data_peak",1635348134,28.000000
+"f2fs_iostat_latency.[254:46].write_sync_meta_avg",1626347346,1.000000
+"f2fs_iostat_latency.[254:46].write_sync_meta_avg",1632350255,0.000000
+"f2fs_iostat_latency.[254:46].write_sync_meta_avg",1635348134,1.000000
+"f2fs_iostat_latency.[254:46].write_sync_meta_cnt",1626347346,1325.000000
+"f2fs_iostat_latency.[254:46].write_sync_meta_cnt",1632350255,1602.000000
+"f2fs_iostat_latency.[254:46].write_sync_meta_cnt",1635348134,1739.000000
+"f2fs_iostat_latency.[254:46].write_sync_meta_peak",1626347346,20.000000
+"f2fs_iostat_latency.[254:46].write_sync_meta_peak",1632350255,20.000000
+"f2fs_iostat_latency.[254:46].write_sync_meta_peak",1635348134,8.000000
+"f2fs_iostat_latency.[254:46].write_sync_node_avg",1626347346,1.000000
+"f2fs_iostat_latency.[254:46].write_sync_node_avg",1632350255,1.000000
+"f2fs_iostat_latency.[254:46].write_sync_node_avg",1635348134,0.000000
+"f2fs_iostat_latency.[254:46].write_sync_node_cnt",1626347346,428.000000
+"f2fs_iostat_latency.[254:46].write_sync_node_cnt",1632350255,390.000000
+"f2fs_iostat_latency.[254:46].write_sync_node_cnt",1635348134,407.000000
+"f2fs_iostat_latency.[254:46].write_sync_node_peak",1626347346,24.000000
+"f2fs_iostat_latency.[254:46].write_sync_node_peak",1632350255,32.000000
+"f2fs_iostat_latency.[254:46].write_sync_node_peak",1635348134,16.000000
diff --git a/test/trace_processor/fs/f2fs_iostat_latency.sql b/test/trace_processor/fs/f2fs_iostat_latency.sql
new file mode 100644
index 0000000..fa20398
--- /dev/null
+++ b/test/trace_processor/fs/f2fs_iostat_latency.sql
@@ -0,0 +1,10 @@
+SELECT
+  name,
+  ts,
+  value
+FROM
+  counter AS c
+  JOIN
+  counter_track AS ct
+  ON c.track_id = ct.id
+ORDER BY name,ts
diff --git a/test/trace_processor/fs/f2fs_iostat_latency.textproto b/test/trace_processor/fs/f2fs_iostat_latency.textproto
new file mode 100644
index 0000000..445fb6f
--- /dev/null
+++ b/test/trace_processor/fs/f2fs_iostat_latency.textproto
@@ -0,0 +1,195 @@
+packet {
+  ftrace_events {
+    cpu: 0
+    event {
+      timestamp: 1626347346
+      pid: 9087
+      f2fs_iostat_latency {
+        dev: 0xfe2e
+        d_rd_peak: 4
+        d_rd_avg: 0
+        d_rd_cnt: 84
+        n_rd_peak: 0
+        n_rd_avg: 0
+        n_rd_cnt: 0
+        m_rd_peak: 4
+        m_rd_avg: 2
+        m_rd_cnt: 4
+        d_wr_s_peak: 24
+        d_wr_s_avg: 2
+        d_wr_s_cnt: 2398
+        n_wr_s_peak: 24
+        n_wr_s_avg: 1
+        n_wr_s_cnt: 428
+        m_wr_s_peak: 20
+        m_wr_s_avg: 1
+        m_wr_s_cnt: 1325
+        d_wr_as_peak: 16
+        d_wr_as_avg: 3
+        d_wr_as_cnt: 800
+        n_wr_as_peak: 0
+        n_wr_as_avg: 0
+        n_wr_as_cnt: 0
+        m_wr_as_peak: 0
+        m_wr_as_avg: 0
+        m_wr_as_cnt: 0
+      }
+    }
+  }
+}
+packet {
+  ftrace_events {
+    cpu: 4
+    event {
+      timestamp: 1629349027
+      pid: 9662
+      f2fs_iostat_latency {
+        dev: 0xfe20
+        d_rd_peak: 4
+        d_rd_avg: 0
+        d_rd_cnt: 143
+        n_rd_peak: 3
+        n_rd_avg: 1
+        n_rd_cnt: 121
+        m_rd_peak: 4
+        m_rd_avg: 2
+        m_rd_cnt: 4
+        d_wr_s_peak: 20
+        d_wr_s_avg: 2
+        d_wr_s_cnt: 2705
+        n_wr_s_peak: 20
+        n_wr_s_avg: 0
+        n_wr_s_cnt: 411
+        m_wr_s_peak: 20
+        m_wr_s_avg: 1
+        m_wr_s_cnt: 1471
+        d_wr_as_peak: 16
+        d_wr_as_avg: 2
+        d_wr_as_cnt: 929
+        n_wr_as_peak: 5
+        n_wr_as_avg: 1
+        n_wr_as_cnt: 23
+        m_wr_as_peak: 0
+        m_wr_as_avg: 0
+        m_wr_as_cnt: 0
+      }
+    }
+  }
+}
+packet {
+  ftrace_events {
+    cpu: 3
+    event {
+      timestamp: 1632350255
+      pid: 2718
+      f2fs_iostat_latency {
+        dev: 0xfe2e
+        d_rd_peak: 4
+        d_rd_avg: 0
+        d_rd_cnt: 108
+        n_rd_peak: 0
+        n_rd_avg: 0
+        n_rd_cnt: 0
+        m_rd_peak: 4
+        m_rd_avg: 0
+        m_rd_cnt: 5
+        d_wr_s_peak: 36
+        d_wr_s_avg: 2
+        d_wr_s_cnt: 3034
+        n_wr_s_peak: 32
+        n_wr_s_avg: 1
+        n_wr_s_cnt: 390
+        m_wr_s_peak: 20
+        m_wr_s_avg: 0
+        m_wr_s_cnt: 1602
+        d_wr_as_peak: 12
+        d_wr_as_avg: 2
+        d_wr_as_cnt: 531
+        n_wr_as_peak: 0
+        n_wr_as_avg: 0
+        n_wr_as_cnt: 0
+        m_wr_as_peak: 5
+        m_wr_as_avg: 1
+        m_wr_as_cnt: 34
+      }
+    }
+  }
+}
+packet {
+  ftrace_events {
+    cpu: 2
+    event {
+      timestamp: 1635348134
+      pid: 9634
+      f2fs_iostat_latency {
+        dev: 0xfe2e
+        d_rd_peak: 4
+        d_rd_avg: 0
+        d_rd_cnt: 127
+        n_rd_peak: 0
+        n_rd_avg: 0
+        n_rd_cnt: 0
+        m_rd_peak: 4
+        m_rd_avg: 2
+        m_rd_cnt: 4
+        d_wr_s_peak: 28
+        d_wr_s_avg: 1
+        d_wr_s_cnt: 3019
+        n_wr_s_peak: 16
+        n_wr_s_avg: 0
+        n_wr_s_cnt: 407
+        m_wr_s_peak: 8
+        m_wr_s_avg: 1
+        m_wr_s_cnt: 1739
+        d_wr_as_peak: 36
+        d_wr_as_avg: 2
+        d_wr_as_cnt: 790
+        n_wr_as_peak: 0
+        n_wr_as_avg: 0
+        n_wr_as_cnt: 0
+        m_wr_as_peak: 0
+        m_wr_as_avg: 0
+        m_wr_as_cnt: 0
+      }
+    }
+  }
+}
+packet {
+  ftrace_events {
+    cpu: 2
+    event {
+      timestamp: 1638349595
+      pid: 9657
+      f2fs_iostat_latency {
+        dev: 0xfe20
+        d_rd_peak: 4
+        d_rd_avg: 0
+        d_rd_cnt: 135
+        n_rd_peak: 0
+        n_rd_avg: 0
+        n_rd_cnt: 0
+        m_rd_peak: 4
+        m_rd_avg: 1
+        m_rd_cnt: 5
+        d_wr_s_peak: 12
+        d_wr_s_avg: 2
+        d_wr_s_cnt: 3092
+        n_wr_s_peak: 36
+        n_wr_s_avg: 1
+        n_wr_s_cnt: 392
+        m_wr_s_peak: 40
+        m_wr_s_avg: 1
+        m_wr_s_cnt: 1856
+        d_wr_as_peak: 12
+        d_wr_as_avg: 3
+        d_wr_as_cnt: 631
+        n_wr_as_peak: 0
+        n_wr_as_avg: 0
+        n_wr_as_cnt: 0
+        m_wr_as_peak: 0
+        m_wr_as_avg: 0
+        m_wr_as_cnt: 0
+      }
+    }
+  }
+}
diff --git a/test/trace_processor/fs/index b/test/trace_processor/fs/index
index c79f389..e95ab09 100644
--- a/test/trace_processor/fs/index
+++ b/test/trace_processor/fs/index
@@ -1 +1,2 @@
 f2fs_iostat.textproto f2fs_iostat.sql f2fs_iostat.out
+f2fs_iostat_latency.textproto f2fs_iostat_latency.sql f2fs_iostat_latency.out