Skip to main content
RunBook Academy

Proxmox VEXIX · TroubleshootingEvidence and escalation

Storage and ZFS troubleshooting

Advanced⏱ ~32 minzpoolzfspvesm

What you'll learn

  • Import a pool whose device names or host identity have changed, including read-only for rescue
  • Diagnose a resilver that has stalled by finding the device that is slowing it
  • Account for every byte in a full pool, including snapshots and zvol reservations
  • Free space on a pool that is too full to accept a delete
  • Recognise a suspended pool and the guest io-error state it produces

Prerequisites

Verified against Proxmox VE 9.2.4 · Proxmox Backup Server 4.2.5 · Ceph Squid / Tentacle · Debian 13 (Trixie) · Linux kernel 7.0 (PVE 9.2 default) · 2026-08-12

Not yet marked complete on this device.

ZFS faults reach you dressed as Proxmox faults. The storage shows inactive, a guest will not start, a backup fails, a VM is paused. The Proxmox layer is reporting accurately and has nothing more to tell you; everything useful is one layer down.

Four faults cover most of what you will meet, and each has a different first command.

Fault one: the pool will not import

pvesm status shows the ZFS storage inactive. zpool list shows nothing.

Read-only / Safewhat does ZFS see, and what could it import
zpool list

zpool import

zpool import -d /dev/disk/by-id

ls -l /dev/disk/by-id | grep -v part
Read-only / Safe
$ zpool import
   pool: tank
   id: 10913148573287938276
state: ONLINE
status: The pool was last accessed by another system.
action: The pool can be imported using its name or numeric identifier and
the '-f' flag.
 see: https://openzfs.github.io/openzfs-docs/msg/ZFS-8000-EY
config:

tank        ONLINE
  mirror-0  ONLINE
    ata-SAMSUNG_MZ7L3960_S6ABC0000000001  ONLINE
    ata-SAMSUNG_MZ7L3960_S6ABC0000000002  ONLINE

The common causes and their answers:

Symptom in zpool importCauseAction
Pool not listed at allDevices not present, or names not scannedzpool import -d /dev/disk/by-id; check lsblk, cabling, HBA
“last accessed by another system”Hostid mismatch — reinstall, disk move, or another live host-f, after confirming no other system has it
FAULTED, “insufficient replicas”Too many devices missing for the redundancy levelFind the missing devices; do not force
“may be in use from other system” with a live peerGenuinely dual-attachedStop. Forcing this is how you destroy a pool
Imports but hangsDamaged pool, or a device that responds slowly-o readonly=on, and -N to skip mounting

Fault two: the resilver has stopped moving

zpool status shows a resilver in progress with an estimate that grows every time you look.

Read-only / Safefind the device that is holding up the resilver
zpool status -v

zpool iostat -v 5 3

zpool events -v | tail -40

journalctl -k --since "-6h" | grep -iE 'ata|scsi|nvme|I/O error|medium error' | tail -40
Read-only / Safe
$ zpool status -v tank
  pool: tank
state: DEGRADED
status: One or more devices is currently being resilvered.
action: Wait for the resilver to complete.
scan: resilver in progress since Tue Aug 11 22:04:11 2026
1.42T scanned at 41.2M/s, 388G issued at 11.3M/s, 6.71T total
388G resilvered, 5.64% done, 6 days 14:22:19 to go
config:

NAME            STATE     READ WRITE CKSUM
tank            DEGRADED     0     0     0
  raidz2-0      DEGRADED     0     0     0
    ata-...001  ONLINE       0     0     0
    ata-...002  ONLINE       0     0    47
    ata-...003  ONLINE       0     0     0
    replacing-3 DEGRADED     0     0     0
      old       OFFLINE      0     0     0
      ata-...09 ONLINE       0     0     0

Fault three: the pool is full and nothing accounts for it

zfs list shows the pool nearly full. The guests on it add up to far less.

Read-only / Safeaccount for every byte
zpool list -o name,size,alloc,free,cap,frag,health

zfs list -o space -r rpool

zfs list -t snapshot -o name,used,refer -s used | tail -30

