io: use io_uring for all io
There should no longer be any - read - write - connect - sendmsg - recvmsg - accept calls in the codebase. Previously we were using a mix of io_uring and these calls which had some negative effects: Since we were using the old system calls, we had to set the file descriptors to non-blocking. But our io_uring code did not handle EAGAIN. This lead to programs sometimes being killed when the wayland IO was actually blocking. Now all file descriptors are set to blocking, but io_uring makes it non-blocking from our perspective. The one exception are evdev files because they are read via libinput and libinput uses the old system calls.
This commit is contained in:
parent
2db0ee8995
commit
9812a02f87
55 changed files with 900 additions and 672 deletions
|
|
@ -15,7 +15,7 @@ pub struct BufFdIn {
|
|||
fd: Rc<OwnedFd>,
|
||||
ring: Rc<IoUring>,
|
||||
|
||||
in_fd: VecDeque<OwnedFd>,
|
||||
in_fd: VecDeque<Rc<OwnedFd>>,
|
||||
|
||||
in_buf: Buf,
|
||||
in_left: usize,
|
||||
|
|
@ -86,7 +86,7 @@ impl BufFdIn {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_fd(&mut self) -> Result<OwnedFd, BufFdError> {
|
||||
pub fn get_fd(&mut self) -> Result<Rc<OwnedFd>, BufFdError> {
|
||||
match self.in_fd.pop_front() {
|
||||
Some(f) => Ok(f),
|
||||
None => Err(BufFdError::NoFd),
|
||||
|
|
|
|||
|
|
@ -4,17 +4,16 @@ use {
|
|||
time::Time,
|
||||
utils::{
|
||||
buf::Buf,
|
||||
buffd::{BufFdError, BUF_SIZE, CMSG_BUF_SIZE},
|
||||
buffd::{BufFdError, BUF_SIZE},
|
||||
oserror::OsError,
|
||||
},
|
||||
},
|
||||
std::{
|
||||
collections::VecDeque,
|
||||
mem::{self, MaybeUninit},
|
||||
mem::{self},
|
||||
rc::Rc,
|
||||
slice,
|
||||
},
|
||||
uapi::{c, Errno, OwnedFd},
|
||||
uapi::{c, OwnedFd},
|
||||
};
|
||||
|
||||
pub(super) const OUT_BUF_SIZE: usize = 2 * BUF_SIZE;
|
||||
|
|
@ -80,8 +79,6 @@ impl OutBufferSwapchain {
|
|||
pub struct BufFdOut {
|
||||
fd: Rc<OwnedFd>,
|
||||
ring: Rc<IoUring>,
|
||||
cmsg_buf: Box<[MaybeUninit<u8>; CMSG_BUF_SIZE]>,
|
||||
fd_ids: Vec<i32>,
|
||||
}
|
||||
|
||||
impl BufFdOut {
|
||||
|
|
@ -89,8 +86,6 @@ impl BufFdOut {
|
|||
Self {
|
||||
fd: fd.clone(),
|
||||
ring: ring.clone(),
|
||||
cmsg_buf: Box::new([MaybeUninit::uninit(); CMSG_BUF_SIZE]),
|
||||
fd_ids: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -131,7 +126,7 @@ impl BufFdOut {
|
|||
buf = buffer.buf.slice(buffer.meta.read_pos..next_pos);
|
||||
}
|
||||
}
|
||||
match self.ring.sendmsg(&self.fd, buf, fds, timeout).await {
|
||||
match self.ring.sendmsg_one(&self.fd, buf, fds, timeout).await {
|
||||
Ok(n) => {
|
||||
buffer.meta.read_pos += n;
|
||||
Ok(())
|
||||
|
|
@ -144,59 +139,23 @@ impl BufFdOut {
|
|||
|
||||
pub async fn flush2(
|
||||
&mut self,
|
||||
buf: &[u8],
|
||||
fds: &mut Vec<Rc<OwnedFd>>,
|
||||
mut buf: Buf,
|
||||
mut fds: Vec<Rc<OwnedFd>>,
|
||||
) -> Result<(), BufFdError> {
|
||||
let mut read_pos = 0;
|
||||
while read_pos < buf.len() {
|
||||
if self.flush_sync2(&mut read_pos, buf, fds)? {
|
||||
self.ring.writable(&self.fd).await?;
|
||||
let res = self
|
||||
.ring
|
||||
.sendmsg_one(&self.fd, buf.slice(read_pos..), mem::take(&mut fds), None)
|
||||
.await;
|
||||
match res {
|
||||
Ok(n) => read_pos += n,
|
||||
Err(IoUringError::OsError(OsError(c::ECONNRESET))) => {
|
||||
return Err(BufFdError::Closed)
|
||||
}
|
||||
Err(e) => return Err(BufFdError::Io(e)),
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn flush_sync2(
|
||||
&mut self,
|
||||
read_pos: &mut usize,
|
||||
buf: &[u8],
|
||||
fds: &mut Vec<Rc<OwnedFd>>,
|
||||
) -> Result<bool, BufFdError> {
|
||||
let mut cmsg_len = 0;
|
||||
let mut fds_opt = None;
|
||||
if fds.len() > 0 {
|
||||
self.fd_ids.clear();
|
||||
self.fd_ids.extend(fds.iter().map(|f| f.raw()));
|
||||
let hdr = c::cmsghdr {
|
||||
cmsg_len: 0,
|
||||
cmsg_level: c::SOL_SOCKET,
|
||||
cmsg_type: c::SCM_RIGHTS,
|
||||
};
|
||||
let mut cmsg_buf = &mut self.cmsg_buf[..];
|
||||
cmsg_len = uapi::cmsg_write(&mut cmsg_buf, hdr, &self.fd_ids[..]).unwrap();
|
||||
fds_opt = Some(fds);
|
||||
}
|
||||
while *read_pos < buf.len() {
|
||||
let buf = &buf[*read_pos..];
|
||||
let hdr = uapi::Msghdr {
|
||||
iov: slice::from_ref(&buf),
|
||||
control: Some(&self.cmsg_buf[..cmsg_len]),
|
||||
name: uapi::sockaddr_none_ref(),
|
||||
};
|
||||
let bytes_sent =
|
||||
match uapi::sendmsg(self.fd.raw(), &hdr, c::MSG_DONTWAIT | c::MSG_NOSIGNAL) {
|
||||
Ok(b) => {
|
||||
if let Some(fds) = fds_opt.take() {
|
||||
fds.clear();
|
||||
}
|
||||
b
|
||||
}
|
||||
Err(Errno(c::EAGAIN)) => return Ok(true),
|
||||
Err(Errno(c::ECONNRESET)) => return Err(BufFdError::Closed),
|
||||
Err(e) => return Err(BufFdError::Io(e.into())),
|
||||
};
|
||||
*read_pos += bytes_sent;
|
||||
}
|
||||
Ok(false)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@ impl<'a, 'b> MsgParser<'a, 'b> {
|
|||
|
||||
pub fn fd(&mut self) -> Result<Rc<OwnedFd>, MsgParserError> {
|
||||
match self.buf.get_fd() {
|
||||
Ok(fd) => Ok(Rc::new(fd)),
|
||||
Ok(fd) => Ok(fd),
|
||||
_ => Err(MsgParserError::MissingFd),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue