How BFQ I/O Scheduling Works in Linux

The Linux operating system relies on input/output (I/O) schedulers to manage how read and write requests are submitted to storage devices. Budget Fair Queueing (BFQ) is a proportional-share storage I/O scheduler designed to optimize both system responsiveness and throughput. Unlike traditional schedulers that allocate fixed time slices, BFQ assigns a dynamic "budget" measured in sectors to each active process, ensuring low-latency operations for interactive tasks while preventing heavy I/O operations from starving the system.

The Core Mechanism: Budget-Based Allocation

BFQ evolves from the older Completely Fair Queueing (CFQ) scheduler, replacing time-based slicing with a sector-based budget. When an application requests storage access, BFQ assigns it a budget representing the number of sectors the process is permitted to transfer before the scheduler switches to another task.

To manage these queues mathematically, BFQ implements an augmented variant of the Worst-case Fair Weighted Fair Queueing (B-WF2Q+) algorithm. This algorithm tracks the service guarantees of each process and ensures that:

Low Latency and Interactive Application Detection

A primary strength of BFQ is its heuristic engine that identifies latency-sensitive tasks, such as desktop GUI interactions, audio playback, and video streaming. When BFQ detects that an application requires minimal, non-continuous disk access to keep the user interface responsive, it automatically flags the process.

Flagged interactive applications are given immediate, privileged access to the storage controller, pre-empting large background read or write requests. Once the critical frames or user commands are executed, the scheduler yields control back to bulk operations like file downloads or database indexing.

Device Throughput and Playout

Achieving high throughput requires balancing fairness with hardware physics. On mechanical drives (HDDs), switching between different data locations incurs physical seek latency. On flash storage (SSDs and eMMC), interleaving unrelated write streams can reduce flash translation layer (FTL) efficiency.

BFQ optimizes device throughput using "budgets" in the following ways:

I/O Priorities with ionice

BFQ natively integrates with the standard Linux I/O priority subsystem (ionice). It categorizes tasks into three main classes:

  1. Real-Time: Granted priority over all other requests; processes in this class deplete their budgets first.
  2. Best-Effort: The default class where bandwidth is divided according to user-defined weights (ranging from 0 to 7).
  3. Idle: Receives storage access only when no other process has pending I/O operations.

Ideal Use Cases

BFQ is built specifically for scenarios where responsiveness is paramount: