When the virtual disk becomes a bottleneck
Last month I completed a full storage layer review across our VMware vSphere 8.0 cluster. The trigger was a handful of database VMs (MySQL, PostgreSQL) consistently reporting abnormally high I/O wait — CPU ready time looked fine, RAM wasn’t the issue, but disk throughput was only hitting around 60–70% of the SAN’s theoretical benchmark.
After systematically ruling out other factors — datastore, HBA driver, RAID policy — I discovered that all of those VMs were using the LSI Logic SAS adapter, the default when creating a new VM in vSphere. This is a fully emulated hardware adapter, and that was the root cause.
Switching to PVSCSI (Paravirtual SCSI) resolved most of the problem. CPU I/O processing dropped noticeably, and throughput climbed up to where it should have been all along. This post documents that process — from the technical reasoning to the implementation steps and measured results.
How PVSCSI differs from LSI Logic
LSI Logic SAS/BusLogic is an emulated adapter: the VMkernel must simulate the complete behavior of a real physical device. Every I/O command from the guest OS passes through a full emulation layer with significant overhead — interrupt simulation, register emulation, and virtual DMA mapping. The guest OS requires no special driver because it “thinks” it’s talking to real hardware.
PVSCSI is a paravirtualized adapter: the guest OS knows it’s running on VMware and uses a purpose-built driver to communicate directly with the VMkernel through an optimized protocol. There is no emulation layer. I/O requests go straight into the VMkernel, dramatically reducing the CPU cycles consumed.
According to VMware’s published benchmarks, under heavy I/O workloads:
- CPU overhead reduced by approximately 30–50% for I/O-intensive workloads
- Throughput increases up to 20–30% for sequential read/write
- Random 4K IOPS improves 20–40% for database workloads depending on storage configuration
That said, PVSCSI doesn’t always show a clear advantage. For low-I/O VMs like static web servers or dev/test environments, the difference is barely noticeable. PVSCSI really shines under heavy workloads: database servers, file servers, and VMs running continuous CI/CD build pipelines.
Prerequisites for using PVSCSI
- VMware vSphere 4.0 or later (or VMware Workstation 6.5+)
- Guest OS: RHEL/CentOS 5+, Ubuntu 10.04+, Windows Server 2003 SP2+ (with VMware Tools), Windows Vista+ (driver built-in)
- VMware Tools must be installed and up to date
- Important note: Some older OSes such as Windows Server 2003 and RHEL 4 do not include a PVSCSI driver in their boot image — driver injection is required if using PVSCSI as the boot disk
Configuring PVSCSI — Step-by-Step
Option 1: Change the adapter via vSphere Client (GUI)
This is the fastest approach for one or two VMs. The VM must be fully Powered Off (not Suspended).
- Right-click the VM → Edit Settings
- Click on SCSI Controller 0 (or the current adapter)
- Open the Change Type dropdown → select VMware Paravirtual
- Click OK → Power On the VM
After booting, open Device Manager on Windows and look for “VMware PVSCSI Controller” to confirm the driver loaded correctly. On Linux, lsmod | grep vmw_pvscsi is sufficient.
Option 2: Use PowerCLI to change adapters in bulk
Doing this manually for 10+ VMs would eat up an entire afternoon. PowerCLI handles it in minutes:
# Connect to vCenter
Connect-VIServer -Server vcenter.yourdomain.com
# Get the list of VMs to update (e.g., all VMs in the "Production-DB" folder)
$vms = Get-VM -Location (Get-Folder "Production-DB")
foreach ($vm in $vms) {
# Skip VMs that are still running
if ($vm.PowerState -ne "PoweredOff") {
Write-Warning "$($vm.Name) is powered on, skipping..."
continue
}
# Get SCSI controllers that are not already PVSCSI
$scsiCtrl = Get-ScsiController -VM $vm | Where-Object { $_.Type -ne "ParaVirtualSCSI" }
if ($scsiCtrl) {
Write-Host "Changing SCSI adapter for $($vm.Name)..."
Set-ScsiController -ScsiController $scsiCtrl -Type ParaVirtualSCSI
Write-Host " Done: $($vm.Name)" -ForegroundColor Green
} else {
Write-Host "$($vm.Name) already uses PVSCSI, skipping." -ForegroundColor Cyan
}
}
Disconnect-VIServer -Confirm:$false
A practical tip: don’t power everything on at once. Work in batches of 3–5 VMs, verify the logs and disk performance before moving to the next batch — if there’s a driver issue, you’ll catch it immediately and only need to roll back a small group rather than a dozen VMs simultaneously.
Option 3: Edit the .vmx file directly (VMware Workstation / Fusion)
# Find the .vmx file for the VM
find ~/vmware -name "*.vmx" | grep "VMName"
# Open the file and find the scsi0.virtualDev line, change from:
# scsi0.virtualDev = "lsisas1068"
# To:
# scsi0.virtualDev = "pvscsi"
sed -i 's/scsi0.virtualDev = "lsisas1068"/scsi0.virtualDev = "pvscsi"/' /path/to/vm.vmx
Then open VMware Workstation and power on the VM as normal.
Post-change verification — on a Linux guest
# Check whether the PVSCSI driver is loaded
lsmod | grep vmw_pvscsi
# vmw_pvscsi 36864 4
# View disk controller information
lspci | grep -i scsi
# VMware PVSCSI SCSI Controller
# Run a basic disk speed test with dd
dd if=/dev/zero of=/tmp/test_io bs=1M count=1024 oflag=direct
# 1073741824 bytes (1.1 GB) copied, 2.84 s, 378 MB/s
Real-world benchmarks with fio
For more accurate measurements, I used fio — the standard I/O benchmarking tool:
# Install fio
apt install fio # Ubuntu/Debian
yum install fio # CentOS/RHEL
# Test 1: Sequential write (simulates log writing, backups)
fio --name=seq-write \
--ioengine=libaio \
--rw=write \
--bs=1M \
--numjobs=4 \
--size=2G \
--runtime=60 \
--group_reporting \
--filename=/tmp/fio_test
# Test 2: Random 4K read (simulates database IOPS)
fio --name=rand-read \
--ioengine=libaio \
--rw=randread \
--bs=4k \
--iodepth=64 \
--numjobs=4 \
--size=2G \
--runtime=60 \
--group_reporting \
--filename=/tmp/fio_test
Actual comparison results from a PostgreSQL VM (vSphere 8.0, NVMe datastore):
- LSI Logic SAS: Random 4K Read ~85K IOPS, CPU I/O wait ~12%
- PVSCSI: Random 4K Read ~118K IOPS, CPU I/O wait ~6%
CPU wait dropped from 12% down to 6% — that was the most striking result for me. Half of those CPU cycles were previously being held hostage waiting on I/O. With that headroom freed up, PostgreSQL had more room to process actual queries.
A Proxmox perspective — to understand PVSCSI more deeply
When migrating from VMware to Proxmox for my personal lab, I noticed a number of interesting parallels. Proxmox uses VirtIO SCSI as its paravirtual adapter instead of PVSCSI — same concept, different implementation. On Proxmox, if you don’t enable VirtIO, disk performance suffers just as badly as VMware does with the emulated LSI Logic adapter.
The takeaway: paravirtualization isn’t a “VMware-exclusive feature” — it’s an I/O optimization architecture that every serious hypervisor must implement. VMware calls it PVSCSI, KVM/Proxmox calls it VirtIO — the underlying principle is identical, and both solve the same emulation overhead problem.
When you should NOT switch to PVSCSI
- Boot disk on older OSes without a built-in driver: Windows Server 2003 and RHEL 4 require injecting the PVSCSI driver into WinPE or initramfs before changing the boot disk. If you’re not comfortable with that process, keep LSI Logic for the boot disk and only switch data disks to PVSCSI.
- Low-I/O dev/test VMs: It’s not worth the downtime to swap the adapter on a VM that only runs a static web server or a lightweight dev environment.
- No maintenance window available: Changing the SCSI adapter requires a full VM Power Off. Plan the window carefully and communicate it in advance.
Conclusion
What I appreciate most about PVSCSI is this: no new hardware, no additional licenses — just knowing the option exists and flipping a single setting. Yet plenty of production environments are still running LSI Logic simply because “that’s what was set by default and nobody changed it.”
If you’re managing a VMware cluster with I/O-heavy workloads — database servers, build servers, NFS servers running inside VMs — auditing your SCSI adapter type should be at the top of your to-do list. Downtime is just a few minutes per VM, but the improvement shows up immediately on your monitoring dashboard.
One final tip: after switching to PVSCSI, also review the queue depth. PVSCSI defaults to a much higher queue depth than LSI Logic (256 vs. 32 per device). If your datastore has its own limits, you may need to tune the Disk.SchedNumReqOutstanding parameter on the ESXi host to avoid queue saturation and ensure other VMs sharing the same datastore aren’t negatively impacted.

