1 // Copyright 2019 The ChromiumOS Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 use std::collections::BTreeMap; 6 use std::io; 7 use std::sync::Arc; 8 9 use anyhow::anyhow; 10 use base::error; 11 use base::warn; 12 use base::AsRawDescriptor; 13 use base::Error as SysError; 14 use base::RawDescriptor; 15 use base::Tube; 16 use base::WorkerThread; 17 use data_model::Le32; 18 use remain::sorted; 19 use resources::Alloc; 20 use sync::Mutex; 21 use thiserror::Error; 22 use virtio_sys::virtio_fs::virtio_fs_config; 23 use virtio_sys::virtio_fs::VIRTIO_FS_SHMCAP_ID_CACHE; 24 use vm_control::FsMappingRequest; 25 use vm_control::VmResponse; 26 use vm_memory::GuestMemory; 27 use zerocopy::AsBytes; 28 29 use crate::pci::PciAddress; 30 use crate::pci::PciBarConfiguration; 31 use crate::pci::PciBarPrefetchable; 32 use crate::pci::PciBarRegionType; 33 use crate::pci::PciCapability; 34 use crate::virtio::copy_config; 35 use crate::virtio::device_constants::fs::FS_MAX_TAG_LEN; 36 use crate::virtio::DeviceType; 37 use crate::virtio::Interrupt; 38 use crate::virtio::PciCapabilityType; 39 use crate::virtio::Queue; 40 use crate::virtio::VirtioDevice; 41 use crate::virtio::VirtioPciShmCap; 42 43 #[cfg(feature = "arc_quota")] 44 mod arc_ioctl; 45 mod caps; 46 mod config; 47 mod expiring_map; 48 mod multikey; 49 pub mod passthrough; 50 mod read_dir; 51 mod worker; 52 53 pub use config::CachePolicy; 54 pub use config::Config; 55 use fuse::Server; 56 use passthrough::PassthroughFs; 57 pub use worker::Worker; 58 59 const QUEUE_SIZE: u16 = 1024; 60 61 const FS_BAR_NUM: u8 = 4; 62 const FS_BAR_OFFSET: u64 = 0; 63 const FS_BAR_SIZE: u64 = 1 << 33; 64 65 /// Errors that may occur during the creation or operation of an Fs device. 66 #[sorted] 67 #[derive(Error, Debug)] 68 pub enum Error { 69 /// Failed to create the file system. 70 #[error("failed to create file system: {0}")] 71 CreateFs(io::Error), 72 /// Creating WaitContext failed. 73 #[error("failed to create WaitContext: {0}")] 74 CreateWaitContext(SysError), 75 /// Error happened in FUSE. 76 #[error("fuse error: {0}")] 77 FuseError(fuse::Error), 78 /// Failed to get the uids for the worker thread. 79 #[error("failed to get uids for the worker thread: {0}")] 80 GetResuid(SysError), 81 /// Failed to get the securebits for the worker thread. 82 #[error("failed to get securebits for the worker thread: {0}")] 83 GetSecurebits(SysError), 84 /// A request is missing readable descriptors. 85 #[error("request does not have any readable descriptors")] 86 NoReadableDescriptors, 87 /// A request is missing writable descriptors. 88 #[error("request does not have any writable descriptors")] 89 NoWritableDescriptors, 90 /// Error while reading from the virtio queue's Event. 91 #[error("failed to read from virtio queue Event: {0}")] 92 ReadQueueEvent(SysError), 93 /// Failed to set the securebits for the worker thread. 94 #[error("failed to set securebits for the worker thread: {0}")] 95 SetSecurebits(SysError), 96 /// Failed to signal the virio used queue. 97 #[error("failed to signal used queue: {0}")] 98 SignalUsedQueue(SysError), 99 /// The tag for the Fs device was too long to fit in the config space. 100 #[error("Fs device tag is too long: len = {0}, max = {}", FS_MAX_TAG_LEN)] 101 TagTooLong(usize), 102 /// Calling unshare to disassociate FS attributes from parent failed. 103 #[error("failed to unshare fs from parent: {0}")] 104 UnshareFromParent(SysError), 105 /// Error while polling for events. 106 #[error("failed to wait for events: {0}")] 107 WaitError(SysError), 108 } 109 110 impl From<fuse::Error> for Error { from(err: fuse::Error) -> Error111 fn from(err: fuse::Error) -> Error { 112 Error::FuseError(err) 113 } 114 } 115 116 pub type Result<T> = ::std::result::Result<T, Error>; 117 118 pub struct Fs { 119 cfg: virtio_fs_config, 120 tag: String, 121 fs: Option<PassthroughFs>, 122 queue_sizes: Box<[u16]>, 123 avail_features: u64, 124 acked_features: u64, 125 pci_bar: Option<Alloc>, 126 tube: Option<Tube>, 127 workers: Vec<WorkerThread<Result<()>>>, 128 } 129 130 impl Fs { new( base_features: u64, tag: &str, num_workers: usize, fs_cfg: Config, tube: Tube, ) -> Result<Fs>131 pub fn new( 132 base_features: u64, 133 tag: &str, 134 num_workers: usize, 135 fs_cfg: Config, 136 tube: Tube, 137 ) -> Result<Fs> { 138 if tag.len() > FS_MAX_TAG_LEN { 139 return Err(Error::TagTooLong(tag.len())); 140 } 141 142 let mut cfg_tag = [0u8; FS_MAX_TAG_LEN]; 143 cfg_tag[..tag.len()].copy_from_slice(tag.as_bytes()); 144 145 let cfg = virtio_fs_config { 146 tag: cfg_tag, 147 num_request_queues: Le32::from(num_workers as u32), 148 }; 149 150 let fs = PassthroughFs::new(tag, fs_cfg).map_err(Error::CreateFs)?; 151 152 // There is always a high priority queue in addition to the request queues. 153 let num_queues = num_workers + 1; 154 155 Ok(Fs { 156 cfg, 157 tag: tag.to_string(), 158 fs: Some(fs), 159 queue_sizes: vec![QUEUE_SIZE; num_queues].into_boxed_slice(), 160 avail_features: base_features, 161 acked_features: 0, 162 pci_bar: None, 163 tube: Some(tube), 164 workers: Vec::with_capacity(num_workers + 1), 165 }) 166 } 167 } 168 169 impl VirtioDevice for Fs { keep_rds(&self) -> Vec<RawDescriptor>170 fn keep_rds(&self) -> Vec<RawDescriptor> { 171 let mut fds = self 172 .fs 173 .as_ref() 174 .map(PassthroughFs::keep_rds) 175 .unwrap_or_default(); 176 if let Some(rd) = self.tube.as_ref().map(|s| s.as_raw_descriptor()) { 177 fds.push(rd); 178 } 179 180 fds 181 } 182 device_type(&self) -> DeviceType183 fn device_type(&self) -> DeviceType { 184 DeviceType::Fs 185 } 186 queue_max_sizes(&self) -> &[u16]187 fn queue_max_sizes(&self) -> &[u16] { 188 &self.queue_sizes 189 } 190 features(&self) -> u64191 fn features(&self) -> u64 { 192 self.avail_features 193 } 194 ack_features(&mut self, mut v: u64)195 fn ack_features(&mut self, mut v: u64) { 196 // Check if the guest is ACK'ing a feature that we didn't claim to have. 197 let unrequested_features = v & !self.avail_features; 198 if unrequested_features != 0 { 199 warn!("virtio_fs got unknown feature ack: {:x}", v); 200 201 // Don't count these features as acked. 202 v &= !unrequested_features; 203 } 204 self.acked_features |= v; 205 } 206 read_config(&self, offset: u64, data: &mut [u8])207 fn read_config(&self, offset: u64, data: &mut [u8]) { 208 copy_config(data, 0, self.cfg.as_bytes(), offset) 209 } 210 activate( &mut self, _guest_mem: GuestMemory, interrupt: Interrupt, queues: BTreeMap<usize, Queue>, ) -> anyhow::Result<()>211 fn activate( 212 &mut self, 213 _guest_mem: GuestMemory, 214 interrupt: Interrupt, 215 queues: BTreeMap<usize, Queue>, 216 ) -> anyhow::Result<()> { 217 if queues.len() != self.queue_sizes.len() { 218 return Err(anyhow!( 219 "expected {} queues, got {}", 220 self.queue_sizes.len(), 221 queues.len() 222 )); 223 } 224 225 let fs = self.fs.take().expect("missing file system implementation"); 226 let use_dax = fs.cfg().use_dax; 227 228 let server = Arc::new(Server::new(fs)); 229 let socket = self.tube.take().expect("missing mapping socket"); 230 let mut slot = 0; 231 232 // Set up shared memory for DAX. 233 // TODO(b/176129399): Remove cfg! once DAX is supported on ARM. 234 if cfg!(target_arch = "x86_64") && use_dax { 235 // Create the shared memory region now before we start processing requests. 236 let request = FsMappingRequest::AllocateSharedMemoryRegion( 237 self.pci_bar.as_ref().cloned().expect("No pci_bar"), 238 ); 239 socket 240 .send(&request) 241 .expect("failed to send allocation message"); 242 slot = match socket.recv() { 243 Ok(VmResponse::RegisterMemory { slot }) => slot, 244 Ok(VmResponse::Err(e)) => panic!("failed to allocate shared memory region: {}", e), 245 r => panic!( 246 "unexpected response to allocate shared memory region: {:?}", 247 r 248 ), 249 }; 250 } 251 252 let socket = Arc::new(Mutex::new(socket)); 253 let mut watch_resample_event = true; 254 255 self.workers = queues 256 .into_iter() 257 .map(|(idx, queue)| { 258 let server = server.clone(); 259 let irq = interrupt.clone(); 260 let socket = Arc::clone(&socket); 261 262 let worker = 263 WorkerThread::start(format!("v_fs:{}:{}", self.tag, idx), move |kill_evt| { 264 let mut worker = Worker::new(queue, server, irq, socket, slot); 265 worker.run(kill_evt, watch_resample_event) 266 }); 267 268 if watch_resample_event { 269 watch_resample_event = false; 270 } 271 272 worker 273 }) 274 .collect(); 275 Ok(()) 276 } 277 get_device_bars(&mut self, address: PciAddress) -> Vec<PciBarConfiguration>278 fn get_device_bars(&mut self, address: PciAddress) -> Vec<PciBarConfiguration> { 279 if self.fs.as_ref().map_or(false, |fs| !fs.cfg().use_dax) { 280 return vec![]; 281 } 282 283 self.pci_bar = Some(Alloc::PciBar { 284 bus: address.bus, 285 dev: address.dev, 286 func: address.func, 287 bar: FS_BAR_NUM, 288 }); 289 290 vec![PciBarConfiguration::new( 291 FS_BAR_NUM as usize, 292 FS_BAR_SIZE, 293 PciBarRegionType::Memory64BitRegion, 294 PciBarPrefetchable::Prefetchable, 295 )] 296 } 297 get_device_caps(&self) -> Vec<Box<dyn PciCapability>>298 fn get_device_caps(&self) -> Vec<Box<dyn PciCapability>> { 299 if self.fs.as_ref().map_or(false, |fs| !fs.cfg().use_dax) { 300 return vec![]; 301 } 302 303 vec![Box::new(VirtioPciShmCap::new( 304 PciCapabilityType::SharedMemoryConfig, 305 FS_BAR_NUM, 306 FS_BAR_OFFSET, 307 FS_BAR_SIZE, 308 VIRTIO_FS_SHMCAP_ID_CACHE as u8, 309 ))] 310 } 311 } 312