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

google / alioth / 17114607742

21 Aug 2025 01:31AM UTC coverage: 10.411%. Remained the same
17114607742

Pull #273

github

web-flow
Merge 897d3fdbf into 7925c9625
Pull Request #273: feat: virtio packed queue

30 of 57 new or added lines in 9 files covered. (52.63%)

50 existing lines in 4 files now uncovered.

714 of 6858 relevant lines covered (10.41%)

16.1 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✔
NEW
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✔
NEW
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

93
pub fn copy_from_reader(
20✔
94
    mut reader: impl Read,
95
) -> impl FnMut(&mut Descriptor) -> Result<Option<usize>> {
96
    move |desc| {
16✔
97
        let ret = reader.read_vectored(&mut desc.writable);
58✔
98
        match ret {
8✔
NEW
99
            Ok(0) => {
×
100
                let size: usize = desc.writable.iter().map(|s| s.len()).sum();
12✔
101
                if size == 0 { Ok(Some(0)) } else { Ok(None) }
5✔
102
            }
103
            Ok(len) => Ok(Some(len)),
14✔
104
            Err(e) if e.kind() == ErrorKind::WouldBlock => Ok(None),
13✔
105
            Err(e) => Err(e)?,
6✔
106
        }
107
    }
108
}
109

110
pub fn copy_to_writer(
20✔
111
    mut writer: impl Write,
112
) -> impl FnMut(&mut Descriptor) -> Result<Option<usize>> {
113
    move |desc| {
16✔
114
        let ret = writer.write_vectored(&desc.readable);
58✔
115
        match ret {
8✔
NEW
116
            Ok(0) => {
×
117
                let size: usize = desc.readable.iter().map(|s| s.len()).sum();
12✔
118
                if size == 0 { Ok(Some(0)) } else { Ok(None) }
5✔
119
            }
120
            Ok(_) => Ok(Some(0)),
8✔
121
            Err(e) if e.kind() == ErrorKind::WouldBlock => Ok(None),
13✔
122
            Err(e) => Err(e)?,
6✔
123
        }
124
    }
125
}
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