mirror of
https://github.com/tokio-rs/tokio.git
synced 2026-08-25 00:00:18 +02:00
io_uring: change Completable to not return io::Result (#7702)
This commit is contained in:
@@ -72,7 +72,9 @@ async fn write_uring(path: &Path, mut buf: OwnedBuf) -> io::Result<()> {
|
|||||||
let mut buf_offset: usize = 0;
|
let mut buf_offset: usize = 0;
|
||||||
let mut file_offset: u64 = 0;
|
let mut file_offset: u64 = 0;
|
||||||
while buf_offset < total {
|
while buf_offset < total {
|
||||||
let (n, _buf, _fd) = Op::write_at(fd, buf, buf_offset, file_offset)?.await?;
|
let (n, _buf, _fd) = Op::write_at(fd, buf, buf_offset, file_offset)?.await;
|
||||||
|
// TODO: handle EINT here
|
||||||
|
let n = n?;
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
return Err(io::ErrorKind::WriteZero.into());
|
return Err(io::ErrorKind::WriteZero.into());
|
||||||
}
|
}
|
||||||
|
|||||||
+16
-10
@@ -1,10 +1,13 @@
|
|||||||
use super::utils::cstr;
|
use super::utils::cstr;
|
||||||
use crate::{
|
|
||||||
fs::UringOpenOptions,
|
use crate::fs::UringOpenOptions;
|
||||||
runtime::driver::op::{CancelData, Cancellable, Completable, CqeResult, Op},
|
use crate::runtime::driver::op::{CancelData, Cancellable, Completable, CqeResult, Op};
|
||||||
};
|
|
||||||
use io_uring::{opcode, types};
|
use io_uring::{opcode, types};
|
||||||
use std::{ffi::CString, io, os::fd::FromRawFd, path::Path};
|
use std::ffi::CString;
|
||||||
|
use std::io::{self, Error};
|
||||||
|
use std::os::fd::FromRawFd;
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) struct Open {
|
pub(crate) struct Open {
|
||||||
@@ -15,11 +18,14 @@ pub(crate) struct Open {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Completable for Open {
|
impl Completable for Open {
|
||||||
type Output = crate::fs::File;
|
type Output = io::Result<crate::fs::File>;
|
||||||
fn complete(self, cqe: CqeResult) -> io::Result<Self::Output> {
|
fn complete(self, cqe: CqeResult) -> Self::Output {
|
||||||
let fd = cqe.result? as i32;
|
cqe.result
|
||||||
let file = unsafe { crate::fs::File::from_raw_fd(fd) };
|
.map(|fd| unsafe { crate::fs::File::from_raw_fd(fd as i32) })
|
||||||
Ok(file)
|
}
|
||||||
|
|
||||||
|
fn complete_with_error(self, err: Error) -> Self::Output {
|
||||||
|
Err(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+12
-11
@@ -1,12 +1,9 @@
|
|||||||
use crate::{
|
use crate::runtime::driver::op::{CancelData, Cancellable, Completable, CqeResult, Op};
|
||||||
runtime::driver::op::{CancelData, Cancellable, Completable, CqeResult, Op},
|
use crate::util::as_ref::OwnedBuf;
|
||||||
util::as_ref::OwnedBuf,
|
|
||||||
};
|
|
||||||
use io_uring::{opcode, types};
|
use io_uring::{opcode, types};
|
||||||
use std::{
|
use std::io::{self, Error};
|
||||||
io,
|
use std::os::fd::{AsRawFd, OwnedFd};
|
||||||
os::fd::{AsRawFd, OwnedFd},
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) struct Write {
|
pub(crate) struct Write {
|
||||||
@@ -15,9 +12,13 @@ pub(crate) struct Write {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Completable for Write {
|
impl Completable for Write {
|
||||||
type Output = (u32, OwnedBuf, OwnedFd);
|
type Output = (io::Result<u32>, OwnedBuf, OwnedFd);
|
||||||
fn complete(self, cqe: CqeResult) -> io::Result<Self::Output> {
|
fn complete(self, cqe: CqeResult) -> Self::Output {
|
||||||
Ok((cqe.result?, self.buf, self.fd))
|
(cqe.result, self.buf, self.fd)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn complete_with_error(self, err: Error) -> Self::Output {
|
||||||
|
(Err(err), self.buf, self.fd)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
use crate::io::uring::open::Open;
|
use crate::io::uring::open::Open;
|
||||||
use crate::io::uring::write::Write;
|
use crate::io::uring::write::Write;
|
||||||
use crate::runtime::Handle;
|
use crate::runtime::Handle;
|
||||||
|
|
||||||
use io_uring::cqueue;
|
use io_uring::cqueue;
|
||||||
use io_uring::squeue::Entry;
|
use io_uring::squeue::Entry;
|
||||||
use std::future::Future;
|
use std::future::Future;
|
||||||
|
use std::io::{self, Error};
|
||||||
|
use std::mem;
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
use std::task::Context;
|
use std::task::{Context, Poll, Waker};
|
||||||
use std::task::Poll;
|
|
||||||
use std::task::Waker;
|
|
||||||
use std::{io, mem};
|
|
||||||
|
|
||||||
// This field isn't accessed directly, but it holds cancellation data,
|
// This field isn't accessed directly, but it holds cancellation data,
|
||||||
// so `#[allow(dead_code)]` is needed.
|
// so `#[allow(dead_code)]` is needed.
|
||||||
@@ -110,7 +110,13 @@ impl From<cqueue::Entry> for CqeResult {
|
|||||||
/// A trait that converts a CQE result into a usable value for each operation.
|
/// A trait that converts a CQE result into a usable value for each operation.
|
||||||
pub(crate) trait Completable {
|
pub(crate) trait Completable {
|
||||||
type Output;
|
type Output;
|
||||||
fn complete(self, cqe: CqeResult) -> io::Result<Self::Output>;
|
fn complete(self, cqe: CqeResult) -> Self::Output;
|
||||||
|
|
||||||
|
// This is used when you want to terminate an operation with an error.
|
||||||
|
//
|
||||||
|
// The `Op` type that implements this trait can return the passed error
|
||||||
|
// upstream by embedding it in the `Output`.
|
||||||
|
fn complete_with_error(self, error: Error) -> Self::Output;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Extracts the `CancelData` needed to safely cancel an in-flight io_uring operation.
|
/// Extracts the `CancelData` needed to safely cancel an in-flight io_uring operation.
|
||||||
@@ -121,7 +127,7 @@ pub(crate) trait Cancellable {
|
|||||||
impl<T: Cancellable> Unpin for Op<T> {}
|
impl<T: Cancellable> Unpin for Op<T> {}
|
||||||
|
|
||||||
impl<T: Cancellable + Completable + Send> Future for Op<T> {
|
impl<T: Cancellable + Completable + Send> Future for Op<T> {
|
||||||
type Output = io::Result<T::Output>;
|
type Output = T::Output;
|
||||||
|
|
||||||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||||
let this = self.get_mut();
|
let this = self.get_mut();
|
||||||
@@ -132,9 +138,21 @@ impl<T: Cancellable + Completable + Send> Future for Op<T> {
|
|||||||
State::Initialize(entry_opt) => {
|
State::Initialize(entry_opt) => {
|
||||||
let entry = entry_opt.take().expect("Entry must be present");
|
let entry = entry_opt.take().expect("Entry must be present");
|
||||||
let waker = cx.waker().clone();
|
let waker = cx.waker().clone();
|
||||||
|
|
||||||
// SAFETY: entry is valid for the entire duration of the operation
|
// SAFETY: entry is valid for the entire duration of the operation
|
||||||
let idx = unsafe { driver.register_op(entry, waker)? };
|
match unsafe { driver.register_op(entry, waker) } {
|
||||||
this.state = State::Polled(idx);
|
Ok(idx) => this.state = State::Polled(idx),
|
||||||
|
Err(err) => {
|
||||||
|
let data = this
|
||||||
|
.take_data()
|
||||||
|
.expect("Data must be present on Initialization");
|
||||||
|
|
||||||
|
this.state = State::Complete;
|
||||||
|
|
||||||
|
return Poll::Ready(data.complete_with_error(err));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
Poll::Pending
|
Poll::Pending
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user