zfs get -r -o name,property,value refreservation,reservation,used,usedbysnapshots rpool | head -40
Read-only / Safe
$ zfs list -o space -r rpool/data
NAME                        AVAIL   USED  USEDSNAP  USEDDS  USEDREFRESERV  USEDCHILD
rpool/data                  212G  3.42T         0      0B             0B     3.42T
rpool/data/vm-141-disk-0    212G  1.02T      640G    404G             0B         0B
rpool/data/vm-142-disk-0    712G  1.98T         0    478G          1.5T         0B
rpool/data/subvol-205-disk-0 212G   412G      398G   14.1G             0B         0B

The four things that consume a ZFS pool without being obvious:

Snapshots. USEDSNAP is space held only by snapshots. A guest that deletes 100 GB frees nothing while a snapshot references it. This is the most common answer by a wide margin.

Refreservations on zvols. A thick-provisioned zvol reserves its full size whether or not it is written. USEDREFRESERV shows it. This is space that exists to guarantee the guest can always write, and it is a deliberate choice — but it is often an accidental one, inherited from a storage created without thin provisioning.

Fragmentation and the 80% rule. ZFS performance degrades as a pool fills, because finding contiguous free space gets harder. zpool list shows FRAG. A pool above about 80% is one to plan capacity for, not one to keep filling.

Reservations on datasets, which do the same job as refreservations at the dataset level and are rarer but harder to spot.

Fault four: guests are paused and the storage looks fine

A pool that hits an unrecoverable I/O error can enter a suspended state, in which all I/O to it blocks. Guests do not error; they stop.

Read-only / Safeis the pool suspended, and what are the guests doing
zpool status

zpool get failmode rpool

qm list

qm status 141

journalctl -k --since "-2h" | grep -iE 'zfs|zio|I/O failure|pool.*suspended' | tail -30

Key takeaways

  • zpool import with no arguments is the diagnosis for a pool that will not import: it prints the state, the reason and the recommended action.
  • Scan by -d /dev/disk/by-id. Device names are not stable and a pool that “disappeared” has usually just been renamed by the kernel.
  • -f overrides the check that stops two hosts importing the same pool. Confirm no other system has it — powered off, not merely shut down — before using it. Import -o readonly=on -N first when in doubt.
  • A resilver whose estimate keeps growing usually means a second marginal device returning checksum errors, or heavy client load. zpool iostat -v distinguishes them. Do not offline a second device while redundancy is already reduced.
  • zfs list -o space -r accounts for a full pool: USEDSNAP for snapshots, USEDREFRESERV for thick zvol reservations, USEDCHILD for descendants.
  • A pool at 100% may be unable to accept a delete, because deleting is a write. Destroy a snapshot or drop a refreservation instead.
  • A suspended pool with the default failmode=wait blocks all I/O, which presents as an unresponsive node rather than as a storage error. zpool status belongs early in the checklist for any hung node; recovery is to fix the device and then zpool clear.
  • Checksum errors are invisible to applications because ZFS repairs them transparently. Scrub on a schedule and alert on the counters, not only on pool state.

Knowledge check

Knowledge check · 5 questions

  1. Q1. A resilver on a RAIDZ2 pool reports six days remaining, where a previous resilver of the same pool took nine hours. zpool status shows CKSUM 47 on a device that is not the one being replaced. What is the finding and what should you not do?

  2. Q2. A ZFS pool is at 100% and you cannot delete guest disks to free space — the delete itself fails. Why, and what works instead?

  3. Q3. A node has become unresponsive: the GUI hangs for that node, qm list takes minutes, and tasks are stacking up. There is no obvious CPU or memory pressure. Which of these belong in the first minute? Select all that apply.

  4. Q4. Because ZFS repairs checksum errors transparently from redundancy, a failing disk can accumulate errors for weeks inside an ONLINE pool with no symptom visible to any guest or application.

  5. Q5. A rebuilt node cannot import its pool. zpool import reports the pool as ONLINE with status "The pool was last accessed by another system" and suggests -f. The disks are in a shared SAS enclosure also cabled to a second server. What now?

Passing score: 75%. Answers are checked in this browser.