Stage 3 · Build
Storage Reliability & Performance
I/O Scheduler Selection
Choosing none, mq-deadline, kyber, or BFQ for NVMe, SSD, and spinning disks.
Scheduler Overview
The I/O scheduler sits between the filesystem and the block device driver. It reorders, merges, and prioritizes I/O requests. The right scheduler depends on your storage hardware and workload characteristics.
# View current scheduler
cat /sys/block/nvme0n1/queue/scheduler
# [none] kyber mq-deadline bfq
cat /sys/block/sda/queue/scheduler
# [mq-deadline] kyber bfq none
# Change scheduler at runtime
echo kyber > /sys/block/sda/queue/scheduler
# Persistent via udev rule
cat > /etc/udev/rules.d/60-ioscheduler.rules << 'EOF'
ACTION=="add|change", KERNEL=="nvme*", ATTR{queue/scheduler}="none"
ACTION=="add|change", KERNEL=="sd*", ATTR{queue/scheduler}="mq-deadline"
ACTION=="add|change", KERNEL=="vd*", ATTR{queue/scheduler}="none"
EOF
sudo udevadm control --reload-rules
sudo udevadm triggerSchedulers can be changed at runtime without affecting existing I/O. The change applies to new requests only.
none: Direct Dispatch
The none scheduler passes requests directly to the hardware with no reordering. This is optimal for fast NVMe drives where the hardware queue management is already efficient.
# No queuing overhead
echo none > /sys/block/nvme0n1/queue/scheduler
# Test with fio
fio --name=test --ioengine=libaio --direct=1 --bs=4k --iodepth=128 --rw=randread --size=1G --filename=/dev/nvme0n1 --runtime=30
# Typical NVMe results with none:
# IOPS: 500K-1M (random 4K read)
# Latency: 10-20 microsecondsnone is the default and recommended scheduler for NVMe drives. The hardware already handles multi-queue scheduling efficiently.
mq-deadline
mq-deadline provides deadline-based request ordering. It ensures no request waits longer than a configured deadline (default 500ms for reads, 5s for writes). This prevents starvation of reads by writes.
# View deadline parameters
cat /sys/block/sda/queue/iosched/read_expire
# 500 (ms)
cat /sys/block/sda/queue/iosched/write_expire
# 5000 (ms)
cat /sys/block/sda/queue/iosched/writes_starved
# 2 (reads get 2x priority)
# Configure for database workload
echo 250 > /sys/block/sda/queue/iosched/read_expire # 250ms read deadline
echo 2500 > /sys/block/sda/queue/iosched/write_expire # 2500ms write deadline
echo 1 > /sys/block/sda/queue/iosched/writes_starved # Reads get higher prioritymq-deadline is the best general-purpose scheduler. It provides fairness and prevents starvation. Use it for SATA SSDs and databases.
kyber
kyber is a latency-focused scheduler that uses two queues: one for reads and one for writes. It targets low latency by dispatching requests based on latency targets rather than deadlines.
# View kyber parameters
cat /sys/block/sda/queue/iosched/read_lat_nsec
# 2000000 (2ms target read latency)
cat /sys/block/sda/queue/iosched/write_lat_nsec
# 10000000 (10ms target write latency)
# Configure for low-latency reads
echo 1000000 > /sys/block/sda/queue/iosched/read_lat_nsec # 1ms
echo 5000000 > /sys/block/sda/queue/iosched/write_lat_nsec # 5ms
# Monitor kyber behavior
cat /sys/block/sda/queue/iosched/read_done_cnt
cat /sys/block/sda/queue/iosched/write_done_cntkyber works well for fast SSDs where you want consistent latency. It dynamically adjusts dispatch rates to meet latency targets.
BFQ
BFQ (Budget Fair Queueing) provides proportional share scheduling. It gives each process a fair share of I/O bandwidth based on weights. BFQ is excellent for desktop and interactive workloads where responsiveness matters.
# View BFQ parameters
cat /sys/block/sda/queue/iosched/weight
# 100 (default weight)
cat /sys/block/sda/queue/iosched/fifo_expire_sync
# 125 (ms)
cat /sys/block/sda/queue/iosched/low_latency
# 1 (enabled)
# Set weights for different processes
echo 200 > /sys/block/sda/queue/iosched/weight # Higher weight = more bandwidth
# BFQ is best for desktop/interactive workloads
# Disable for high-throughput serversBFQ is ideal for desktop Linux, laptops, and interactive servers. For high-throughput servers, mq-deadline or none is usually better.
Selection Guide
| Storage Type | Workload | Recommended Scheduler |
|---|---|---|
| NVMe | Any | none |
| SATA SSD | Database | mq-deadline |
| SATA SSD | General | mq-deadline |
| SATA SSD | Latency-sensitive | kyber |
| HDD | Desktop/Laptop | BFQ |
| HDD | Server | mq-deadline |
| virtio | VM disk | none |
Define scheduler settings in /etc/udev/rules.d/ so they persist across reboots. This ensures every disk gets the right scheduler automatically.
Run fio with your workload pattern before and after changing the scheduler. Measure IOPS, latency (p50, p99, p999), and throughput to validate the improvement.
Mark this lesson complete to store local progress and unlock a cleaner resume path the next time you visit.