Stop Losing Access When One Storage Path Dies: Practical Device Mapper Multipath on Linux
Software RAID protects you when a disk dies. Multipath protects you when a path dies.
If a host reaches the same LUN over two iSCSI NICs, two Fibre Channel HBAs, or two NVMe-oF fabrics, Linux will happily show you two (or four) block devices for one volume. Without multipath, a switch blip or cable pull turns into I/O errors — even though the data is still online on another path.
Device Mapper Multipath (multipath-tools / multipathd) collapses those paths into one stable device under /dev/mapper/, fails over automatically, and can load-balance when the array allows it.
This is a practical operator guide: install, configure safely, verify topology, test failover, and avoid the classic "local disk got swallowed by multipath" footgun.
What multipath is (and is not)
| Layer | Problem it solves |
|---|---|
| mdadm RAID | Disk/device redundancy and striping on the host |
| LVM | Volume composition, snapshots, thin pools |
| DM Multipath | Multiple I/O paths to the same remote LUN |
| Btrfs/ZFS scrub | Checksum integrity inside the filesystem/pool |
Use multipath when the storage presents one logical unit through multiple SCSI/NVMe paths. Do not use it as a substitute for RAID, backups, or array-side replication.
RHEL's storage docs describe DM Multipath exactly this way: multiple I/O paths between server and array become a single device, spanning separate cables, switches, and controllers.
Packages and service
Debian / Ubuntu:
sudo apt update
sudo apt install multipath-tools multipath-tools-boot
RHEL / Fedora / Alma / Rocky:
sudo dnf install device-mapper-multipath
sudo mpathconf --enable
Enable and start the daemon:
sudo systemctl enable --now multipathd.service
systemctl status multipathd.service --no-pager
On systemd builds, multipathd.socket can start the daemon on first CLI contact, and the service can integrate with WatchdogSec= (which overrides polling_interval / max_polling_interval when set). Prefer the enabled service so path monitoring is always running.
Discover what the host already sees
Before writing config, inventory raw paths:
# SCSI / iSCSI / FC disks
lsblk -o NAME,SIZE,TYPE,TRAN,WWN,MODEL,SERIAL
# Persistent IDs (prefer these over /dev/sdX)
ls -l /dev/disk/by-id/ | head
# iSCSI sessions (if applicable)
sudo iscsiadm -m session -P 3 2>/dev/null | sed -n '1,80p'
# FC remote ports (if applicable)
ls /sys/class/fc_remote_ports 2>/dev/null
You are looking for two or more block devices that share the same WWID/WWN but differ by path (by-path, HBA, or session target portal).
Dry-run multipath discovery without changing maps:
sudo multipath -d -v3
Show the live effective config (defaults + built-in hardware table + your file):
sudo multipath -t | less
# or
sudo multipathd show config | less
For a template limited to devices actually present:
sudo multipath -T
A safe baseline /etc/multipath.conf
Create or edit /etc/multipath.conf. Start conservative: friendly names, sensible path checks, no infinite hang-on-total-path-loss, and a blacklist that keeps local boot disks out of multipath.
sudo tee /etc/multipath.conf >/dev/null <<'EOF'
defaults {
user_friendly_names yes
find_multipaths yes
path_selector "service-time 0"
path_grouping_policy group_by_prio
path_checker tur
prio const
detect_prio yes
failback immediate
no_path_retry 12
queue_without_daemon no
verbosity 2
}
blacklist {
# Keep common local disks out unless you know you need them multipathed.
# Property/devnode defaults already exclude many non-disk types.
device {
vendor "ATA"
product ".*"
}
device {
vendor "NVMe"
product ".*"
}
}
blacklist_exceptions {
# Explicitly allow SAN/iSCSI vendors you trust (examples — match your array).
# device {
# vendor "NETAPP"
# product "LUN"
# }
}
# Optional: pin a stable alias for a known LUN WWID
# multipaths {
# multipath {
# wwid 36001405xxxxxxxxxxxxxxxxxxxxxxx
# alias data01
# }
# }
EOF
Reload configuration into the running daemon:
sudo multipathd reconfigure
# or
sudo systemctl reload multipathd.service
Why these knobs
From multipath.conf(5) (Debian multipath-tools / upstream):
-
user_friendly_names yes— aliases likempathavia/etc/multipath/bindingsinstead of raw WWIDs. Per-mapaliasstill wins. -
find_multipaths yes— create a map when the WWID was seen before or at least two non-blacklisted paths share a WWID. Safer thangreedy(everything becomes multipath) and more automatic than defaultstrict(WWIDs file only). -
path_checker tur— asyncTEST UNIT READY; default checker and a good general choice.detect_checker yes(default behavior path) will preferturon ALUA devices. -
path_selector "service-time 0"— default selector; picks paths based on outstanding I/O and relative throughput. Alternatives:round-robin 0,queue-length 0,historical-service-time 0(kernel 5.8+). -
path_grouping_policy group_by_prio— groups by priority (works well with ALUA viadetect_prio yes→sysfs/aluaprioritizer).multibusputs all paths in one group;failoveris one path per group. -
failback immediate— return to the best path group when it recovers. Usemanualorfollowoverin some active/passive dual-host designs. -
no_path_retry 12— queue briefly while paths recover, then fail I/O. Prefer this over deprecatedfeatures "1 queue_if_no_path", which can leave unkillableDstate processes if all paths stay down (KNOWN ISSUESin the man page). -
queue_without_daemon no— if multipathd stops, disable queuing so shutdown cannot hang forever waiting for dead paths.
Built-in hardware tables already know 100+ arrays. Only add a devices { device { ... } } override when vendor docs require it.
Blacklist strategy that will not eat your root disk
Evaluation order for blacklist criteria: property → devnode → device → protocol → wwid. Whitelist (blacklist_exceptions) wins per criterion.
Defaults already:
- Blacklist non-
sd/ non-dasd/ non-nvmedevnodes via!^(sd[a-z]|dasd[a-z]|nvme[0-9]) - Require a sensible udev property match (
SCSI_IDENT_|ID_WWN) via the default property exception
Still blacklist local SATA/NVMe explicitly in homelabs where a USB bridge or odd WWN might look "SAN-like". Confirm with:
sudo multipathd show devices
sudo multipathd show blacklist
Protocol filter example (only multipath iSCSI + FC, not local ATA):
blacklist {
protocol "scsi:ata"
protocol "nvme:pcie"
}
Recognized protocol strings include scsi:fcp, scsi:iscsi, scsi:sas, nvme:tcp, nvme:rdma, nvme:fc, and others listed in multipath.conf(5). Inspect live paths with:
sudo multipathd show paths format "%d %P %w %t %T %i %o"
Build and inspect maps
# Create/update maps from current paths
sudo multipath -v2
# Topology from sysfs + device-mapper
sudo multipath -ll
# Richer view (includes checker state)
sudo multipath -ll -v3
Typical healthy topology looks like:
mpatha (36001405aabbccddeeff001122334455) dm-3 NETAPP,LUN
size=500G features='0' hwhandler='1 alua' wp=rw
|-+- policy='service-time 0' prio=50 status=active
| |- 8:0:0:1 sdc 8:32 active ready running
| `- 8:0:1:1 sde 8:64 active ready running
`-+- policy='service-time 0' prio=10 status=enabled
|- 9:0:0:1 sdd 8:48 active ready running
`- 9:0:1:1 sdf 8:80 active ready running
Read this as: one multipath device mpatha, two path groups (often ALUA active/optimized vs non-optimized), four underlying paths.
Daemon-side checks:
sudo multipathd show maps status
sudo multipathd show maps topology
sudo multipathd show paths
sudo multipathd show status
sudo multipathd show daemon
Device nodes you should use in fstab/LVM/crypttab:
ls -l /dev/mapper/mpath*
readlink -f /dev/mapper/mpatha
ls -l /dev/disk/by-id/dm-name-mpatha /dev/disk/by-id/dm-uuid-* 2>/dev/null | head
Always mount /dev/mapper/mpatha (or a by-id dm link), never /dev/sdc. Path device names reshuffle; the multipath map does not.
Partitions on multipath devices
kpartx maps partition tables on top of multipath (and is invoked from hotplug when maps appear):
sudo kpartx -av /dev/mapper/mpatha
ls -l /dev/mapper/mpatha*
# list only
sudo kpartx -l /dev/mapper/mpatha
You should see nodes like /dev/mapper/mpatha1. Put filesystems or PVs there.
Skip automatic partition maps only if you intentionally manage whole-LUN devices:
defaults {
skip_kpartx yes
}
LVM and multipath coexistence
Tell LVM to prefer multipath nodes and ignore underlying path devices so it does not activate the same PV four times.
/etc/lvm/lvm.conf (snippet):
devices {
# Obtain with: sudo multipath -l | ...
# Modern LVM ships multipath-aware filters; verify with:
# sudo lvmdevices
# sudo pvs -a -o+devices
obtain_device_list_from_udev = 1
multipath_component_detection = 1
}
After maps exist:
sudo pvcreate /dev/mapper/mpatha
sudo vgcreate vg_data /dev/mapper/mpatha
sudo lvcreate -n lv_data -l 100%FREE vg_data
sudo mkfs.xfs /dev/vg_data/lv_data
If LVM still sees duplicate PVs on sd* paths, fix filters or ensure multipath claimed the devices before LVM (multipath -u during udev; multipath-tools-boot on Debian helps early boot).
Controlled failover test
Do this on a non-production LUN first, or during a maintenance window.
1. Start a write workload
# Example: sustained write to a test filesystem on the multipath LV
sudo mkdir -p /mnt/mpath-test
sudo mount /dev/vg_data/lv_data /mnt/mpath-test
sudo dd if=/dev/zero of=/mnt/mpath-test/probe.bin bs=1M count=2048 oflag=direct &
echo $!
2. Fail one path administratively
# Pick a path device from multipath -ll, e.g. sdc
sudo multipathd fail path sdc
sudo multipath -ll
I/O should continue on remaining paths. dd should not die.
3. Reinstate the path
sudo multipathd reinstate path sdc
sudo multipath -ll
With failback immediate and healthy priorities, the preferred path group should become active again.
4. Real link pull (best test)
- Unplug one FC cable, or
-
sudo ip link set ethX downon one iSCSI interface, or - Log out one iSCSI session:
sudo iscsiadm -m node -T <iqn> -p <portal> --logout
Watch:
sudo journalctl -u multipathd -f
sudo multipathd show paths format "%d %t %T %o %P"
5. Force path-group switch (optional)
sudo multipathd switch multipath mpatha group 2
sudo multipath -ll
Operational commands cheat sheet
| Goal | Command |
|---|---|
| List topology | multipath -ll |
| Reload all maps |
multipath -r or multipathd reconfigure
|
| Effective config | multipath -t |
| Add WWID to wwids file | multipath -a /dev/sdc |
| Remove WWID | multipath -w /dev/sdc |
| Flush unused map | multipath -f mpatha |
| Flush all unused | multipath -F |
| Fail/reinstate path |
multipathd fail path sdc / reinstate path sdc
|
| Disable queuing (emergency) | multipathd disablequeueing maps |
| Resize after array grow |
multipathd resize map mpatha then grow FS/LVM |
Interactive shell: sudo multipathd -k then show topology, show paths, etc.
Boot-time notes
- Install the distro boot integration package (
multipath-tools-booton Debian/Ubuntu,mpathconf --enableon RHEL) so initramfs can assemble maps before mounting multipathed root or critical volumes. - Rebuild initramfs after first working config:
sudo update-initramfs -u(Debian/Ubuntu) orsudo dracut -f(Fedora/RHEL). - In
crypttab/fstab, reference/dev/mapper/<alias>or/dev/disk/by-id/dm-name-<alias>, never ephemeral/dev/sd*. -
find_multipaths smartcan delay udev for single-path devices; preferyesplus explicit blacklists in mixed local+SAN hosts.
Monitoring that catches path loss
A tiny daily oneshot is enough for many labs:
sudo tee /usr/local/sbin/check-multipath-health >/dev/null <<'EOF'
#!/bin/bash
set -euo pipefail
out="$(multipathd show paths format '%d %t %T %o' 2>/dev/null || true)"
if [[ -z "$out" ]]; then
echo "multipath: no paths reported (daemon down or no maps)"
exit 0
fi
# Flag anything not ready/running
bad="$(printf '%s\n' "$out" | awk '($2 != "active" && $2 != "ghost") || ($3 != "ready") {print}' || true)"
if [[ -n "${bad}" ]]; then
echo "multipath path problems detected:"
echo "$bad"
multipath -ll || true
exit 1
fi
echo "multipath paths OK"
exit 0
EOF
sudo chmod 755 /usr/local/sbin/check-multipath-health
sudo tee /etc/systemd/system/multipath-health.service >/dev/null <<'EOF'
[Unit]
Description=Check DM-Multipath path health
After=multipathd.service
Requires=multipathd.service
[Service]
Type=oneshot
ExecStart=/usr/local/sbin/check-multipath-health
EOF
sudo tee /etc/systemd/system/multipath-health.timer >/dev/null <<'EOF'
[Unit]
Description=Daily multipath path health check
[Timer]
OnCalendar=daily
Persistent=true
RandomizedDelaySec=15m
[Install]
WantedBy=timers.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable --now multipath-health.timer
sudo systemctl start multipath-health.service
journalctl -u multipath-health.service -n 20 --no-pager
Wire failures into email/ChatOps however you already alert on systemd unit failures.
Common failure modes
Mounted
/dev/sddinstead of/dev/mapper/mpatha
Path loss = filesystem death. Fix mounts/LVM to the dm device.Local disk multipathed
Tighten blacklist;multipath -funused maps; scrub bindings/wwids if needed (multipath -Wresets wwids to current maps — understand it before running).Infinite I/O hang when array disappears
You used perpetual queueing. Setno_path_retryto a finite value; keepqueue_without_daemon no.Flapping marginal paths
Look atsan_path_err_*/marginal_pathgroupsinmultipath.conf(5)("Shaky paths detection") before blaming the HBA.Wrong active controller forever
Check ALUA:detect_prio yes, hardware handleralua, and array host mode set to a Linux DM-Multipath profile per vendor docs.Duplicate LVM PVs
Enable multipath component detection; neverpvcreateon raw path devices once multipath owns the LUN.
Cleanup / rollback
# Stop using maps (unmount/vgchange -an first!)
sudo umount /mnt/mpath-test || true
sudo vgchange -an vg_data 2>/dev/null || true
sudo multipath -F
sudo systemctl disable --now multipathd.service
# Remove or rename /etc/multipath.conf if you are abandoning multipath
Boundary check
| Use multipath | Use something else |
|---|---|
| Dual-HBA FC to one SAN LUN | mdadm for local disk RAID |
| Two NIC iSCSI sessions to one target LUN | Bond/LACP alone (helps link, not SCSI session failover the same way) |
| NVMe-oF multipathing via DM-MP or native NVMe multipath | Btrfs/ZFS scrub for bitrot |
| Transparent path failover under LVM/XFS | backups (restic, snapshots) for data loss |
Native NVMe multipathing in the kernel is a related but separate mode (nvme_core.multipath); multipath-tools also ships foreign library support for NVMe. Pick one approach per stack — do not double-multipath blindly.
Quick bring-up checklist
- Install
multipath-tools/device-mapper-multipathand enablemultipathd. - Confirm multiple paths share one WWID (
lsblk,by-id,multipath -d -v3). - Drop a minimal
multipath.confwith friendly names,find_multipaths yes, finiteno_path_retry, and local-disk blacklist. -
multipathd reconfigure && multipath -ll— one map, multiplereadypaths. - Create partitions with
kpartxor whole-LUN LVM on/dev/mapper/mpathXonly. - Fail a path with
multipathd fail path …under load; confirm I/O survives. - Point fstab/crypttab/LVM at mapper nodes; rebuild initramfs if needed at boot.
- Add a daily health oneshot so silent path loss is not discovered during the next outage.
Redundant cables only help if the OS treats them as one volume. Multipath is how Linux does that — configure it once, test failover on purpose, and stop treating /dev/sdX as stable storage names.
Sources and references
-
multipath.conf(5)— Debian manpages (configuration reference: defaults, blacklist, find_multipaths, selectors, no_path_retry, known issues): https://manpages.debian.org/bookworm/multipath-tools/multipath.conf.5.en.html -
multipath(8)— map create/list/flush/wwids operations: https://manpages.debian.org/bookworm/multipath-tools/multipath.8.en.html -
multipathd(8)— daemon CLI (show paths/maps, fail/reinstate, reconfigure, systemd integration): https://manpages.debian.org/bookworm/multipath-tools/multipathd.8.en.html -
kpartx(8)— partition device maps on multipath LUNs: https://manpages.debian.org/bookworm/kpartx/kpartx.8.en.html - Red Hat Enterprise Linux 9 — Managing storage devices (DM Multipath overview in the storage stack): https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/9/html-single/managing_storage_devices/index
- multipath-tools upstream (OpenSVC / Christophe Varoqui et al.) via distribution packaging and man pages above
Top comments (0)