Coverage Report

Created: 2025-11-16 06:56

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/vhost-0.14.0/src/lib.rs
Line
Count
Source
1
// Copyright (C) 2019 Alibaba Cloud. All rights reserved.
2
// SPDX-License-Identifier: Apache-2.0 or BSD-3-Clause
3
4
//! # Virtio Vhost Backend Drivers
5
//!
6
//! Virtio devices use virtqueues to transport data efficiently. The first generation of virtqueue
7
//! is a set of three different single-producer, single-consumer ring structures designed to store
8
//! generic scatter-gather I/O. The virtio specification 1.1 introduces an alternative compact
9
//! virtqueue layout named "Packed Virtqueue", which is more friendly to memory cache system and
10
//! hardware implemented virtio devices. The packed virtqueue uses read-write memory, that means
11
//! the memory will be both read and written by both host and guest. The new Packed Virtqueue is
12
//! preferred for performance.
13
//!
14
//! Vhost is a mechanism to improve performance of Virtio devices by delegate data plane operations
15
//! to dedicated IO service processes. Only the configuration, I/O submission notification, and I/O
16
//! completion interruption are piped through the hypervisor.
17
//! It uses the same virtqueue layout as Virtio to allow Vhost devices to be mapped directly to
18
//! Virtio devices. This allows a Vhost device to be accessed directly by a guest OS inside a
19
//! hypervisor process with an existing Virtio (PCI) driver.
20
//!
21
//! The initial vhost implementation is a part of the Linux kernel and uses ioctl interface to
22
//! communicate with userspace applications. Dedicated kernel worker threads are created to handle
23
//! IO requests from the guest.
24
//!
25
//! Later Vhost-user protocol is introduced to complement the ioctl interface used to control the
26
//! vhost implementation in the Linux kernel. It implements the control plane needed to establish
27
//! virtqueues sharing with a user space process on the same host. It uses communication over a
28
//! Unix domain socket to share file descriptors in the ancillary data of the message.
29
//! The protocol defines 2 sides of the communication, frontend and backend. Frontend is the application
30
//! that shares its virtqueues. Backend is the consumer of the virtqueues. Frontend and backend can be
31
//! either a client (i.e. connecting) or server (listening) in the socket communication.
32
33
#![deny(missing_docs)]
34
35
#[cfg_attr(feature = "vhost-user", macro_use)]
36
extern crate bitflags;
37
#[cfg_attr(feature = "vhost-kern", macro_use)]
38
extern crate vmm_sys_util;
39
40
mod backend;
41
pub use backend::*;
42
43
#[cfg(feature = "vhost-net")]
44
pub mod net;
45
#[cfg(feature = "vhost-vdpa")]
46
pub mod vdpa;
47
#[cfg(feature = "vhost-kern")]
48
pub mod vhost_kern;
49
#[cfg(feature = "vhost-user")]
50
pub mod vhost_user;
51
#[cfg(feature = "vhost-vsock")]
52
pub mod vsock;
53
54
/// Due to the way `xen` handles memory mappings we can not combine it with
55
/// `postcopy` feature which relies on persistent memory mappings. Thus we
56
/// disallow enabling both features at the same time.
57
#[cfg(all(feature = "postcopy", feature = "xen"))]
58
compile_error!("Both `postcopy` and `xen` features can not be enabled at the same time.");
59
60
/// Error codes for vhost operations
61
#[derive(Debug)]
62
pub enum Error {
63
    /// Invalid operations.
64
    InvalidOperation,
65
    /// Invalid guest memory.
66
    InvalidGuestMemory,
67
    /// Invalid guest memory region.
68
    InvalidGuestMemoryRegion,
69
    /// Invalid IOTLB message.
70
    InvalidIotlbMsg,
71
    /// Invalid queue.
72
    InvalidQueue,
73
    /// Invalid descriptor table address.
74
    DescriptorTableAddress,
75
    /// Invalid used address.
76
    UsedAddress,
77
    /// Invalid available address.
78
    AvailAddress,
79
    /// Invalid log address.
80
    LogAddress,
81
    #[cfg(feature = "vhost-kern")]
82
    /// Error opening the vhost backend driver.
83
    VhostOpen(std::io::Error),
84
    #[cfg(feature = "vhost-kern")]
85
    /// Error while running ioctl.
86
    IoctlError(std::io::Error),
87
    /// Error from IO subsystem.
88
    IOError(std::io::Error),
89
    #[cfg(feature = "vhost-user")]
90
    /// Error from the vhost-user subsystem.
91
    VhostUserProtocol(vhost_user::Error),
92
}
93
94
impl std::fmt::Display for Error {
95
0
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
96
0
        match self {
97
0
            Error::InvalidOperation => write!(f, "invalid vhost operations"),
98
0
            Error::InvalidGuestMemory => write!(f, "invalid guest memory object"),
99
0
            Error::InvalidGuestMemoryRegion => write!(f, "invalid guest memory region"),
100
0
            Error::InvalidIotlbMsg => write!(f, "invalid IOTLB message"),
101
0
            Error::InvalidQueue => write!(f, "invalid virtqueue"),
102
            Error::DescriptorTableAddress => {
103
0
                write!(f, "invalid virtqueue descriptor table address")
104
            }
105
0
            Error::UsedAddress => write!(f, "invalid virtqueue used table address"),
106
0
            Error::AvailAddress => write!(f, "invalid virtqueue available table address"),
107
0
            Error::LogAddress => write!(f, "invalid virtqueue log address"),
108
0
            Error::IOError(e) => write!(f, "IO error: {}", e),
109
            #[cfg(feature = "vhost-kern")]
110
0
            Error::VhostOpen(e) => write!(f, "failure in opening vhost file: {}", e),
111
            #[cfg(feature = "vhost-kern")]
112
0
            Error::IoctlError(e) => write!(f, "failure in vhost ioctl: {}", e),
113
            #[cfg(feature = "vhost-user")]
114
0
            Error::VhostUserProtocol(e) => write!(f, "vhost-user: {}", e),
115
        }
116
0
    }
