The completely fair queueing (cfq) scheduler aims to equally divide all available I/O bandwidth among all processes issuing I/O requests. It is best suited for most medium and large multi-processor systems, as well as systems which required balanced I/O performance over several I/O controllers and LUNs. As such, cfq is the default scheduler for Red Hat Enterprise Linux 5.
The cfq scheduler maintains a maximum of 64 internal request queues; each process running on the system is assigned is assigned to any of these queues. Each time a process submits a synchronous I/O request, it is moved to the assigned internal queue. Asynchronous requests from all processes are batched together according to their process's I/O priority; for example, all asynchronous requests from processes with a scheduling priority of "idle" (3) are put into one queue.
During each cycle, requests are moved from each non-empty internal request queue into one dispatch queue. in a round-robin fashion. Once in the dispatch queue, requests are ordered to minimize disk seeks and serviced accordingly.
To illustrate: let's say that the 64 internal queues contain 10 I/O request seach, and quantum is set to 8. In the first cycle, the cfq scheduler will take one request from each of the first 8 internal queues. Those 8 requests are moved to the dispatch queue. In the next cycle (given that there are 8 free slots in the dispatch queue) the cfq scheduler will take one request from each of the next batches of 8 internal queues.
Example 1. How the cfq scheduler works
The tunable variables for the cfq scheduler are set in files found under /sys/block/<device>/queue/iosched/. These files are:
quantum
Total number of requests to be moved from internal queues to the dispatch queue in each cycle.
queued
Maximum number of requests allowed per internal queue.
For more information about ionice, scheduling classes, and scheduling priorities, refer to man ionice.