summary refs log tree commit diff
diff options
context:
space:
mode:
authorStephen Barber <smbarber@chromium.org>2019-10-04 15:20:05 -0700
committerCommit Bot <commit-bot@chromium.org>2019-10-08 08:55:59 +0000
commit7595d80248541434a8f4d93b5032b701cfdf4c7f (patch)
tree45e76c5defdfe8e36090658b51c7e1551e079db1
parent04e9c03f03f4c5e479d13c5f318d3b89d784ad7f (diff)
downloadcrosvm-7595d80248541434a8f4d93b5032b701cfdf4c7f.tar
crosvm-7595d80248541434a8f4d93b5032b701cfdf4c7f.tar.gz
crosvm-7595d80248541434a8f4d93b5032b701cfdf4c7f.tar.bz2
crosvm-7595d80248541434a8f4d93b5032b701cfdf4c7f.tar.lz
crosvm-7595d80248541434a8f4d93b5032b701cfdf4c7f.tar.xz
crosvm-7595d80248541434a8f4d93b5032b701cfdf4c7f.tar.zst
crosvm-7595d80248541434a8f4d93b5032b701cfdf4c7f.zip
devices: virtio_net: handle errors in tapfd poll adding/removal
Add error handling for adding/removing the tapfd to epoll.

We only remove the tap fd from the poll context if the tap is
readable, i.e. it would busy loop, so don't assume it's removed
from the poll context when there's a deferred rx frame.

BUG=chromium:1010742
TEST=arcvm network works

Change-Id: I84aab2dbe7ea31d724f04d3b3fb0a6916f232300
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/1842399
Tested-by: kokoro <noreply+kokoro@google.com>
Tested-by: Stephen Barber <smbarber@chromium.org>
Reviewed-by: Dylan Reid <dgreid@chromium.org>
Reviewed-by: Chirantan Ekbote <chirantan@chromium.org>
Commit-Queue: Stephen Barber <smbarber@chromium.org>
-rw-r--r--devices/src/virtio/net.rs23
1 files changed, 15 insertions, 8 deletions
diff --git a/devices/src/virtio/net.rs b/devices/src/virtio/net.rs
index 43fba38..7680b66 100644
--- a/devices/src/virtio/net.rs
+++ b/devices/src/virtio/net.rs
@@ -10,7 +10,7 @@ use std::sync::atomic::{AtomicUsize, Ordering};
 use std::sync::Arc;
 use std::thread;
 
-use libc::EAGAIN;
+use libc::{EAGAIN, EEXIST};
 use net_sys;
 use net_util::{Error as TapError, MacAddress, TapT};
 use sys_util::guest_memory::Error as MemoryError;
@@ -237,9 +237,12 @@ where
                             if self.rx_single_frame() {
                                 self.deferred_rx = false;
                             } else {
-                                // The guest has not yet made any buffers available. Remove the
-                                // tapfd from the poll context until more are made available.
-                                poll_ctx.delete(&self.tap).map_err(NetError::PollDeleteTap);
+                                // There is an outstanding deferred frame and the guest has not yet
+                                // made any buffers available. Remove the tapfd from the poll
+                                // context until more are made available.
+                                poll_ctx
+                                    .delete(&self.tap)
+                                    .map_err(NetError::PollDeleteTap)?;
                                 continue;
                             }
                         }
@@ -253,10 +256,14 @@ where
                         // There should be a buffer available now to receive the frame into.
                         if self.deferred_rx && self.rx_single_frame() {
                             // The guest has made buffers available, so add the tap back to the
-                            // poll context.
-                            poll_ctx
-                                .add(&self.tap, Token::RxTap)
-                                .map_err(NetError::PollAddTap);
+                            // poll context in case it was removed.
+                            match poll_ctx.add(&self.tap, Token::RxTap) {
+                                Ok(_) => {}
+                                Err(e) if e.errno() == EEXIST => {}
+                                Err(e) => {
+                                    return Err(NetError::PollAddTap(e));
+                                }
+                            }
                             self.deferred_rx = false;
                         }
                     }