diff options
author | Chirantan Ekbote <chirantan@chromium.org> | 2019-11-15 14:25:36 +0900 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2019-11-22 05:54:03 +0000 |
commit | 6576091e5623bb64af7076672b4ec4e42923ef3c (patch) | |
tree | ddaaeabb0e3359cd8536270939520b71c2c25b8a | |
parent | 220605a5fd03d7181d55b59d6bd147c86a4c8bc0 (diff) | |
download | crosvm-6576091e5623bb64af7076672b4ec4e42923ef3c.tar crosvm-6576091e5623bb64af7076672b4ec4e42923ef3c.tar.gz crosvm-6576091e5623bb64af7076672b4ec4e42923ef3c.tar.bz2 crosvm-6576091e5623bb64af7076672b4ec4e42923ef3c.tar.lz crosvm-6576091e5623bb64af7076672b4ec4e42923ef3c.tar.xz crosvm-6576091e5623bb64af7076672b4ec4e42923ef3c.tar.zst crosvm-6576091e5623bb64af7076672b4ec4e42923ef3c.zip |
devices: fs: Only resample interrupts on one thread
Having more than one thread watch the interrupt resample event meant that the threads would race to acknowledge the event: if thread B called epoll_wait after thread A got a readable event for the resample eventfd but before thread A called `read()` on the eventfd, then thread B would also get a readable event for that eventfd. Both threads would then attempt to acknowledge the event but only one would succeed. This would leave the other thread blocked on the `read()` call until the resample event became readable again. Fix this by having only one worker watch the resample event. BUG=b:136128319 TEST=`tast run vm.Virtiofs` on kevin Change-Id: I5cd781a9c79ac718207a944433ea20a967735237 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/1923568 Tested-by: Chirantan Ekbote <chirantan@chromium.org> Tested-by: kokoro <noreply+kokoro@google.com> Commit-Queue: Chirantan Ekbote <chirantan@chromium.org> Reviewed-by: Stephen Barber <smbarber@chromium.org> Reviewed-by: Daniel Verkamp <dverkamp@chromium.org>
-rw-r--r-- | devices/src/virtio/fs/mod.rs | 7 | ||||
-rw-r--r-- | devices/src/virtio/fs/worker.rs | 22 |
2 files changed, 21 insertions, 8 deletions
diff --git a/devices/src/virtio/fs/mod.rs b/devices/src/virtio/fs/mod.rs index ce7739a..0442bad 100644 --- a/devices/src/virtio/fs/mod.rs +++ b/devices/src/virtio/fs/mod.rs @@ -236,6 +236,7 @@ impl VirtioDevice for Fs { let server = Arc::new(Server::new(fs)); let irq = Arc::new(interrupt); + let mut watch_resample_event = true; for (idx, (queue, evt)) in queues.into_iter().zip(queue_evts.into_iter()).enumerate() { let (self_kill_evt, kill_evt) = match EventFd::new().and_then(|e| Ok((e.try_clone()?, e))) { @@ -255,9 +256,13 @@ impl VirtioDevice for Fs { .name(format!("virtio-fs worker {}", idx)) .spawn(move || { let mut worker = Worker::new(mem, queue, server, irq); - worker.run(evt, kill_evt) + worker.run(evt, kill_evt, watch_resample_event) }); + if watch_resample_event { + watch_resample_event = false; + } + match worker_result { Ok(worker) => self.workers.push((self_kill_evt, worker)), Err(e) => { diff --git a/devices/src/virtio/fs/worker.rs b/devices/src/virtio/fs/worker.rs index ec0ec8a..36b8b69 100644 --- a/devices/src/virtio/fs/worker.rs +++ b/devices/src/virtio/fs/worker.rs @@ -56,7 +56,12 @@ impl<F: FileSystem + Sync> Worker<F> { Ok(()) } - pub fn run(&mut self, queue_evt: EventFd, kill_evt: EventFd) -> Result<()> { + pub fn run( + &mut self, + queue_evt: EventFd, + kill_evt: EventFd, + watch_resample_event: bool, + ) -> Result<()> { #[derive(PollToken)] enum Token { // A request is ready on the queue. @@ -67,12 +72,15 @@ impl<F: FileSystem + Sync> Worker<F> { Kill, } - let poll_ctx = PollContext::build_with(&[ - (&queue_evt, Token::QueueReady), - (&kill_evt, Token::Kill), - (self.irq.get_resample_evt(), Token::InterruptResample), - ]) - .map_err(Error::CreatePollContext)?; + let poll_ctx = + PollContext::build_with(&[(&queue_evt, Token::QueueReady), (&kill_evt, Token::Kill)]) + .map_err(Error::CreatePollContext)?; + + if watch_resample_event { + poll_ctx + .add(self.irq.get_resample_evt(), Token::InterruptResample) + .map_err(Error::CreatePollContext)?; + } loop { let events = poll_ctx.wait().map_err(Error::PollError)?; |