How to Directly Map USB Storage Device as Raw Disk in Libvirt KVM Virtual Machine


2 views

When working with KVM virtualization, there are multiple ways to expose physical storage devices to guest VMs. While most documentation focuses on creating storage pools or virtual disk images, direct device mapping is less commonly documented but equally powerful for specific use cases.

Before proceeding, ensure:

1. The USB device is properly connected and recognized by the host (check with lsblk)
2. You have appropriate permissions (typically root/sudo access)
3. The device isn't currently mounted on the host
4. Libvirt and KVM are properly installed

The most reliable approach is to define the device in your VM's XML configuration. Here's a complete example:

<disk type='block' device='disk'>
  <driver name='qemu' type='raw'/>
  <source dev='/dev/sdc1'/>
  <target dev='vdb' bus='virtio'/>
</disk>

Key elements explained:

  • type='block': Specifies we're using a physical block device
  • device='disk': Treats it as a regular disk (not CDROM etc.)
  • driver type='raw': Essential for direct device access
  • source dev: Points to the actual device path

For temporary access without VM restart, use virsh attach-device:

virsh attach-device myvm usb_device.xml --persistent

Where usb_device.xml contains:

<hostdev mode='subsystem' type='usb'>
  <source>
    <vendor id='0x1234'/>
    <product id='0x5678'/>
  </source>
</hostdev>

Permission Errors: Ensure the libvirt-qemu user has access to the device:

chown root:libvirt /dev/sdc1
chmod 660 /dev/sdc1

Device Busy: Unmount the device first:

umount /dev/sdc1

Remember that direct device access:

  • Bypasses host filesystem permissions
  • May expose the host to malicious guest actions
  • Should be used cautiously in multi-tenant environments

When working with KVM virtualization, directly mapping USB storage devices to VMs requires careful configuration. Unlike file-based storage backends, USB passthrough involves device-level access which presents unique challenges.

The most straightforward approach is defining the USB device as a disk in your domain XML:


<disk type='block' device='disk'>
  <driver name='qemu' type='raw'/>
  <source dev='/dev/sdX'/>
  <target dev='vdb' bus='virtio'/>
</disk>

Key considerations:

  • Replace /dev/sdX with your actual device (e.g., /dev/sdc1)
  • Use lsblk to identify the correct device path
  • The VM must have permissions to access the raw device

For persistent USB device mapping, create a storage pool definition:


<pool type='disk'>
  <name>usb_pool</name>
  <source>
    <device path='/dev/sdX'/>
  </source>
  <target>
    <path>/dev</path>
  </target>
</pool>

Then define the volume in your domain XML:


<disk type='volume' device='disk'>
  <driver name='qemu' type='raw'/>
  <source pool='usb_pool' volume='sdc1'/>
  <target dev='vdb' bus='virtio'/>
</disk>

For advanced scenarios where you need the entire USB controller:


<hostdev mode='subsystem' type='usb'>
  <source>
    <vendor id='0x1234'/>
    <product id='0x5678'/>
  </source>
</hostdev>

Find your USB device IDs with:


lsusb

Permission problems: Ensure the libvirt-qemu user has read/write access to the device:


chown root:libvirt-qemu /dev/sdX
chmod 660 /dev/sdX

Device in use errors: Unmount the device before attaching:


umount /dev/sdX1

Hotplug limitations: Most USB passthrough requires VM restart for changes.

For best performance with USB 3.0 devices:

  • Use virtio-scsi instead of virtio-blk
  • Consider enabling write caching in the guest OS
  • Monitor I/O performance with iostat -x 1