File Sharing with Qemu and Virt-Manager

I’ve been using qemu and libvirt to create and manage virtual machines under Linux. I’m using Virtual Machine Manager to graphically manage the machines. I’ve been really impressed with qemu + KVM performanace, and Virt-Manager provides a very nice and easy to use interface. There is just one thing lacking, in comparison to “traditional” desktop virtualization software (eg. Virtualbox): there is no pre-configured way to share files between the host and the guest. In contrast, Virtualbox provides a really easy way to transfer files. As long as the agent is installed you can just “copy and paste” them over, or drag them into the VM from the host (and vice versa). In this article, I’ll try to configure an easy way to share files between the host and the VM. My host is an ArchLinux system, and the two guests are Fedora 35 and Windows 10. The steps in this article should be generic enough to “just work” on most other distros, but YMMV.

NB: This is intended as an easy way to share files for classic “desktop” virtualization settings. It’s not intended for servers, where there are multiple users on the host or the guests.

We’ll be using the same method for both guests, because it works on Linux and on Windows. Instead of the “traditional” way (sharing over the network with SMB, NFS, or 9p), we’ll we using a file system developed by libvirt called virtiofs. Virtiofs was developed for precisely this purpose (“Unlike existing approaches, it is designed to offer local file system semantics and performance.”). This makes file sharing easier to configure, since we don’t need to set up a server. It also should offer very good performance.

Host

To set this up, we first need a folder on the host. This can be done in several ways. I decided to just create a folder in /mnt, and change its ownership to my user:

sudo mkdir /mnt/vfs_share
sudo chown foo:foo /mnt/vfs_share

Then we need to add a virtiofs device.

Virtiofs needs shared memory to work. This can be enabled in the hardware configuration window. Navigate to Hardware -> Memory and select Enable shared memory.

After that, open virt-manager and navigate to the hardware settings of the virtual machine. Click on Add Hardware.

The virt-manager hardware window. The left pane contains the different categories. The right pane contains the setting for the specific category. Beneath the categore pane, there is a button called 'Add Hardware'

Virtual Machine Manager hardware configuration window.

A dialog box should pop up. In the pane on the left, click on Filesystem

The 'Add Hardware dialog'. The left pane contains a list of hardware devices that can be added. The option 'Filesystem' is selected.

The ‘Add Hardware’ dialog window

Enter the necessary settings.

The same window, with the apprioprate settings.

Filesystem options

The settings are as follows:

For the Driver, we keep the default (virtiofs). The source path is the path on our host filesystem. The target path is a bit of a misnomer. It’s not actually a path, just an identifier that we use as a mount point in our guest file system. This will become clear when we mount the file system in the guest later.

If you want a more detailed overview of these options and some alternatives, check out the libvirt knowledge base on virtiofs

Guest

Linux

After that, it’s time to configure the guest. First we create a folder in our users home directory that we will mount the share into.

mkdir ~/share

After that, we can mount the share with:

sudo mount -t virtiofs share /home/foo/share

If we want to make this permanent, we can just add an entry to /etc/fstab

share   /home/foo/share       virtiofs        defaults        0       0

After rebooting, the share should be mounted! If your user on the host and the guest are the same, you don’t even need to worry about any other permissions. Otherwise, change the folder with chmod to suit your needs.

Windows 10

Windows 10 can also use virtiofs, but it needs some additional work. First, we need to install 2 pieces of software:

This installation can be done in two ways: manually or with chocolatey.

Chocolatey

If you already have Chocolatey installed, it’s as simple as:

choco install virtio-drivers winfsp

If you don’t have Chocolatey installed, I highly recommend that you check it out. It’s a package manager for Windows that integrates quite well into the system. It makes maintaining software on Windows a lot easier! Installation instructions are here.

During the installation of the virtio-drivers it will pop up a dialog box asking if you trust the drivers. Confirm the dialog box to install them.

Manual install

Download WinFSP here and install it. The default options are fine if you just want to use the drivers.

After that, you need to download the latest ISO from the following archive. After downloading, mount the ISO. Then open Device Manager. Select the appropriate device. It should appear under Other devices as a Mass storage controller

A view of the device manager.

Device Manager

Right-click on the device and select Update driver. From that menu, select Browse my computer for drivers. Browse to the location of the ISO, and select the directory of the drivers.

Configuration

After that, it’s a good idea to create a service for the drivers, so they are automatically loaded during system startup.

sc.exe create VirtioFsSvc binpath="C:\ProgramData\Chocolatey\bin\virtiofs.exe" start=auto depend="WinFsp.Launcher/VirtioFsDrv" DisplayName="Virtio FS Service"
sc.exe start VirtioFsSvc

If you’ve installed manually, find the location of the .exe and change the binpath.

Benchmarks

All Benchmarks were done on a Dell Latitude 5401 with the following specs:

Name Value
CPU Intel i5-9400H (8) @ 4.300GHz
GPU Intel CoffeeLake-H GT2 [UHD Graphics 630]
Memory 16 GB DDR4
Storage 512 GB NVMe

Linux

For the benchmark, I simply copied over a 10 GB file with cp, measuring it with time. That gave me the following result:

real    0m12.532s
user    0m0.002s
sys     0m5.785s

I also transferred the same file with rsync, to get a progress bar. That way I could get a feel for the approximate speed of the transfer. The transfer speed was around 250-300 MB/s consistently.

Windows

On Windows, I also copied the file in 2 ways. First using the windows File transfer dialog. I got up speeds of about 550-700 MB/s. After that, I tried the same using robocopy (A Microsoft tool for robust file copying).

-------------------------------------------------------------------------------
   ROBOCOPY     ::     Robust File Copy for Windows
-------------------------------------------------------------------------------

  Started : Friday, 11 March 2022 10:23:20
   Source : C:\Users\foo\Downloads\
     Dest = Z:\

    Files : *.*

  Options : *.* /DCOPY:DA /COPY:DAT /R:1000000 /W:30

------------------------------------------------------------------------------

                           1    C:\Users\foo\Downloads
100%        New File              10.0 g        10gig.img

------------------------------------------------------------------------------

               Total    Copied   Skipped  Mismatch    FAILED    Extras
    Dirs :         1         0         1         0         0         0
   Files :         1         1         0         0         0         2
   Bytes :  10.000 g  10.000 g         0         0         0   797.0 k
   Times :   0:00:18   0:00:18                       0:00:00   0:00:00


   Speed :           566020993 Bytes/sec.
   Speed :           32387.981 MegaBytes/min.
   Ended : Friday, 11 March 2022 10:23:39

Here we end up with roughly the same speed as the windows file dialog.

Conclusion

I’m very pleased with these results. The process of setting it up is quite easy (although not as “seamless” as the solutions Virtualbox and VMWare provide). The performance seems fantastic, at first glance. For now, I’m very happy with it. I will be testing this further. If I hit any snags or discover something else that’s interesting, I’ll let you know.


Articles from blogs I read - Generated by openring