blktrace
Linux blktrace — Complete Learning Notes & Output Guide
blktraceis the low-level block layer I/O tracing facility built into the Linux kernel. It captures the complete lifecycle of every I/O request—from the moment a filesystem submits a buffer (bio), through I/O scheduler queues and merging, down to device driver dispatch and hardware completion.
1. What is blktrace?
blktrace stands for:
Block Layer Tracer
While iostat provides point-in-time rolling averages and biolatency provides logarithmic histograms, blktrace provides an event-by-event chronicle of the kernel block I/O pipeline.
Using the kernel relayfs / debugfs infrastructure, blktrace logs raw per-CPU binary trace streams that are subsequently parsed and formatted into human-readable text by blkparse or analyzed by btt (Block Trace Toolkit).
It answers the deepest storage diagnostic questions:
- Where is time being spent: inside the application, waiting in OS kernel queues, or waiting for physical NAND/platter hardware response?
- Are sequential requests being merged effectively into large transfers, or is I/O fragmenting into small requests?
- How long do requests sit waiting for queue tags or scheduler dispatch slots?
- What are the exact physical sector numbers being accessed across the partition?
2. Installation & Ecosystem Tools
blktrace is distributed as a standalone package containing multiple complementary utilities:
| Tool | Role |
|---|---|
blktrace |
Kernel-space recorder that writes raw per-CPU binary trace streams to disk. |
blkparse |
Formatter that reads raw binary traces and parses them into chronological event logs. |
btrace |
A convenience wrapper script that runs blktrace and pipes live into blkparse. |
btt |
Block Trace Toolkit: Post-processing analytical engine that computes exact pipeline latency stages (Q2G, G2I, I2D, D2C). |
blkrawverify |
Validates consistency of raw trace files. |
Debian / Ubuntu
sudo apt update
sudo apt install blktrace
RHEL / Rocky / AlmaLinux / CentOS
sudo dnf install blktrace
Arch Linux
sudo pacman -S blktrace
Verify:
blktrace -v
3. The Linux Block I/O Lifecycle (The Event Sequence)
Every I/O request traverses several well-defined phases inside the Linux kernel block layer. blktrace instruments each of these transitions with a unique action code:
Application (write() / read())
|
v
Filesystem (VFS)
|
v
+-------------------------------------------------------------+
| LINUX BLOCK LAYER |
| |
| 1. [A] Remap: Translates partition/LVM to physical disk. |
| 2. [Q] Queued: bio submitted to the block queue. |
| 3. [G] Get Request: Allocates a struct request. |
| 4. [M] Merged: Request merged with an existing queued I/O.|
| 5. [I] Inserted: Sent to I/O scheduler (mq-deadline/bfq).|
| 6. [D] Dispatched: Issued to the hardware device driver. |
| |
+-------------------------------------------------------------+
|
v
+-------------------------------------------------------------+
| HARDWARE LAYER |
| |
| 7. [C] Completed: Storage controller returns ACK/data. |
| |
+-------------------------------------------------------------+
4. Basic Syntax & Execution Modes
Because blktrace outputs binary files per CPU core, standard execution requires either piping to blkparse or using the btrace wrapper.
Method 1: Live Real-Time Tracing via btrace
sudo btrace /dev/sda
Method 2: Two-Step Recording & Parsing (Recommended for Production)
# 1. Record 10 seconds of raw trace data to files: <dev>.<cpu>
sudo blktrace -d /dev/sda -w 10
# 2. Parse the recorded binary dumps into a formatted report
blkparse -i sda -d sda.parse.out
5. Anatomy of the Standard blkparse Output Line
When parsed, every single block layer event is printed as a structured text line:
8,0 2 1 0.000000000 4512 Q WS 2457600 + 8 [python3]
8,0 2 2 0.000001250 4512 G WS 2457600 + 8 [python3]
8,0 2 3 0.000002100 4512 I WS 2457600 + 8 [python3]
8,0 0 4 0.000005400 0 D WS 2457600 + 8 [swapper/0]
8,0 1 5 0.000128450 0 C WS 2457600 + 8 [0]
6. Detailed Breakdown of Every Output Heading & Field
+---------+-----+-----+---------------+------+--------+------+---------------+-----------+
| Device | CPU | Seq | Timestamp | PID | Action | RWBS | Sector + Size | Process |
+---------+-----+-----+---------------+------+--------+------+---------------+-----------+
| 8,0 | 2 | 1 | 0.000000000 | 4512 | Q | WS | 2457600 + 8 | [python3] |
+---------+-----+-----+---------------+------+--------+------+---------------+-----------+
6.1 Device (8,0)
- Format:
Major,Minordevice numbers. - Meaning: Identifies the Linux block device handle.
8,0corresponds to/dev/sda,8,16to/dev/sdb,259,0to/dev/nvme0n1.
6.2 CPU (2)
- Meaning: The logical CPU core on which the kernel event was processed.
6.3 Seq (Sequence Number, 1)
- Meaning: Monotonically increasing sequence integer per trace session. Used to detect dropped events or out-of-order execution across multiple cores.
6.4 Timestamp (0.000000000)
- Format: Seconds.Nanoseconds elapsed since trace initialization.
- Troubleshooting Significance: High-resolution timing used to calculate microsecond and nanosecond intervals between consecutive pipeline stages.
6.5 PID (4512)
- Meaning: The Process ID that initiated the operation. If an action is processed in an interrupt handler or kernel worker context upon completion, this may display
0(idle task / kernel context).
6.6 Action (Event Stage Code, Q)
- Meaning: The specific block lifecycle state being transitioned through. (Full list decoded in Section 7).
6.7 RWBS (I/O Type & Flags, WS)
- Meaning: Direction and attributes of the request (e.g., Write, Synchronous). (Full list decoded in Section 8).
6.8 Sector + Size (2457600 + 8)
- Format:
Starting_Sector + Number_of_Sectors - Sector Size: Standard Linux block layer calculations assume 512 bytes per sector.
- Byte Calculation:
$$\text{Bytes} = 8 \text{ sectors} \times 512\text{ bytes} = 4096\text{ bytes (4 KB)}$$
- Troubleshooting Significance: Consecutive sector numbers reveal sequential streaming. Disjointed, widely varying sector numbers indicate random I/O seeking.
6.9 Process ([python3])
- Meaning: The executable command name of the thread owning the operation. In completion events (
C), this often displays[0]or the return status code.
7. Deep-Dive: Action / Event Codes
The single-character Action code indicates the exact block-layer transition point:
| Code | Name | Technical Meaning |
|---|---|---|
A |
Remap | The I/O was remapped to a different device or partition (e.g., translating a logical volume or MD-RAID block to a physical disk sector). |
Q |
Queued | A bio request from the filesystem or memory manager has entered the block device queue. |
G |
Get Request | A new struct request structure was allocated from the block layer request pool. |
M |
Merged | The request was contiguous with a previously queued request and merged into a single larger request. |
F |
Front Merge | Merged to the beginning of an existing request in the queue. |
B |
Bounce | Memory buffer resides in high memory and required bouncing through a low-memory DMA buffer. |
I |
Inserted | The request was submitted to the I/O scheduler (e.g., mq-deadline, bfq). |
D |
Dispatched | The request left the scheduler queue and was sent down to the physical device driver/controller. |
C |
Completed | The storage device signaled completion via hardware interrupt; the driver finalized the request. |
P |
Plug | The queue was plugged (temporarily paused) to allow subsequent requests to accumulate and merge. |
U |
Unplug | The queue was unplugged; queued requests are released for dispatch. |
S |
Sleep | The process was put to sleep waiting for an available request descriptor due to queue exhaustion. |
8. Deep-Dive: RWBS Flags
The RWBS field denotes the read/write direction and operational modifiers:
| Flag Character | Name | Technical Meaning |
|---|---|---|
R |
Read | Data is being fetched from disk into memory. |
W |
Write | Data is being transferred from memory to non-volatile storage. |
D |
Discard / TRIM | Deallocates flash blocks on SSDs/NVMe drives. |
S |
Synchronous | The application thread is blocking until the I/O completes. |
A |
Read Ahead | Speculative read issued by the OS kernel ahead of current pointer. |
M |
Metadata | Filesystem superblock, inode, or directory tree metadata operation. |
F |
FUA | Force Unit Access: Writes must bypass device volatile write caches and commit directly to flash/magnetic media. |
B |
Barrier / Flush | Flush command issued to ensure previously written data is safely committed before continuing. |
N |
None | No direction specified (often used for queue management commands). |
Common Combinations
WS: Synchronous Write (e.g., database WAL commits,fsync).RA: Read-Ahead read.WM: Metadata Write (allocating inodes or updating filesystem tables).WSF: Synchronous Write with Force Unit Access (high-durability transactional write).
9. Post-Processing with btt (Block Trace Toolkit)
btt analyzes the raw trace data produced by blktrace and breaks down where latency occurred across the kernel lifecycle:
# Run btt against parsed trace data
btt -i sda.parse.out
Raw btt Output Example
==================== All Devices ====================
ALL MIN AVG MAX N
--------------- ------------- ------------- ------------- -----------
Q2G 0.000000850 0.000001240 0.000045100 10420
G2I 0.000000420 0.000000910 0.000012400 10420
I2D 0.000001100 0.004501200 0.085420100 10420
D2C 0.000120400 0.000850120 0.012450800 10420
Q2C 0.000125400 0.005353470 0.097883300 10420
The 5 Critical Latency Stages
Q (Queued)
|
|---> Q2G: Time to allocate a request structure
v
G (Get Request)
|
|---> G2I: Time to prepare and insert into scheduler
v
I (Inserted)
|
|---> I2D: Time spent sitting in scheduler / OS queue (Queue Delay)
v
D (Dispatched)
|
|---> D2C: Physical Hardware Service Time (Drive Controller Latency)
v
C (Completed)
========================================================================
Total End-to-End Latency = Q2C (Queue to Completion)
========================================================================
| Latency Metric | Description | Diagnostic Significance |
|---|---|---|
Q2G |
Queue to Get Request | Delays here indicate request pool exhaustion (nr_requests ceiling reached). |
G2I |
Get Request to Insert | Usually negligible; delays indicate memory allocator locks. |
I2D |
Insert to Dispatch | OS Queuing Delay. Long I2D times mean requests are stalled waiting for hardware queue tags or block scheduler slots. |
D2C |
Dispatch to Complete | Hardware Service Time. Long D2C times indicate slow physical NAND/disk media, SAN network delays, or bad sectors. |
Q2C |
Total Latency | Overall duration from initial kernel submission to final completion. |
10. blktrace vs. iostat vs. biosnoop vs. biolatency
| Feature | blktrace + btt |
iostat -x |
biosnoop (eBPF) |
biolatency (eBPF) |
|---|---|---|---|---|
| Primary Scope | Full kernel queue pipeline | High-level device averages | Driver dispatch & completion | Logarithmic latency histograms |
| OS Queue Time (I2D) | Yes (exact nanoseconds) | Estimated via aqu-sz |
Yes (via -Q) |
Yes (via -Q) |
| Hardware Latency (D2C) | Yes (exact nanoseconds) | Estimated via await |
Yes | Yes |
| Request Merging Visibility | Full (M, F events) |
Output averages (rrqm/s) |
No | No |
| Sector / LBA Tracking | Yes (exact sector numbers) | No | Yes | No |
| Overhead | Moderate to High | Zero (Reads /proc) |
Moderate | Negligible |
| Storage Consumption | Writes large binary traces | None | Terminal output only | None (in-kernel maps) |
11. Real-World Troubleshooting Scenarios
Scenario A: Diagnosing Host Queue Congestion vs. Hardware Storage Failure
A server experiences 100ms I/O latency spikes. You need to know whether the physical drive is dying or if the Linux kernel scheduler is backlogged.
Run blktrace and parse with btt:
sudo btrace /dev/sda -w 10 -o trace_run
btt -i trace_run.parse.out
- Case 1:
I2D = 95ms,D2C = 5ms: The physical disk responded in only 5ms. The 95ms stall occurred inI2D, proving the bottleneck is host OS queue congestion (e.g., queue depth too shallow, wrong I/O scheduler, or block layer lock contention). - Case 2:
I2D = 1ms,D2C = 99ms: The OS handed the request to the hardware immediately, but the drive took 99ms to return. The bottleneck is physical storage hardware (bad sectors, flash controller thermal throttling, or cloud EBS bandwidth exhaustion).
Scenario B: Verifying Sequential I/O Merging Efficiency
A data ingestion service writes 4KB records continuously. You want to verify whether the Linux block layer is merging them into efficient 128KB transfers before hitting disk:
sudo btrace /dev/sda | grep -E "( M | D )"
- Healthy Merging: You see numerous
M(Merge) events followed by a singleD(Dispatch) with a large sector size (+ 256). - Unmerged / Fragmented I/O: Every
Qevent is followed immediately by aDevent with+ 8(4KB) and zeroMevents, proving that writes are unbuffered and bypassing scheduler merging.
12. Important Interview Questions & Answers
Q: What is the operational distinction between the I2D and D2C latency stages in btt?
Answer: I2D (Insert to Dispatch) measures the time a request spent waiting inside the Linux kernel block layer and I/O scheduler queues before being handed off to the device driver. D2C (Dispatch to Completion) measures the time from when the device driver sent the request to the storage controller until the storage hardware completed the transfer and triggered an interrupt. High I2D points to OS scheduler misconfigurations or queue depth exhaustion, while high D2C points to physical disk saturation or hardware bottlenecks.
Q: What does an A (Remap) event in blkparse indicate?
Answer: An A event indicates that an I/O request targeting a logical partition (e.g., /dev/sda1), device-mapper target (LVM, LUKS encryption), or MD-RAID array was remapped by the kernel block layer to its underlying physical disk and physical starting sector address.
Q: Why is blktrace typically run for short windows (10–30 seconds) rather than left running continuously?
Answer: blktrace records high-volume binary trace records for every block layer event across all CPU cores into /sys/kernel/debug/tracing via relayfs. On a storage subsystem processing 50,000 to 100,000 IOPS, blktrace can generate gigabytes of trace data per minute, consuming significant disk space and introducing I/O interference if the trace data is written to the same storage controller being monitored.