mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
virtio-devices: console: Handle output queue errors gracefully
Address translation, guest memory read, write, and flush failures on the transmitq propagated errors that killed the console device thread. A host-side I/O error such as a PTY disconnect would permanently disable the console. Log warnings and continue processing instead. Signed-off-by: Rob Bradford <rbradford@meta.com> Assisted-by: Claude:claude-opus-4-6
This commit is contained in:
@@ -51,12 +51,6 @@ const VIRTIO_CONSOLE_F_SIZE: u64 = 0;
|
|||||||
|
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
enum Error {
|
enum Error {
|
||||||
#[error("Failed to read from guest memory")]
|
|
||||||
GuestMemoryRead(#[source] vm_memory::guest_memory::Error),
|
|
||||||
#[error("Failed to write_all output")]
|
|
||||||
OutputWriteAll(#[source] io::Error),
|
|
||||||
#[error("Failed to flush output")]
|
|
||||||
OutputFlush(#[source] io::Error),
|
|
||||||
#[error("Failed to add used index")]
|
#[error("Failed to add used index")]
|
||||||
QueueAddUsed(#[source] virtio_queue::Error),
|
QueueAddUsed(#[source] virtio_queue::Error),
|
||||||
}
|
}
|
||||||
@@ -266,21 +260,28 @@ impl ConsoleEpollHandler {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if let Some(out) = &mut self.out {
|
if let Some(out) = &mut self.out {
|
||||||
|
let addr = match desc
|
||||||
|
.addr()
|
||||||
|
.translate_gva(self.access_platform.as_deref(), desc.len() as usize)
|
||||||
|
{
|
||||||
|
Ok(a) => a,
|
||||||
|
Err(e) => {
|
||||||
|
warn!("Failed to translate transmitq descriptor address: {e}");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
};
|
||||||
let mut buf: Vec<u8> = Vec::new();
|
let mut buf: Vec<u8> = Vec::new();
|
||||||
desc_chain
|
if let Err(e) =
|
||||||
.memory()
|
desc_chain
|
||||||
.write_volatile_to(
|
.memory()
|
||||||
desc.addr()
|
.write_volatile_to(addr, &mut buf, desc.len() as usize)
|
||||||
.translate_gva(self.access_platform.as_deref(), desc.len() as usize)
|
{
|
||||||
.map_err(|e| {
|
warn!("Failed to read from transmitq descriptor: {e}");
|
||||||
Error::GuestMemoryRead(vm_memory::GuestMemoryError::IOError(e))
|
continue;
|
||||||
})?,
|
}
|
||||||
&mut buf,
|
if let Err(e) = out.write_all(&buf) {
|
||||||
desc.len() as usize,
|
warn!("Failed to write console output: {e}");
|
||||||
)
|
}
|
||||||
.map_err(Error::GuestMemoryRead)?;
|
|
||||||
|
|
||||||
out.write_all(&buf).map_err(Error::OutputWriteAll)?;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
trans_queue
|
trans_queue
|
||||||
@@ -289,8 +290,11 @@ impl ConsoleEpollHandler {
|
|||||||
used_descs = true;
|
used_descs = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if used_descs && let Some(out) = &mut self.out {
|
if used_descs
|
||||||
out.flush().map_err(Error::OutputFlush)?;
|
&& let Some(out) = &mut self.out
|
||||||
|
&& let Err(e) = out.flush()
|
||||||
|
{
|
||||||
|
warn!("Failed to flush console output: {e}");
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(used_descs)
|
Ok(used_descs)
|
||||||
|
|||||||
Reference in New Issue
Block a user