Google Summer of Code logo

GSoC 2025 Final Report

Project Description

This project was carried out as part of Google Summer of Code (GSoC) 2025. Virtiofs is a shared file system that lets virtual machines access a directory tree on the host. Virtiofsd is the user-level host daemon that communicates with the guest VMs and performs I/O operations on the shared directory tree. Before my patches, virtiofsd was performing I/O operations in a blocking manner. Although virtiofsd has a thread pool feature, the max degree of parallelism was limited by the size of the thread pool. This project aims to enable asynchronous request processing by leveraging io_uring and Rust’s async/await.

Preliminaries

This project introduces an entirely new processing path to virtiofsd. Implementing it requires several design decisions, and I first had to become familiar with io_uring.

Prototyping io_uring Usage in Rust

There are several ways to handle io_uring in Rust, ranging from low-level io_uring crate to high-level, async-runtime-integrated crates such as tokio-uring crate and monoio crate. I began by writing small Rust programs that make use of io_uring (see playground repo). In particular, I experimented with three approaches:

  1. Using the high-level tokio-uring crate. [code]
  2. Using the low-level io_uring crate. [code]
  3. Using the low-level io_uring crate together with Rust’s async/await. [code]

Integrating a full-featured runtime with virtiofsd is somewhat tricky, because virtiofsd uses epoll to detect incoming I/O requests from the guest, which is typically employed as the reactor in async runtimes. Therefore, I ultimately adopted a hybrid approach 3:

  1. Issue I/O using low-level crate, and wraps it as a Future.
  2. Use the lightweight runtime smol solely for scheduling Futures.
  3. Manually wait for io_uring I/O completions using epoll, and send the results via a channel.

Design Explorations

Before submitting MR !291, I explored the following in a fork branch.

  1. How to integrate io_uring into virtiofsd
  2. Potential configuration options for io_uring

For the integration, I had to decide where to place the boundary between sync fn and async fn. In the end, I aligned this boundary with the one used in the existing thread pool implementation. Instead of spawning a task onto a thread, in the asynchronous path we spawn the Future onto the async runtime’s executor (i.e., scheduler).

I also investigated several io_uring configurations, including submission queue polling and personality registrations. Personalities in io_uring allow registering credentials that can later be used when performing I/O. This feature is particularly important for virtiofsd, because guest VMs may request operations such as create with specific credentials. In such cases, we must first map the guest’s credentials to host credentials and then perform I/O under those mapped credentials.

Credential handling is not a major issue in the thread pool implementation, since each thread has its own associated credentials, and modifying them does not affect other tasks running on other threads. However, with an async runtime, multiple tasks may run concurrently on the same thread. To avoid credential mix-ups, I used io_uring personalities to ensure safe credentials handling.

This approach is implemented in commits such as Add PersonalityStore and Handle create with io_uring in MR !291.

My Contributions

1. Add Minimal Support for io_uring Asynchronous Request Processing

  • MergeRequest !291 [not merged yet]

Although this MR is still under review, it provides a working implementation. This MR makes rename, read, write and create asynchronous. Rather than replacing the existing implementations, this MR introduces a new flag --io-uring that switches underlying implementations with a fallback to synchronous mode if asynchronous processing for a given operation is not yet supported.

Rough benchmarks showed more than twice the throughput with io_uring enabled compared to the synchronous implementations on SSDs.

2. Fix Clippy Warnings

  • MergeRequest !294 [merged]

This is a small merge request adopts suggestions from newly introduce clippy warning. I noticed CI was failing due to this while working MR !291. I fixed it quickly, and this MR got merged.

Future Work

  • Address all the review comments in !291, and make it merged.
  • Detailed benchmarks to reveal the exact performance differences and the appropriate scenarios.
  • Support more I/O operations for asynchronous I/O processing.

Acknowledgements

I greatly appreciate the dedicated support and guidance from German and Hanna! I had a great time engaging in this interesting project.