fs: skip some io_uring tests on Kernels that don't support it (#8134)

This commit is contained in:
Mattia Pitossi
2026-05-11 13:58:50 +02:00
committed by GitHub
parent ee0dc90926
commit bdcea6b2cd
5 changed files with 73 additions and 14 deletions
@@ -40,6 +40,8 @@ jobs:
make defconfig
make -j$(nproc)
# We are running tests also on a Kernel version that does not support io_uring
# to check if the fallback mechanism works
- name: Generate test binaries with io_uring enabled
run: |
# Build both integration (tokio/tests/) and unit (e.g., tokio/src/fs/file/tests.rs) tests with io_uring enabled
+13 -4
View File
@@ -13,10 +13,21 @@ use std::fs;
use std::future::poll_fn;
use std::task::Poll;
use tempfile::NamedTempFile;
use tokio_test::assert_pending;
use crate::support::io_uring::io_uring_supported;
mod support {
pub(crate) mod io_uring;
}
// see: https://github.com/tokio-rs/tokio/issues/7979
#[tokio::test]
async fn file_descriptors_are_closed_when_cancelling_open_op() {
if !io_uring_supported() {
return;
}
let tmp = NamedTempFile::new().unwrap();
let path = tmp.path().to_path_buf();
@@ -37,10 +48,8 @@ async fn file_descriptors_are_closed_when_cancelling_open_op() {
let fut = opt.open(&path);
// If io_uring is enabled (and not falling back to the thread pool),
// the first poll should return Pending. We don't check if the result
// is actually pending because we run some checks on old kernel that
// do not support uring.
let _pending = Box::pin(fut).poll_unpin(cx);
// the first poll should return Pending.
assert_pending!(Box::pin(fut).poll_unpin(cx));
tx.send(()).unwrap();
@@ -6,6 +6,11 @@
target_os = "linux"
))]
mod support {
pub(crate) mod io_uring;
}
use std::fmt::Debug;
use std::fs;
use std::future::Future;
use std::path::PathBuf;
@@ -16,6 +21,9 @@ use std::time::Duration;
use tempfile::NamedTempFile;
use tokio::sync::mpsc::{unbounded_channel, UnboundedSender};
use tokio::time::timeout;
use tokio_test::assert_pending;
use crate::support::io_uring::io_uring_supported;
/// Count currently-open fds in this process.
fn fd_count() -> usize {
@@ -42,14 +50,17 @@ struct PollOpenOnceThenNeverRepoll<F> {
polled_once: bool,
}
impl<F: Future> Future for PollOpenOnceThenNeverRepoll<F> {
type Output = ();
impl<F: Future> Future for PollOpenOnceThenNeverRepoll<F>
where
F::Output: Debug,
{
type Output = F::Output;
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
if !self.polled_once {
// We don't check if the result is actually pending because
// we run some checks on old kernel that do not support uring.
let _pending = self.inner.as_mut().poll(cx);
// If io_uring is enabled (and not falling back to the thread pool),
// the first poll should return Pending.
assert_pending!(self.inner.as_mut().poll(cx));
self.polled_once = true;
self.first_poll_tx.take().unwrap().send(()).unwrap();
@@ -80,7 +91,7 @@ async fn completed_then_dropped_before_repoll(path: PathBuf) {
second_poll_tx: Some(second_tx),
polled_once: false,
}
.await;
.await
});
// Wait until the inner open has been polled once and registered with io_uring.
@@ -98,6 +109,10 @@ async fn completed_then_dropped_before_repoll(path: PathBuf) {
#[test]
fn uring_completed_then_dropped() {
if !io_uring_supported() {
return;
}
let rt = tokio::runtime::Builder::new_multi_thread()
.worker_threads(1)
.enable_all()
+13 -4
View File
@@ -14,10 +14,21 @@ use std::future::poll_fn;
use std::task::Poll;
use tempfile::NamedTempFile;
use tokio::runtime::Builder;
use tokio_test::assert_pending;
use crate::support::io_uring::io_uring_supported;
mod support {
pub(crate) mod io_uring;
}
// see: https://github.com/tokio-rs/tokio/issues/7979
#[test]
fn shutdown_runtime_while_performing_io_uring_ops() {
if !io_uring_supported() {
return;
}
let tmp = NamedTempFile::new().unwrap();
let path = tmp.path().to_path_buf();
@@ -41,10 +52,8 @@ fn shutdown_runtime_while_performing_io_uring_ops() {
let fut = opt.open(&path);
// If io_uring is enabled (and not falling back to the thread pool),
// the first poll should return Pending. We don't check if the result
// is actually a pending because we run some CI checks based on old
// kernels that don't support uring.
let _pending = Box::pin(fut).poll_unpin(cx);
// the first poll should return Pending.
assert_pending!(Box::pin(fut).poll_unpin(cx));
tx.send(()).unwrap();
+24
View File
@@ -0,0 +1,24 @@
#![cfg(all(
tokio_unstable,
feature = "io-uring",
feature = "rt",
feature = "fs",
target_os = "linux"
))]
use io_uring::IoUring;
// Currently, we are running some of the tests on Kernels where io_uring is not supported
// to check if the fallback mechanism works, this comes with the limitation that we are not
// able to run some checks (e.g., asserting a poll returns pending). This utiliy function
// is useful when we want to run a test only in Linux targets where io_uring is supported.
pub fn io_uring_supported() -> bool {
match IoUring::new(256) {
Ok(_) => true,
// The Kernel does not support io-uring
Err(e) if e.raw_os_error() == Some(libc::ENOSYS) => false,
Err(_) => unreachable!(
"The target should either support io_uring or return ENOSYS if not supported"
),
}
}