Skip to content

fixed descriptor support #222

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
b5fb182
Introduce fd variations: raw and fixed
FrankReh Feb 3, 2023
a57f2ae
Adds the fixed descriptor capability to SharedFd
FrankReh Feb 3, 2023
2d67d61
fuller open fixed support
FrankReh Feb 10, 2023
24b2749
async close fixed support
FrankReh Feb 10, 2023
1baf987
File::read fixed support
FrankReh Feb 10, 2023
c9e9ceb
File::write fixed support
FrankReh Feb 10, 2023
ff699e2
support dropping fixed file table descriptors
FrankReh Feb 11, 2023
9cbca8e
general comment cleanup
FrankReh Feb 11, 2023
297477e
comment idea for fixed slot drop
FrankReh Feb 12, 2023
8f76a1f
Merge branch 'master' into frankreh/fixed-descriptor-support
FrankReh Feb 13, 2023
cbef4d2
Merge branch 'master' into frankreh/fixed-descriptor-support
FrankReh Feb 14, 2023
3debd20
opcode::Close uses Fixed(fd) now
FrankReh Feb 14, 2023
94adb7d
Merge branch 'master' into frankreh/fixed-descriptor-support
FrankReh Feb 20, 2023
b81fce0
bump io-uring dependency to 0.5.13
FrankReh Feb 20, 2023
c80ae28
remove allow(dead_code)
FrankReh Feb 20, 2023
3de2068
remove old commented-out code
FrankReh Feb 20, 2023
2390971
simplify shared_fd::CommonFd
FrankReh Feb 20, 2023
21ef00f
Merge branch 'master' into frankreh/fixed-descriptor-support
FrankReh Feb 20, 2023
7913a17
Merge branch 'master' into frankreh/fixed-descriptor-support
FrankReh Feb 21, 2023
4522d04
Merge branch 'master' into frankreh/fixed-descriptor-support
FrankReh Feb 25, 2023
60a7ca3
Merge branch 'master' into frankreh/fixed-descriptor-support
FrankReh Feb 27, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 23 additions & 11 deletions src/io/close.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,36 @@
use crate::io::shared_fd::sealed::CommonFd;
use crate::runtime::driver::op;
use crate::runtime::driver::op::{Completable, Op};
use crate::runtime::CONTEXT;
use std::io;
use std::os::unix::io::RawFd;

pub(crate) struct Close {
fd: RawFd,
}
pub(crate) struct Close {}

