fuse_backend_rs/transport/
fs_cache_req_handler.rs

1// Copyright © 2019 Intel Corporation
2//
3// SPDX-License-Identifier: Apache-2.0
4
5#[cfg(not(feature = "virtiofs"))]
6/// Fake trait to simplify implementation when vhost-user-fs is not used.
7pub trait FsCacheReqHandler {}
8
9#[cfg(feature = "virtiofs")]
10pub use virtiofs::FsCacheReqHandler;
11
12#[cfg(feature = "virtiofs")]
13mod virtiofs {
14    use std::io;
15    use std::os::unix::io::RawFd;
16
17    #[cfg(feature = "vhost-user-fs")]
18    use vhost::vhost_user::message::{
19        VhostUserFSSlaveMsg, VhostUserFSSlaveMsgFlags, VHOST_USER_FS_SLAVE_ENTRIES,
20    };
21    #[cfg(feature = "vhost-user-fs")]
22    use vhost::vhost_user::{SlaveFsCacheReq, VhostUserMasterReqHandler};
23
24    use crate::abi::virtio_fs::RemovemappingOne;
25    #[cfg(feature = "vhost-user-fs")]
26    use crate::abi::virtio_fs::SetupmappingFlags;
27
28    /// Trait to support virtio-fs DAX Window operations.
29    ///
30    /// The virtio-fs DAX Window allows bypassing guest page cache and allows mapping host
31    /// page cache directly in guest address space.
32    ///
33    /// When a page of file is needed, guest sends a request to map that page (in host page cache)
34    /// in VMM address space. Inside guest this is a physical memory range controlled by virtiofs
35    /// device. And guest directly maps this physical address range using DAX and hence getsi
36    /// access to file data on host.
37    ///
38    /// This can speed up things considerably in many situations. Also this can result in
39    /// substantial memory savings as file data does not have to be copied in guest and it is
40    /// directly accessed from host page cache.
41    pub trait FsCacheReqHandler: Send + Sync + 'static {
42        /// Setup a dedicated mapping so that guest can access file data in DAX style.
43        fn map(
44            &mut self,
45            foffset: u64,
46            moffset: u64,
47            len: u64,
48            flags: u64,
49            fd: RawFd,
50        ) -> io::Result<()>;
51
52        /// Remove those mappings that provide the access to file data.
53        fn unmap(&mut self, requests: Vec<RemovemappingOne>) -> io::Result<()>;
54    }
55
56    #[cfg(feature = "vhost-user-fs")]
57    impl FsCacheReqHandler for SlaveFsCacheReq {
58        fn map(
59            &mut self,
60            foffset: u64,
61            moffset: u64,
62            len: u64,
63            flags: u64,
64            fd: RawFd,
65        ) -> io::Result<()> {
66            let mut msg: VhostUserFSSlaveMsg = Default::default();
67            msg.fd_offset[0] = foffset;
68            msg.cache_offset[0] = moffset;
69            msg.len[0] = len;
70            msg.flags[0] = if (flags & SetupmappingFlags::WRITE.bits()) != 0 {
71                VhostUserFSSlaveMsgFlags::MAP_W | VhostUserFSSlaveMsgFlags::MAP_R
72            } else {
73                VhostUserFSSlaveMsgFlags::MAP_R
74            };
75
76            self.fs_slave_map(&msg, &fd)?;
77
78            Ok(())
79        }
80
81        fn unmap(&mut self, requests: Vec<RemovemappingOne>) -> io::Result<()> {
82            for chunk in requests.chunks(VHOST_USER_FS_SLAVE_ENTRIES) {
83                let mut msg: VhostUserFSSlaveMsg = Default::default();
84
85                for (ind, req) in chunk.iter().enumerate() {
86                    msg.len[ind] = req.len;
87                    msg.cache_offset[ind] = req.moffset;
88                }
89
90                self.fs_slave_unmap(&msg)?;
91            }
92
93            Ok(())
94        }
95    }
96}