mdadm (multiple disk administration) is the standard Linux utility for creating, managing, and monitoring software RAID arrays using the kernel md driver.
Table of Contents#
- Overview
- RAID Levels
- Installation
- Creating a RAID Array
- Persistent Configuration
- Monitoring and Alerting
- Disk Failure and Recovery
- Write-Intent Bitmap
- Array Management
- Troubleshooting
- See Also
- Sources
1. Overview#
mdadm manages Linux software RAID arrays built on the kernel's md (multiple devices) driver. It supports RAID levels 0, 1, 4, 5, 6, and 10, plus linear (JBOD) and multipath configurations. Software RAID via mdadm:
- Runs on any hardware without a dedicated RAID controller
- Stores metadata (superblock) on each member device for portability
- Supports hot-spare disks for automatic failure recovery
- Integrates with the initramfs for booting from RAID arrays
- Provides email alerting on disk failures via the monitoring daemon
Components#
| Component | Description |
|---|---|
| md driver | Kernel module that implements the RAID logic |
| mdadm | Userspace tool for array creation, management, and monitoring |
| Superblock | Metadata stored on each device describing the array layout (version 1.2 is default) |
| Chunk size | Unit of data striping (default 512 KiB) |
| Bitmap | Write-intent log that speeds up resync after unclean shutdown |
2. RAID Levels#
| Level | Type | Min Disks | Redundancy | Usable Capacity | Best For |
|---|---|---|---|---|---|
| 0 | Stripe | 2 | None | N x disk | Temporary/scratch data |
| 1 | Mirror | 2 | 1 disk can fail | 1 x disk | Boot drives, OS mirrors |
| 5 | Stripe + parity | 3 | 1 disk can fail | (N-1) x disk | General purpose |
| 6 | Stripe + double parity | 4 | 2 disks can fail | (N-2) x disk | Large arrays, high reliability |
| 10 | Stripe of mirrors | 4 | 1 per mirror pair | N/2 x disk | Databases, high IOPS |
| Linear | Concatenation | 2 | None | N x disk | Simple capacity aggregation |
3. Installation#
# Debian/Ubuntu
sudo apt update && sudo apt install -y mdadm
# RHEL/CentOS/Rocky
sudo dnf install -y mdadm
# Arch Linux
sudo pacman -S mdadm4. Creating a RAID Array#
Step 1: Identify and Prepare Disks#
# List available disks
lsblk
# Ensure target disks have no existing partitions or data
sudo wipefs -a /dev/sda /dev/sdb /dev/sdcStep 2: Create the Array#
RAID 1 (2-disk mirror):
sudo mdadm --create /dev/md0 --level=1 --raid-devices=2 /dev/sda /dev/sdbRAID 5 (3 disks + optional spare):
sudo mdadm --create /dev/md0 --level=5 --raid-devices=3 \
--spare-devices=1 /dev/sda /dev/sdb /dev/sdc /dev/sddRAID 6 (4 disks):
sudo mdadm --create /dev/md0 --level=6 --raid-devices=4 \
/dev/sda /dev/sdb /dev/sdc /dev/sddRAID 10 (4 disks, near layout):
sudo mdadm --create /dev/md0 --level=10 --raid-devices=4 \
--layout=n2 /dev/sda /dev/sdb /dev/sdc /dev/sddStep 3: Create Filesystem and Mount#
# Format the array
sudo mkfs.ext4 /dev/md0
# Or with XFS
sudo mkfs.xfs /dev/md0
# Create mount point and mount
sudo mkdir -p /mnt/raid
sudo mount /dev/md0 /mnt/raidStep 4: Verify#
sudo mdadm --detail /dev/md0
cat /proc/mdstat5. Persistent Configuration#
Without a persistent configuration file, the array may not assemble automatically on reboot.
Saving the mdadm Configuration#
# Scan for arrays and write to config
sudo mdadm --detail --scan | sudo tee -a /etc/mdadm/mdadm.conf
# On RHEL-based systems
sudo mdadm --detail --scan | sudo tee -a /etc/mdadm.confUpdating initramfs#
The initramfs must include the mdadm configuration to assemble arrays at boot:
# Debian/Ubuntu
sudo update-initramfs -u
# RHEL/CentOS
sudo dracut --force
# Arch Linux
sudo mkinitcpio -PAdding to fstab#
# Get the UUID of the array
sudo blkid /dev/md0
# Add to /etc/fstab
echo 'UUID=<array-uuid> /mnt/raid ext4 defaults 0 2' | sudo tee -a /etc/fstabAlways use UUID rather than /dev/md0 in fstab, since device names can change across reboots.
6. Monitoring and Alerting#
mdadm Monitor Daemon#
mdadm includes a monitoring mode that watches arrays and sends email alerts on events (disk failure, rebuild start, rebuild complete, spare activation).
# Test monitoring (sends a test alert, runs once)
sudo mdadm --monitor --scan --test --oneshot
# Run the monitor daemon
sudo mdadm --monitor --scan --daemonise --mail=admin@example.com --delay=300Systemd Service#
Most distributions ship an mdadm monitoring service:
# Enable the monitoring service
sudo systemctl enable --now mdmonitor
# Check status
sudo systemctl status mdmonitorConfiguration for Email Alerts#
# /etc/mdadm/mdadm.conf (or /etc/mdadm.conf)
MAILADDR admin@example.comEnsure a working MTA (postfix, msmtp, or similar) is configured on the system.
Checking Array Status#
# Quick status of all arrays
cat /proc/mdstat
# Detailed status of a specific array
sudo mdadm --detail /dev/md0
# Check for degraded arrays
sudo mdadm --detail /dev/md0 | grep -i stateScheduled Scrubbing#
Regular data scrubbing detects and corrects silent corruption:
# Trigger a check (non-destructive)
echo check | sudo tee /sys/block/md0/md/sync_action
# Monitor progress
cat /proc/mdstat
# View mismatch count after check
cat /sys/block/md0/md/mismatch_cntAutomate via cron or systemd timer:
# /etc/cron.d/mdadm-scrub
0 2 1 * * root echo check > /sys/block/md0/md/sync_action7. Disk Failure and Recovery#
Detecting a Failed Disk#
# Check array status
sudo mdadm --detail /dev/md0
# Look for [UU_] pattern indicating a missing/failed disk
cat /proc/mdstatOutput example for a degraded RAID 5:
md0 : active raid5 sdc[2] sdb[1] sda[0](F)
2093056 blocks super 1.2 level 5, 512k chunk, algorithm 2 [3/2] [_UU]Removing a Failed Disk#
# Mark the disk as failed (if not already)
sudo mdadm /dev/md0 --fail /dev/sda
# Remove the failed disk from the array
sudo mdadm /dev/md0 --remove /dev/sdaAdding a Replacement Disk#
# Wipe the replacement disk
sudo wipefs -a /dev/sde
# Add the new disk to the array
sudo mdadm /dev/md0 --add /dev/sdeIf there was no hot spare, adding a new disk triggers an automatic rebuild.
Monitoring the Rebuild#
# Watch rebuild progress
watch cat /proc/mdstat
# Detailed rebuild info
sudo mdadm --detail /dev/md0Rebuild time depends on array size, disk speed, and I/O load. Estimated time is shown in /proc/mdstat:
[=>...................] recovery = 12.5% (131072/1046528) finish=5.2min speed=29127K/secControlling Rebuild Speed#
# Set minimum rebuild speed (KB/s)
echo 50000 | sudo tee /sys/block/md0/md/sync_speed_min
# Set maximum rebuild speed (KB/s) to limit impact on production I/O
echo 200000 | sudo tee /sys/block/md0/md/sync_speed_maxUsing Hot Spares#
A hot spare is automatically activated when a disk fails:
# Add a spare during array creation
sudo mdadm --create /dev/md0 --level=5 --raid-devices=3 \
--spare-devices=1 /dev/sda /dev/sdb /dev/sdc /dev/sdd
# Add a spare to an existing array
sudo mdadm /dev/md0 --add /dev/sdd
# If the array is not degraded, the disk becomes a spare automaticallyGrowing an Array#
# Add a disk and grow from 3 to 4 active RAID 5 devices
sudo mdadm /dev/md0 --add /dev/sde
sudo mdadm --grow /dev/md0 --raid-devices=4
# After reshape completes, expand the filesystem
sudo resize2fs /dev/md0 # ext4
sudo xfs_growfs /mnt/raid # XFS8. Write-Intent Bitmap#
A write-intent bitmap tracks which regions of the array have pending writes. After an unclean shutdown, only dirty regions need resync instead of the entire array, dramatically reducing recovery time.
Adding a Bitmap#
# Add an internal bitmap (stored on array member devices)
sudo mdadm --grow /dev/md0 --bitmap=internal
# Add an external bitmap file (for SSDs where write amplification matters)
sudo mdadm --grow /dev/md0 --bitmap=/path/to/bitmapRemoving a Bitmap#
sudo mdadm --grow /dev/md0 --bitmap=noneBitmap Trade-offs#
| Aspect | Without Bitmap | With Bitmap |
|---|---|---|
| Clean shutdown recovery | Full resync | No resync needed |
| Unclean shutdown recovery | Full resync (hours) | Partial resync (seconds to minutes) |
| Write performance | Normal | ~5-10% overhead |
| Recommended for | Disposable/scratch arrays | Production arrays |
9. Array Management#
Viewing Array Details#
# Summary of all arrays
cat /proc/mdstat
# Detailed info for one array
sudo mdadm --detail /dev/md0
# Examine a member device
sudo mdadm --examine /dev/sdaStopping and Reassembling#
# Stop an array
sudo umount /mnt/raid
sudo mdadm --stop /dev/md0
# Assemble from config
sudo mdadm --assemble --scan
# Assemble manually
sudo mdadm --assemble /dev/md0 /dev/sda /dev/sdb /dev/sdcDeleting an Array#
# Stop the array
sudo umount /mnt/raid
sudo mdadm --stop /dev/md0
# Zero the superblock on all member devices
sudo mdadm --zero-superblock /dev/sda /dev/sdb /dev/sdc
# Remove from mdadm.conf
sudo vi /etc/mdadm/mdadm.conf
# Update initramfs
sudo update-initramfs -uRenaming an Array#
# Assemble with a new name
sudo mdadm --stop /dev/md0
sudo mdadm --assemble /dev/md1 /dev/sda /dev/sdb /dev/sdc --update=name10. Troubleshooting#
| Issue | Cause | Solution |
|---|---|---|
| Array not assembled on boot | Missing or outdated mdadm.conf | Run mdadm --detail --scan >> /etc/mdadm/mdadm.conf and update-initramfs -u |
Array in degraded state | Disk failed or was removed | Replace the failed disk (see recovery steps above); add a hot spare for future protection |
mdadm: /dev/md0 assembled from 2 drives - not enough to start | Too few surviving members for the RAID level | Use --force to start a degraded array: mdadm --assemble --force /dev/md0 /dev/sda /dev/sdb |
| Rebuild never completes | I/O contention or very large disks | Increase sync_speed_min; reduce workload during rebuild; consider bitmap to avoid future full resyncs |
mismatch_cnt nonzero after scrub | Silent bit-rot or swap/temp file writes on RAID 5/6 | Small counts on RAID 5/6 from swap files are normal; persistent large counts indicate hardware issues |
/dev/md0 device number changes across reboots | Device enumeration order changed | Use UUID= in fstab and ensure mdadm.conf has UUID= entries from --detail --scan |
| Cannot stop array: "device or resource busy" | Filesystem still mounted or process using the array | Run umount /mnt/raid; check with lsof /mnt/raid or fuser -m /dev/md0 |
| RAID 5/6 write hole after power loss (no bitmap) | Parity not consistent | Add a write-intent bitmap to prevent future occurrences; check data integrity manually |