diff --git a/src/vmm/src/devices/virtio/block/virtio/device.rs b/src/vmm/src/devices/virtio/block/virtio/device.rs index c2538188301..817b9f53643 100644 --- a/src/vmm/src/devices/virtio/block/virtio/device.rs +++ b/src/vmm/src/devices/virtio/block/virtio/device.rs @@ -197,7 +197,7 @@ pub struct ConfigSpace { pub max_write_zeroes_seg: u32, // offset 52 pub write_zeroes_may_unmap: u8, // offset 56 pub(crate) _unused1: [u8; 3], // offset 57 (spec field — virtio_blk_config.unused1) - pub(crate) _pad: [u8; 4], // offset 60 (Rust alignment padding to 64; spec ends at 60) + pub(crate) _pad: [u8; 4], // offset 60 (Rust alignment padding to 64; spec ends at 60) } const _: () = assert!(std::mem::size_of::() == 64); // Compile-time guards against accidental layout drift. The byte offsets here @@ -722,9 +722,10 @@ impl VirtioBlock { } fn drain_and_flush(&mut self, discard: bool) { - if let Err(err) = self.disk.file_engine.drain_and_flush(discard) { - error!("Failed to drain ops and flush block data: {:?}", err); - } + self.disk + .file_engine + .drain_and_flush(discard) + .expect("virtio-block: failed to drain ops and flush block data"); } /// Prepare device for being snapshotted. diff --git a/src/vmm/src/io_uring/queue/submission.rs b/src/vmm/src/io_uring/queue/submission.rs index db308e63a54..072a3a427b3 100644 --- a/src/vmm/src/io_uring/queue/submission.rs +++ b/src/vmm/src/io_uring/queue/submission.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 use std::fmt::Debug; -use std::io::Error as IOError; +use std::io::{Error as IOError, ErrorKind}; use std::mem; use std::num::Wrapping; use std::os::unix::io::RawFd; @@ -130,26 +130,39 @@ impl SubmissionQueue { if min_complete > 0 { flags |= generated::IORING_ENTER_GETEVENTS; } - // SAFETY: Safe because values are valid and we check the return value. - let submitted = SyscallReturnCode(unsafe { - libc::syscall( - libc::SYS_io_uring_enter, - self.io_uring_fd, - self.to_submit, - min_complete, - flags, - std::ptr::null::(), - ) - }) - .into_result()?; - // It's safe to convert to u32 since the syscall didn't return an error. - let submitted = u32::try_from(submitted).unwrap(); - - // This is safe since submitted <= self.to_submit. However we use a saturating_sub - // for extra safety. - self.to_submit = self.to_submit.saturating_sub(submitted); - Ok(submitted) + // The number of retries is completely arbitrary here. I assume that this + // will happen rarely and that if it happens subsequent retry will immediately + // succeed. If we fall in a storm of interrupts something else is probably wrong + // so let the consumer know. + let mut eintr_retries = 3; + loop { + // SAFETY: Safe because values are valid and we check the return value. + let ret = SyscallReturnCode(unsafe { + libc::syscall( + libc::SYS_io_uring_enter, + self.io_uring_fd, + self.to_submit, + min_complete, + flags, + std::ptr::null::(), + ) + }) + .into_result(); + match ret { + Ok(num) => { + // It's safe to convert to u32 since the syscall didn't return an error. + let submitted = u32::try_from(num).unwrap(); + self.to_submit = self.to_submit.saturating_sub(submitted); + return Ok(submitted); + } + Err(err) if err.kind() == ErrorKind::Interrupted && eintr_retries > 0 => { + eintr_retries -= 1; + continue; + } + Err(err) => return Err(SQueueError::from(err)), + } + } } fn mmap(