• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

google / alioth / 16873657826

11 Aug 2025 07:28AM UTC coverage: 10.419% (+0.05%) from 10.366%
16873657826

push

github

Lencerf
fix(virtio): do not treat Ok(0) as errors

Ok(0) from read() or write() generally means either the provided buffer
is empty, or there are no more data to be provided or accepted by the
file descriptor. The second case should be treated as WouldBlock.

Signed-off-by: Changyuan Lyu <changyuanl@google.com>

4 of 6 new or added lines in 1 file covered. (66.67%)

71 existing lines in 3 files now uncovered.

714 of 6853 relevant lines covered (10.42%)

16.13 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.18
/alioth/src/virtio/queue/queue.rs
1
// Copyright 2024 Google LLC
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//     https://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14

15
pub mod split;
16
#[cfg(test)]
17
#[path = "queue_test.rs"]
18
mod tests;
19

20
use std::io::{ErrorKind, IoSlice, IoSliceMut, Read, Write};
21
use std::sync::atomic::{AtomicBool, AtomicU16, AtomicU64, Ordering, fence};
22

23
use crate::virtio::{IrqSender, Result};
24

25
pub const QUEUE_SIZE_MAX: u16 = 256;
26

27
#[derive(Debug, Default)]
28
pub struct Queue {
29
    pub size: AtomicU16,
30
    pub desc: AtomicU64,
31
    pub driver: AtomicU64,
32
    pub device: AtomicU64,
33
    pub enabled: AtomicBool,
34
}
35

36
#[derive(Debug)]
37
pub struct Descriptor<'m> {
38
    pub id: u16,
39
    pub readable: Vec<IoSlice<'m>>,
40
    pub writable: Vec<IoSliceMut<'m>>,
41
}
42

43
pub trait VirtQueue<'m> {
44
    fn reg(&self) -> &Queue;
45
    fn size(&self) -> u16;
46
    fn next_desc(&self) -> Option<Result<Descriptor<'m>>>;
47
    fn avail_index(&self) -> u16;
48
    fn get_descriptor(&self, index: u16) -> Result<Descriptor<'m>>;
49
    fn has_next_desc(&self) -> bool;
50
    fn push_used(&mut self, desc: Descriptor, len: usize) -> u16;
51
    fn enable_notification(&self, enabled: bool);
52
    fn interrupt_enabled(&self) -> bool;
53

54
    fn handle_desc(
34✔
55
        &mut self,
56
        q_index: u16,
57
        irq_sender: &impl IrqSender,
58
        mut op: impl FnMut(&mut Descriptor) -> Result<Option<usize>>,
59
    ) -> Result<()> {
60
        let mut send_irq = false;
66✔
61
        let mut ret = Ok(());
66✔
62
        'out: loop {
×
63
            if !self.has_next_desc() {
48✔
64
                break;
20✔
65
            }
66
            self.enable_notification(false);
50✔
67
            while let Some(desc) = self.next_desc() {
64✔
68
                let mut desc = desc?;
28✔
69
                match op(&mut desc) {
6✔
70
                    Err(e) => {
6✔
71
                        ret = Err(e);
10✔
72
                        self.enable_notification(true);
10✔
73
                        break 'out;
4✔
74
                    }
75
                    Ok(None) => break 'out,
8✔
76
                    Ok(Some(len)) => {
14✔
77
                        self.push_used(desc, len);
2✔
78
                        send_irq = send_irq || self.interrupt_enabled();
14✔
79
                    }
80
                }
81
            }
82
            self.enable_notification(true);
14✔
83
            fence(Ordering::SeqCst);
2✔
84
        }
85
        if send_irq {
34✔
86
            fence(Ordering::SeqCst);
26✔
87
            irq_sender.queue_irq(q_index)
38✔
88
        }
89
        ret
2✔
90
    }
91

92
    fn copy_from_reader(
17✔
93
        &mut self,
94
        q_index: u16,
95
        irq_sender: &impl IrqSender,
96
        mut reader: impl Read,
97
    ) -> Result<()> {
98
        self.handle_desc(q_index, irq_sender, |desc| {
78✔
99
            let ret = reader.read_vectored(&mut desc.writable);
49✔
100
            match ret {
6✔
NEW
101
                Ok(0) => {
×
102
                    let size: usize = desc.writable.iter().map(|s| s.len()).sum();
12✔
103
                    if size == 0 { Ok(Some(0)) } else { Ok(None) }
5✔
104
                }
105
                Ok(len) => Ok(Some(len)),
9✔
106
                Err(e) if e.kind() == ErrorKind::WouldBlock => Ok(None),
13✔
107
                Err(e) => Err(e)?,
6✔
108
            }
109
        })
110
    }
111

112
    fn copy_to_writer(
17✔
113
        &mut self,
114
        q_index: u16,
115
        irq_sender: &impl IrqSender,
116
        mut writer: impl Write,
117
    ) -> Result<()> {
118
        self.handle_desc(q_index, irq_sender, |desc| {
78✔
119
            let ret = writer.write_vectored(&desc.readable);
49✔
120
            match ret {
6✔
NEW
121
                Ok(0) => {
×
122
                    let size: usize = desc.readable.iter().map(|s| s.len()).sum();
12✔
123
                    if size == 0 { Ok(Some(0)) } else { Ok(None) }
5✔
124
                }
125
                Ok(len) => Ok(Some(len)),
9✔
126
                Err(e) if e.kind() == ErrorKind::WouldBlock => Ok(None),
13✔
127
                Err(e) => Err(e)?,
6✔
128
            }
129
        })
130
    }
131
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc