VMFS datastores use on-disk locking (ATS/SCSI reservations) to prevent concurrent access conflicts. When you attempt to unmount, ESXi checks for any active consumers — registered VMs, open VMDKs, swap files, ISO images, HA heartbeats, and SIOC configurations. If any of these exist on any host in the cluster, the unmount is blocked. A common scenario is forgetting to Storage vMotion a powered-off VM's config files or removing HA heartbeat assignment before decommissioning.
Check for active VMs and open files on the datastore
# List all files open on the datastore:
esxcli storage filesystem list | grep -i datastore1
# Check for registered VMs on this datastore:
vim-cmd vmsvc/getallvms | grep "datastore1"
# Check for active VMDK locks:
vmkfstools -D /vmfs/volumes/datastore1/vm/vm.vmdk
Verify HA heartbeat and SIOC status
# Check if datastore is an HA heartbeat volume:
# vSphere Client → Cluster → Configure → vSphere Availability
# → Heartbeat Datastores — remove the target datastore
# Check Storage I/O Control:
esxcli storage filesystem list
# Look for "Mounted: true" and usage indicators
Unmount and detach from all hosts
# Step 1: Unmount the VMFS filesystem:
esxcli storage filesystem unmount -l datastore1
# Step 2: Detach the underlying device (LUN):
esxcli storage core device set --state=off -d naa.xxxxxxxxxxxx
# Verify unmount succeeded:
esxcli storage filesystem list | grep datastore1
# Should return empty or show "Mounted: false"
ScsiDeviceIO: ... APD TimeoutPermanent device loss ... sense key 0x5APD (All Paths Down) is a temporary condition — ESXi loses all paths to a storage device but the device has not reported permanent loss. ESXi retries I/O for 140 seconds (APD timeout), during which VMs are stunned (completely frozen). If paths recover within 140s, VMs resume. If not, VMs may be killed or restarted by HA VMCP.
PDL (Permanent Device Loss) is an immediate, non-recoverable condition — the storage array explicitly reports the LUN is gone (SCSI sense code). VMs receive I/O errors immediately and will crash. There is no retry period for PDL.
Identify APD / PDL state on the device
# Check device path state:
esxcli storage core device list | grep -A 5 "naa.xxxx"
# Look for: "Status: dead" (PDL) or "Status: dead-timeout" (APD)
# Check path status for all devices:
esxcli storage core path list | grep -i "state\|device"
# Review vmkernel log for APD/PDL events:
grep -i "APD\|PDL\|permanent device loss\|all paths down" /var/log/vmkernel.log | tail -30
Check and configure APD timeout and VMCP
# Check current APD timeout (default 140 seconds):
esxcli system settings advanced list -o /Misc/APDTimeout
# Configure HA VMCP (VM Component Protection):
# vSphere Client → Cluster → Configure → vSphere Availability
# → Failure Conditions → Datastore with APD:
# Response: "Power off and restart VMs" (aggressive) or "Issue events" (conservative)
# → Datastore with PDL:
# Response: "Power off and restart VMs" (recommended)
# Verify VMCP is enabled:
esxcli system settings advanced list -o /das/ | grep -i vmcp
Recover VMs after APD/PDL event
# If storage has recovered, rescan all HBAs:
esxcli storage core adapter rescan --all
# Verify device is back online:
esxcli storage core device list -d naa.xxxx | grep Status
# Should show: "Status: on"
# If VMs are still stunned, answer the VM question:
# vSphere Client → VM → Monitor → Questions
# Or power cycle the VM:
vim-cmd vmsvc/power.off <vmid>
vim-cmd vmsvc/power.on <vmid>
vmkernel.log during normal operationCheck current multipathing configuration per device
# List all devices with their current PSP and SATP:
esxcli storage nmp device list
# Check a specific device:
esxcli storage nmp device list -d naa.xxxxxxxxxxxx
# Look for:
# Path Selection Policy: VMW_PSP_RR (Round Robin)
# Storage Array Type Plugin: VMW_SATP_ALUA
# View all paths for a device:
esxcli storage nmp path list -d naa.xxxxxxxxxxxx
Change PSP to Round Robin for active-active arrays
# Set Round Robin on a specific device:
esxcli storage nmp device set -d naa.xxxxxxxxxxxx --psp=VMW_PSP_RR
# Set Round Robin IOPS (switch path after N I/Os):
esxcli storage nmp psp roundrobin deviceconfig set \
-d naa.xxxxxxxxxxxx --iops=1 --type=iops
# IOPS=1: best for latency-sensitive workloads (databases)
# IOPS=1000: best for throughput-heavy workloads (backup, bulk I/O)
# Create a SATP claim rule to auto-apply RR for your array vendor:
esxcli storage nmp satp rule add -s VMW_SATP_ALUA \
-P VMW_PSP_RR -V "VENDOR" -M "MODEL" \
-O "iops=1" -e "Custom RR rule for VENDOR array"
Verify path distribution and performance
# Verify Round Robin is active and paths are distributing:
esxcli storage nmp path list -d naa.xxxxxxxxxxxx
# All paths should show "State: active"
# Use esxtop to verify I/O distribution across paths:
# esxtop → press 'u' for device view
# Check CMDS/s per path — should be roughly equal with RR
# Rescan to apply changes:
esxcli storage core adapter rescan --all
NFS: ... server not respondingESXi connects to NFS datastores over standard TCP/IP networking. Unlike block storage (FC/iSCSI), NFS has no multipathing built into the protocol — it depends entirely on the network layer. When the NFS server becomes unreachable (network partition, server crash, firewall change), ESXi enters a retry loop. VMs are stunned for the duration of the retry. If the VMkernel port used for NFS traffic is misconfigured (wrong VLAN, no IP, or missing NFS traffic type tag), the mount silently fails or operates over a suboptimal path.
Verify NFS mount status and network connectivity
# List all NFS datastores and their status:
esxcli storage nfs list
# Check: Share, Host (NFS server IP), Accessible (true/false)
# Test network connectivity to NFS server:
vmkping -I vmk1 192.168.10.50
# Use the VMkernel interface tagged for NFS traffic
# Check for NFS errors in vmkernel log:
grep -i "NFS\|nfs" /var/log/vmkernel.log | tail -30
Verify VMkernel NFS traffic tag and NFS server exports
# Check VMkernel adapter services (ensure NFS traffic is tagged):
esxcli network ip interface tag get -i vmk1
# Should include "NFS" in enabled services
# On the NFS server, verify exports allow ESXi host:
# Linux NFS: cat /etc/exports
# Example: /nfs_datastore 192.168.10.0/24(rw,no_root_squash,sync)
# Check current NFS mount count vs. limit:
esxcli storage nfs list | wc -l
# Max NFS mounts per ESXi host: 256 (NFS 3) / 256 (NFS 4.1)
Remount NFS datastore and tune timeouts
# Remount an inaccessible NFS datastore:
esxcli storage nfs remove -v NFS_Datastore1
esxcli storage nfs add -H 192.168.10.50 -s /nfs_datastore -v NFS_Datastore1
# Tune NFS heartbeat and timeout settings:
esxcli system settings advanced list -o /NFS/HeartbeatFrequency
# Default: 12 seconds — increase for unstable networks
esxcli system settings advanced set -o /NFS/HeartbeatTimeout -i 5
esxcli system settings advanced set -o /NFS/HeartbeatMaxFailures -i 10
Heap vmfs3 already at its maximum sizeESXi allocates a fixed kernel memory region (the VMFS heap) to track all open files, locks, and metadata on VMFS datastores. Each open VMDK, snapshot delta, descriptor file, and lock file consumes heap memory. When you pack many VMs (especially with snapshots) onto VMFS datastores, the heap can be exhausted. Once the heap is full, ESXi cannot open any new files on any VMFS datastore — VMs fail to power on, snapshots fail, and even running VMs may lose disk connectivity.
Check VMFS heap usage and configuration
# Check current VMFS heap size and maximum:
esxcli system settings advanced list -o /VMFS3/MaxHeapSizeMB
# Default: 640 MB (ESXi 7.x), 256 MB (ESXi 6.x)
# Check heap usage via vsish (advanced):
vsish -e get /system/heaps/vmfs3-*/stats
# Look for: "Current heap size" vs "Max heap size"
# Count open files per datastore:
find /vmfs/volumes/datastore1/ -name "*.vmdk" | wc -l
find /vmfs/volumes/datastore1/ -name "*.lck" -type d | wc -l
Reduce heap consumption — consolidate and clean up
# Consolidate all VM snapshots (reduces delta disk count):
# vSphere Client → VM → Snapshots → Delete All
# PowerCLI — find VMs with snapshots on the host:
Get-VM -Location (Get-VMHost esxi01.local) |
Get-Snapshot | Select VM, Name, SizeMB, Created |
Sort-Object SizeMB -Descending | Format-Table -AutoSize
# Remove orphaned lock files (ONLY if VM is confirmed off):
# find /vmfs/volumes/datastore1/vmname/ -name "*.lck" -type d
# rm -rf /vmfs/volumes/datastore1/vmname/*.lck # CAUTION!
Increase VMFS heap (temporary) and redistribute VMs
# Increase VMFS heap max (requires reboot):
esxcli system settings advanced set -o /VMFS3/MaxHeapSizeMB -i 768
# Long-term: redistribute VMs across more datastores
# Use Storage vMotion to spread VMs:
# PowerCLI:
Get-VM "vm-name" | Move-VM -Datastore "datastore2"
# Monitor heap after changes:
esxcli system settings advanced list -o /VMFS3/MaxHeapSizeMB
relocate disk ... failed or No space left on deviceStorage vMotion copies VMDK data from source to target datastore while the VM is running. It uses a mirror driver that writes to both source and target simultaneously, then switches. If the target datastore runs out of space (thin-to-thick conversion, snapshot growth), the mirror fails. If CBT is corrupted, the incremental copy logic fails. Snapshots add complexity because each delta disk must also be migrated, and active snapshots continue growing during the copy, creating a race condition.
Pre-flight checks before Storage vMotion
# Check target datastore free space:
esxcli storage filesystem list | grep target_datastore
# Ensure free space > 2x the VMDK size (for thin provisioned)
# Check VM snapshot state — consolidate first:
vim-cmd vmsvc/snapshot.get <vmid>
# If snapshots exist, consolidate before migrating:
vim-cmd vmsvc/snapshot.removeall <vmid>
# Check for file locks on VMDK:
vmkfstools -D /vmfs/volumes/source_ds/vm/vm-flat.vmdk
Fix CBT issues and clean up orphaned files
# Reset CBT on the VM (requires stun — brief pause):
# PowerCLI:
$vm = Get-VM "vm-name"
$spec = New-Object VMware.Vim.VirtualMachineConfigSpec
$spec.ChangeTrackingEnabled = $false
$vm.ExtensionData.ReconfigVM($spec)
# Power cycle or create+delete snapshot to apply
$spec.ChangeTrackingEnabled = $true
$vm.ExtensionData.ReconfigVM($spec)
# Clean up orphaned VMDKs on target (verify not in use first):
# ls -la /vmfs/volumes/target_ds/vm-name/
# Remove only files confirmed as orphaned partial copies
Retry Storage vMotion with best practices
# Use PowerCLI for more control over migration:
Get-VM "vm-name" | Move-VM -Datastore "target_ds" `
-DiskStorageFormat Thin -VMotionPriority High
# For large VMs, consider migrating disks individually:
$vm = Get-VM "vm-name"
$disk = Get-HardDisk -VM $vm -Name "Hard disk 1"
Move-HardDisk -HardDisk $disk -Datastore "target_ds" `
-StorageFormat Thin
# Monitor migration progress:
Get-Task | Where { $_.Name -eq "RelocateVM_Task" } |
Select Name, PercentComplete, State
fstrim (Linux) or Optimize-Volume (Windows)Check UNMAP support and current status
# Check if VMFS datastore supports UNMAP:
esxcli storage vmfs unmap get -l datastore1
# Look for: "Reclaim Priority" and "Reclaim Granularity"
# Verify VAAI UNMAP support on the device:
esxcli storage core device vaai status get -d naa.xxxxxxxxxxxx
# "Delete Status: supported" = UNMAP is supported
# Check VMFS version (UNMAP auto only on VMFS 6):
esxcli storage filesystem list | grep datastore1
# VMFS 6.x = automated UNMAP supported
Enable and configure automated UNMAP (VMFS 6)
# Set automated UNMAP priority on VMFS 6 datastore:
esxcli storage vmfs unmap set -l datastore1 -n low
# Options: none, low (default), medium, high
# "low" = minimal I/O impact, reclaims slowly
# "high" = faster reclaim but more I/O overhead
# Run manual UNMAP on VMFS 5 or for immediate reclaim:
esxcli storage vmfs unmap -l datastore1
# This scans all free blocks and sends UNMAP to the array
# For VMFS 5, use the legacy reclaim command:
esxcli storage vmfs unmap --volume-label=datastore1 \
--reclaim-unit=200
Guest-level space reclamation and verification
# Linux guest — trim deleted blocks (passes UNMAP to VMDK):
sudo fstrim -av
# Windows guest — optimize and trim:
Optimize-Volume -DriveLetter C -ReTrim -Verbose
# Verify space was reclaimed on the array:
# Check storage array management console for LUN utilization
# vSphere: Datastore → Monitor → Capacity
# Array-side thin pool utilization should decrease
# Enable automatic guest TRIM passthrough (VM setting):
# VM → Edit Settings → VM Options → Advanced → Configuration Parameters
# disk.EnableUUID = TRUE (for consistent device naming)
CHAP authentication failedDiagnose iSCSI adapter and connectivity
# List iSCSI adapters:
esxcli iscsi adapter list
# Should show vmhba6x (software iSCSI) as "Online"
# Check discovery targets:
esxcli iscsi adapter discovery sendtarget list -A vmhba65
# Verify target IP and port (default: 3260)
# Add a discovery target:
esxcli iscsi adapter discovery sendtarget add \
-A vmhba65 -a 192.168.20.100:3260
# Add a static target:
esxcli iscsi adapter target portal add \
-A vmhba65 -a 192.168.20.100 -n iqn.2024.com.storage:lun01
# Verify CHAP authentication settings:
esxcli iscsi adapter auth chap get -A vmhba65
Diagnose FC HBA link status and zoning
# List FC HBAs and their status:
esxcli storage san fc list
# Check: PortState (Online), Speed (16/32 Gbps), NodeWWN, PortWWN
# If link is down, check physical connections:
# - SFP seated properly
# - Fiber cable connected to correct switch port
# - Switch port enabled and in correct VSAN/zone
# Verify FC targets visible to the HBA:
esxcli storage san fc list -A vmhba2
# Target list should show storage array controller WWPNs
# Check zoning on the FC switch:
# Brocade: zoneshow
# Cisco MDS: show zone active
Rescan and verify LUN visibility
# Rescan all storage adapters:
esxcli storage core adapter rescan --all
# Rescan a specific adapter:
esxcli storage core adapter rescan -A vmhba65
# Verify LUNs are now visible:
esxcli storage core device list | grep -c "naa\."
# Compare count across all cluster hosts — should be equal
# Check VMFS volumes discovered:
esxcli storage filesystem list
# PowerCLI — rescan all hosts in cluster:
Get-Cluster "ClusterName" | Get-VMHost |
Get-VMHostStorage -RescanAllHba -RescanVmfs
SCSI reservation conflictsCheck VAAI support status per device
# Check VAAI status for a specific device:
esxcli storage core device vaai status get -d naa.xxxxxxxxxxxx
# Expected output:
# ATS Status: supported
# Clone Status: supported
# Zero Status: supported
# Delete Status: supported
# Check all devices at once:
esxcli storage core device vaai status get
# Any "unsupported" = that primitive is not offloaded
# Verify VAAI is enabled globally:
esxcli system settings advanced list -o /VMFS3/HardwareAcceleratedLocking
esxcli system settings advanced list -o /DataMover/HardwareAcceleratedMove
esxcli system settings advanced list -o /DataMover/HardwareAcceleratedInit
Enable VAAI primitives if disabled
# Enable Hardware Accelerated Locking (ATS):
esxcli system settings advanced set \
-o /VMFS3/HardwareAcceleratedLocking -i 1
# Enable Hardware Accelerated Move (XCOPY/Clone):
esxcli system settings advanced set \
-o /DataMover/HardwareAcceleratedMove -i 1
# Enable Hardware Accelerated Init (Zero/Write Same):
esxcli system settings advanced set \
-o /DataMover/HardwareAcceleratedInit -i 1
# These are enabled by default (value=1)
# If set to 0, VAAI was explicitly disabled — investigate why
Verify VAAI is being used during operations
# Clone a VM and monitor VAAI usage in vmkernel log:
grep -i "vaai\|xcopy\|ATS\|WriteSame" /var/log/vmkernel.log | tail -20
# During clone, check esxtop for offload indicators:
# esxtop → press 'u' for device view
# APTS/s (ATS operations/sec) > 0 = ATS working
# MBWR/s should be low if XCOPY is offloading the copy
# Test VAAI with a quick thick eager zero disk create:
vmkfstools -c 10G -d eagerzeroedthick \
/vmfs/volumes/datastore1/test/test.vmdk
# With VAAI: completes in seconds
# Without VAAI: takes minutes (block-by-block zeroing)
Check SDRS configuration and automation level
# vSphere Client → Datastore Cluster → Configure → SDRS
# Verify:
# SDRS Automation: "Fully Automated" (not "Manual" or "No automation")
# Space Utilization Threshold: 80% (default)
# I/O Latency Threshold: 15ms (default)
# I/O Metric: Enabled (required for I/O-based balancing)
# PowerCLI — check SDRS settings:
Get-DatastoreCluster | Select Name,
@{N='SDRSAutomation';E={$_.SdrsAutomationLevel}},
@{N='IOLatencyThreshold';E={$_.IOLatencyThresholdMillisecond}},
@{N='SpaceThreshold';E={$_.SpaceUtilizationThresholdPercent}},
@{N='IOMetric';E={$_.IOLoadBalanceEnabled}} |
Format-Table -AutoSize
Check affinity rules and SDRS faults
# Check SDRS VM anti-affinity rules:
# Datastore Cluster → Configure → Rules
# Rules keeping VM disks together or apart may block migrations
# PowerCLI — list SDRS rules:
Get-DatastoreCluster "DS-Cluster-01" |
Get-SdrsRule | Select Name, Enabled, RuleType, VM |
Format-Table -AutoSize
# Check SDRS recommendations and faults:
# Datastore Cluster → Monitor → SDRS → Recommendations
# Look for faulted recommendations — hover for details
# Check SDRS history:
# Datastore Cluster → Monitor → SDRS → History
# Verify migrations are happening (or why they're blocked)
Tune SDRS thresholds and enable full automation
# PowerCLI — set SDRS to fully automated:
Set-DatastoreCluster "DS-Cluster-01" `
-SdrsAutomationLevel FullyAutomated
# Adjust space threshold (trigger migration at 75%):
Set-DatastoreCluster "DS-Cluster-01" `
-SpaceUtilizationThresholdPercent 75
# Enable I/O load balancing:
Set-DatastoreCluster "DS-Cluster-01" `
-IOLoadBalanceEnabled $true `
-IOLatencyThresholdMillisecond 10
# Set SDRS invocation schedule (default: every 8 hours):
# Datastore Cluster → Configure → SDRS → Runtime Settings
# Reduce to 4 hours for more responsive balancing