linux_aio_sys/
lib.rs

1#![allow(non_camel_case_types)]
2
3//! Thin unsafe wrapper for Linux AIO API.
4
5use std::os::raw::{c_int, c_long, c_uint, c_ulong};
6
7include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
8
9pub unsafe fn io_setup(nr_events: c_uint, ctx_idp: *mut aio_context_t) -> c_int {
10    libc::syscall(libc::SYS_io_setup, nr_events, ctx_idp) as c_int
11}
12
13pub unsafe fn io_destroy(ctx_id: aio_context_t) -> c_int {
14    libc::syscall(libc::SYS_io_destroy, ctx_id) as c_int
15}
16
17pub unsafe fn io_submit(ctx_id: aio_context_t, nr: c_ulong, iocbpp: *mut *mut iocb) -> c_int {
18    libc::syscall(libc::SYS_io_submit, ctx_id, nr, iocbpp) as c_int
19}
20
21pub unsafe fn io_cancel(ctx_id: aio_context_t, iocb: *mut iocb, result: *mut io_event) -> c_int {
22    libc::syscall(libc::SYS_io_cancel, ctx_id, iocb, result) as c_int
23}
24
25pub unsafe fn io_getevents(
26    ctx_id: aio_context_t,
27    min_nr: c_long,
28    nr: c_long,
29    events: *mut io_event,
30    timeout: *mut libc::timespec,
31) -> c_int {
32    libc::syscall(libc::SYS_io_getevents, ctx_id, min_nr, nr, events, timeout) as c_int
33}
34
35#[cfg(test)]
36mod test {
37    use super::*;
38    use std::fs::File;
39    use std::io;
40    use std::os::unix::io::AsRawFd;
41    use std::ptr::null_mut;
42
43    // Adapted from https://github.com/cloudflare/cloudflare-blog/blob/master/2019-01-io-submit/aio_passwd.c
44    #[test]
45    fn read_passwd() -> io::Result<()> {
46        let file = File::open("/etc/passwd")?;
47
48        let mut ctx: aio_context_t = 0;
49        let mut r = unsafe { io_setup(128, &mut ctx) };
50        assert_eq!(r, 0);
51
52        let mut buf: [u8; 4096] = unsafe { std::mem::uninitialized() };
53        let mut iocb = iocb {
54            aio_fildes: file.as_raw_fd() as u32,
55            aio_lio_opcode: IOCB_CMD_PREAD as u16,
56            aio_buf: buf.as_mut_ptr() as u64,
57            aio_nbytes: buf.len() as u64,
58            ..Default::default()
59        };
60        r = unsafe { io_submit(ctx, 1, [&mut iocb as *mut iocb].as_mut_ptr()) };
61        assert_eq!(r, 1);
62
63        let mut events = [unsafe { std::mem::uninitialized::<io_event>() }];
64        r = unsafe { io_getevents(ctx, 1, 1, events.as_mut_ptr(), null_mut()) };
65        assert_eq!(r, 1);
66        assert!(events[0].res > 0);
67
68        r = unsafe { io_destroy(ctx) };
69        assert_eq!(r, 0);
70
71        Ok(())
72    }
73}