117
}
118
119
impl std::error::Error for Error {}
120
121
#[cfg(feature = "vhost-user")]
122
impl std::convert::From<vhost_user::Error> for Error {
123
0
    fn from(err: vhost_user::Error) -> Self {
124
0
        Error::VhostUserProtocol(err)
125
0
    }
126
}
127
128
/// Result of vhost operations
129
pub type Result<T> = std::result::Result<T, Error>;
130
131
#[cfg(test)]
132
mod tests {
133
    use super::*;
134
135
    #[test]
136
    fn test_error() {
137
        assert_eq!(
138
            format!("{}", Error::AvailAddress),
139
            "invalid virtqueue available table address"
140
        );
141
        assert_eq!(
142
            format!("{}", Error::InvalidOperation),
143
            "invalid vhost operations"
144
        );
145
        assert_eq!(
146
            format!("{}", Error::InvalidGuestMemory),
147
            "invalid guest memory object"
148
        );
149
        assert_eq!(
150
            format!("{}", Error::InvalidGuestMemoryRegion),
151
            "invalid guest memory region"
152
        );
153
        assert_eq!(
154
            format!("{}", Error::InvalidIotlbMsg),
155
            "invalid IOTLB message"
156
        );
157
        assert_eq!(format!("{}", Error::InvalidQueue), "invalid virtqueue");
158
        assert_eq!(
159
            format!("{}", Error::DescriptorTableAddress),
160
            "invalid virtqueue descriptor table address"
161
        );
162
        assert_eq!(
163
            format!("{}", Error::UsedAddress),
164
            "invalid virtqueue used table address"
165
        );
166
        assert_eq!(
167
            format!("{}", Error::LogAddress),
168
            "invalid virtqueue log address"
169
        );
170
171
        assert_eq!(format!("{:?}", Error::AvailAddress), "AvailAddress");
172
    }
173
174
    #[cfg(feature = "vhost-user")]
175
    #[test]
176
    fn test_convert_from_vhost_user_error() {
177
        let e: Error = vhost_user::Error::OversizedMsg.into();
178
179
        assert_eq!(format!("{}", e), "vhost-user: oversized message");
180
    }
181
}