fix(virtio): monitor the waker with IORING_OP_POLL_ADD

With `IORING_POLL_ADD_MULTI`, we do not need to re-add the waker
to the ring.

Commit 0c4fc4e3ba also used IORING_OP_POLL_ADD for ioeventfds, which
was problematic because POLL_ADD does not clear the internal counter
of an eventfd when it creates a cqe. So once an ioeventfd is re-added
to the ring, it immediately generates a new cqe, despite that there is
no new MMIO yet. This causes the event loop thread to spin.

Signed-off-by: Changyuan Lyu <changyuanl@google.com>
This commit is contained in:
Changyuan Lyu 2024-09-16 09:51:33 -07:00 committed by Lencerf
parent 5659cd29f5
commit 95b9d5f9dd
3 changed files with 2 additions and 14 deletions

View file

@ -233,7 +233,6 @@ pub trait Backend<D: Virtio>: Send + 'static {
type Data<'m>;
fn register_waker(&mut self, token: u64) -> Result<Arc<Waker>>;
fn reregister_waker(&mut self, data: &mut Self::Data<'_>) -> Result<()>;
fn activate_dev(
&mut self,
dev: &mut D,
@ -310,9 +309,6 @@ where
}
}
}
if self.state == WorkerState::Running {
backend.reregister_waker(data)?;
}
Ok(())
}

View file

@ -85,8 +85,8 @@ where
fn submit_waker(&mut self, data: &mut RingData) -> Result<()> {
let fd = types::Fd(self.waker.0.as_raw_fd());
let read = opcode::Read::new(fd, self.efd_buffer.get() as *mut u8, 8);
let entry = read.build().user_data(self.waker_token);
let poll = opcode::PollAdd::new(fd, libc::EPOLLIN as _).multi(true);
let entry = poll.build().user_data(self.waker_token);
unsafe { data.ring.submission().push(&entry) }.unwrap();
Ok(())
}
@ -201,10 +201,6 @@ where
Ok(self.waker.clone())
}
fn reregister_waker(&mut self, data: &mut RingData<'_>) -> Result<()> {
self.submit_waker(data)
}
fn activate_dev(
&mut self,
dev: &mut D,

View file

@ -137,10 +137,6 @@ where
}
}
fn reregister_waker(&mut self, _data: &mut ()) -> Result<()> {
Ok(())
}
fn activate_dev(
&mut self,
dev: &mut D,