Skip to content

fs: Implement io-uring::Op<Statx> and use it to implement fs::try_exists and complete the todo's in read_uring#7791

Open
vrtgs wants to merge 3 commits intotokio-rs:masterfrom
vrtgs:io-uring-metadata
Open

fs: Implement io-uring::Op<Statx> and use it to implement fs::try_exists and complete the todo's in read_uring#7791
vrtgs wants to merge 3 commits intotokio-rs:masterfrom
vrtgs:io-uring-metadata

Conversation

@vrtgs
Copy link
Copy Markdown
Contributor

@vrtgs vrtgs commented Dec 24, 2025

Motivation

get us one step closer to real io-uring

@vrtgs vrtgs force-pushed the io-uring-metadata branch 10 times, most recently from a030621 to d5876fc Compare December 24, 2025 21:19
@vrtgs vrtgs force-pushed the io-uring-metadata branch from d5876fc to 85be9f9 Compare December 24, 2025 21:25
@ADD-SP ADD-SP added A-tokio Area: The main tokio crate M-fs Module: tokio/fs labels Dec 25, 2025
@vrtgs vrtgs changed the title io-uring: implement Op<Statx> and use it to implement fs::try_exists io-uring: implement Op<Statx> and use it to implement fs::try_exists and complete the todo's in read_uring Dec 26, 2025
@vrtgs vrtgs force-pushed the io-uring-metadata branch 2 times, most recently from b9b395f to 9f98fdf Compare December 26, 2025 14:41
@vrtgs vrtgs force-pushed the io-uring-metadata branch from 9f98fdf to 972c7c1 Compare December 26, 2025 15:05
Copy link
Copy Markdown
Contributor

@Daksh14 Daksh14 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this PR! Unfortunately we can't expose this using the std's Metadata to users of tokio because we can't construct one but needed internal usage in read, write, etc.

let size_hint: Option<usize> = size_hint
.ok()
.map(|m| usize::try_from(m.len()).unwrap_or(usize::MAX));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here if we obtain size_hint Err for whatever reason, we should start with a length 0 capacity and gradually increase it

)
.flags(flags as i32)
.mask(linux_raw_sys::general::STATX_BASIC_STATS)
.build();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there a guarantee that after this line the buffer will be initialized? Should we add a check after it completes? What if the kernel errored and the buffer still remains unint?

fn complete(self, cqe: CqeResult) -> Self::Output {
let ret = cqe
.result
.map(|_| Metadata(*unsafe { box_assume_init(self.buffer) }));
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should add a check here to check if the buffer is init or not or a safety comment explaining why this is ok

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alright I will check the return to be exactly 0, if it is 0 then yes there is a guarantee

Comment thread tokio/src/io/uring/utils.rs
let mut buffer = box_new_uninit::<statx>();

let flags: u32 = linux_raw_sys::general::AT_STATX_SYNC_AS_STAT
| (linux_raw_sys::general::AT_SYMLINK_NOFOLLOW * u32::from(!follow_symlinks));
Copy link
Copy Markdown
Contributor

@Daksh14 Daksh14 Dec 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can create an member function that takes in a flags: u32, path: &Path then you can have fn statx_follow_symlinks and fn statx_no_symlinks than have a vague bool argument which might confuse future readers and users

@vrtgs
Copy link
Copy Markdown
Contributor Author

vrtgs commented Dec 29, 2025

Thanks for this PR! Unfortunately we can't expose this using the std's Metadata to users of tokio because we can't construct one but needed internal usage in read, write, etc.

Yeah, I did realize that as well which is why I didn't rewrite tokio::fs::metadata
Never the less as you said internal usage is pretty good, especially with things like tokio::fs::try_exists since that is decently common

@vrtgs vrtgs closed this Dec 29, 2025
@vrtgs vrtgs reopened this Dec 29, 2025
@vrtgs
Copy link
Copy Markdown
Contributor Author

vrtgs commented Dec 29, 2025

I am very sorry for the weird behavior btw, the github app sucks I accidentally closed the pr, when I respond to any comment 2 comment show up, sorry for the inconvenience

@martin-g martin-g changed the title io-uring: implement Op<Statx> and use it to implement fs::try_exists and complete the todo's in read_uring fs: Implement io-uring::Op<Statx> and use it to implement fs::try_exists and complete the todo's in read_uring Dec 29, 2025
// https://man7.org/linux/man-pages/man2/statx.2.html
let statx_op = opcode::Statx::new(
types::Fd(fd.as_raw_fd()),
c"".as_ptr(),
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

}

cfg_io_uring! {
async fn try_exists_uring(path: &Path) -> io::Result<bool> {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: IMO this function can be inlined at line 39 above

Comment thread tokio/Cargo.toml
# Requires `--cfg tokio_unstable` to enable.
[target.'cfg(all(tokio_unstable, target_os = "linux"))'.dependencies]
io-uring = { version = "0.7.6", default-features = false, optional = true }
linux-raw-sys = { version = "0.12.1", optional = true }
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a particular reason to not use libc instead ?
AFAIS it provides all the constants used in this PR from linux-raw-sys

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please do not use linux-raw-sys.

@martin-g martin-g added the T-io-uring Topic: Linux io_uring label Dec 29, 2025
@martin-g
Copy link
Copy Markdown
Member

BTW there was an earlier attempt for Statx support at #7616.
You may check it. There might be something useful to borrow from it.

const MAX_READ_SIZE: usize = 64 * 1024 * 1024;

pub(crate) async fn read_uring(path: &Path) -> io::Result<Vec<u8>> {
let file = OpenOptions::new().read(true).open(path).await?;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like to keep the OpenOptions, use it how you would without breaking/adding new changes and opening files with uring should work.

@mattiapitossi mattiapitossi added the S-waiting-on-author Status: awaiting some action (such as code changes) from the PR or issue author. label Apr 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-tokio Area: The main tokio crate M-fs Module: tokio/fs S-waiting-on-author Status: awaiting some action (such as code changes) from the PR or issue author. T-io-uring Topic: Linux io_uring

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants