| 301 | } |
| 302 | |
| 303 | pub fn reset(&mut self) { |
| 304 | self.queue_evts.clear(); |
| 305 | |
| 306 | // Resume the virtio thread if it was paused. Reset must always |
| 307 | // converge to fresh state, so a resume failure is logged but doesn't |
| 308 | // skip the rest of the teardown. |
| 309 | if self.pause_evt.take().is_some() |
| 310 | && let Err(e) = self.resume() |
| 311 | { |
| 312 | error!("Failed to resume paused device during reset: {e:?}"); |
| 313 | } |
| 314 | |
| 315 | if let Some(kill_evt) = self.kill_evt.take() { |
| 316 | // Ignore the result because there is nothing we can do about it. |
| 317 | let _ = kill_evt.write(1); |
| 318 | } |
| 319 | |
| 320 | if let Some(mut threads) = self.epoll_threads.take() { |
| 321 | for t in threads.drain(..) { |
| 322 | if let Err(e) = t.join() { |
| 323 | error!("Error joining thread: {e:?}"); |
| 324 | } |
| 325 | } |
| 326 | } |
| 327 | |
| 328 | // Drop the interrupt callback clone |
| 329 | self.interrupt_cb = None; |
| 330 | } |
| 331 | |
| 332 | pub fn trigger_interrupt(&self, int_type: VirtioInterruptType) -> std::io::Result<()> { |
| 333 | if let Some(interrupt_cb) = &self.interrupt_cb { |