impl Op<Close> {
pub(crate) fn close(fd: RawFd) -> io::Result<Op<Close>> {
pub(crate) fn close(fd: CommonFd) -> io::Result<Op<Close>> {
use io_uring::{opcode, types};

CONTEXT.with(|x| {
x.handle()
.expect("Not in a runtime context")
.submit_op(Close { fd }, |close| {
opcode::Close::new(types::Fd(close.fd)).build()
match fd {
CommonFd::Raw(raw) => CONTEXT.with(|x| {
x.handle()
.expect("Not in a runtime context")
.submit_op(Close {}, |_close| {
opcode::Close::new(types::Fd(raw)).build()
})
}),
CommonFd::Fixed(_fixed) => {
/* TODO not yet implemented by io-uring
CONTEXT.with(|x| {
x.handle()
.expect("Not in a runtime context")
.submit_op(Close { fd }, |_close| {
opcode::Close_direct::new(_fixed).build()
})
})
})
*/
unreachable!("waiting for the ability to create a fixed descriptor for a request");
}
}
}
}

Expand Down
131 changes: 114 additions & 17 deletions src/io/shared_fd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use std::os::unix::io::{FromRawFd, RawFd};
use std::rc::Rc;
use std::task::Waker;

use crate::io::shared_fd::sealed::CommonFd;
use crate::runtime::driver::op::Op;
use crate::runtime::CONTEXT;

Expand All @@ -21,7 +22,7 @@ pub(crate) struct SharedFd {

struct Inner {
// Open file descriptor
fd: RawFd,
fd: CommonFd,

// Waker to notify when the close operation completes.
state: RefCell<State>,
Expand All @@ -45,15 +46,34 @@ impl SharedFd {
pub(crate) fn new(fd: RawFd) -> SharedFd {
SharedFd {
inner: Rc::new(Inner {
fd,
fd: CommonFd::Raw(fd),
state: RefCell::new(State::Init),
}),
}
}
// TODO once we implement a request that creates a fixed file descriptor, remove this 'allow'.
// It would be possible to create a fixed file using a `register` command to store a raw fd
// into the fixed table, but that's a whole other can of worms - do we track both, can either
// be closed while the other remains active and functional?
#[allow(dead_code)]
pub(crate) fn new_fixed(slot: u32) -> SharedFd {
SharedFd {
inner: Rc::new(Inner {
fd: CommonFd::Fixed(slot),
state: RefCell::new(State::Init),
}),
}
}

/// Returns the RawFd
/// Returns the RawFd.
pub(crate) fn raw_fd(&self) -> RawFd {
self.inner.fd
self.inner.raw_fd()
}

/// Returns true if self represents a RawFd.
#[allow(dead_code)]
pub(crate) fn is_raw_fd(&self) -> bool {
self.inner.is_raw_fd()
}

/// An FD cannot be closed until all in-flight operation have completed.
Expand All @@ -74,11 +94,35 @@ impl SharedFd {
}

impl Inner {
/// Returns the RawFd
pub(crate) fn raw_fd(&self) -> RawFd {
//self.inner.fd.0
match self.fd {
CommonFd::Raw(raw) => raw,
CommonFd::Fixed(_fixed) => {
unreachable!(); // caller could have used is_raw_fd
}
}
}

/// Returns true if self represents a RawFd.
pub(crate) fn is_raw_fd(&self) -> bool {
match self.fd {
CommonFd::Raw(_) => true,
CommonFd::Fixed(_) => false,
}
}
/// If there are no in-flight operations, submit the operation.
fn submit_close_op(&mut self) {
// Close the FD
// Close the file
let common_fd = self.fd;
let state = RefCell::get_mut(&mut self.state);

match *state {
State::Closing(_) | State::Closed => return,
_ => {}
};

// Submit a close operation
// If either:
// - runtime has already closed, or
Expand All @@ -92,19 +136,17 @@ impl Inner {
// dropping it.
//
// TODO: Should we warn?
*state = match CONTEXT.try_with(|cx| cx.is_set()) {
Ok(true) => match Op::close(self.fd) {
Ok(op) => State::Closing(op),
Err(_) => {
let _ = unsafe { std::fs::File::from_raw_fd(self.fd) };
State::Closed
}
},
_ => {
let _ = unsafe { std::fs::File::from_raw_fd(self.fd) };
State::Closed
if let Ok(true) = CONTEXT.try_with(|cx| cx.is_set()) {
if let Ok(op) = Op::close(common_fd) {
*state = State::Closing(op);
return;
}
};

if let CommonFd::Raw(raw) = common_fd {
let _ = unsafe { std::fs::File::from_raw_fd(raw) };
}
*state = State::Closed;
}

/// Completes when the FD has been closed.
Expand Down Expand Up @@ -133,7 +175,7 @@ impl Inner {
Poll::Pending
}
State::Closing(op) => {
// Nothing to do if the close opeation failed.
// Nothing to do if the close operation failed.
let _ = ready!(Pin::new(op).poll(cx));
*state = State::Closed;
Poll::Ready(())
Expand All @@ -156,3 +198,58 @@ impl Drop for Inner {
}
}
}

// Enum and traits copied from the io-uring crate.

/// A file descriptor that has not been registered with io_uring.
#[derive(Debug, Clone, Copy)]
pub struct Raw(pub RawFd); // Note: io-uring names this Fd

/// A file descriptor that has been registered with io_uring using
/// [`Submitter::register_files`](crate::Submitter::register_files) or [`Submitter::register_files_sparse`](crate::Submitter::register_files_sparse).
/// This can reduce overhead compared to using [`Fd`] in some cases.
#[derive(Debug, Clone, Copy)]
pub struct Fixed(pub u32); // TODO consider renaming to Direct (but uring docs use both Fixed descriptor and Direct descriptor)

pub(crate) mod sealed {
use super::{Fixed, Raw};
use std::os::unix::io::RawFd;

#[derive(Debug, Clone, Copy)]
// Note: io-uring names this Target
pub enum CommonFd {
Raw(RawFd),
Fixed(u32),
}

// Note: io-uring names this UseFd
pub trait UseRawFd: Sized {
fn into(self) -> RawFd;
}

// Note: io-uring names this UseFixed
pub trait UseCommonFd: Sized {
fn into(self) -> CommonFd;
}

impl UseRawFd for Raw {
#[inline]
fn into(self) -> RawFd {
self.0
}
}

impl UseCommonFd for Raw {
#[inline]
fn into(self) -> CommonFd {
CommonFd::Raw(self.0)
}
}

impl UseCommonFd for Fixed {
#[inline]
fn into(self) -> CommonFd {
CommonFd::Fixed(self.0)
}
}
}