fuse_backend_rs/transport/
mod.rs

1// Copyright (C) 2020 Alibaba Cloud. All rights reserved.
2//
3// Copyright 2019 The Chromium OS Authors. All rights reserved.
4// Use of this source code is governed by a BSD-style license that can be
5// found in the LICENSE-BSD-3-Clause file.
6//
7// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
8
9//! FUSE/Virtiofs transport drivers to receive requests from/send reply to Fuse/Virtiofs clients.
10//!
11//! Originally a FUSE server communicates with the FUSE driver through the device `/dev/fuse`,
12//! and the communication protocol is called as FUSE protocol. Later the FUSE protocol is extended
13//! to support Virtio-fs device. So there are two transport layers supported:
14//! - fusedev: communicate with the FUSE driver through `/dev/fuse`
15//! - virtiofs: communicate with the virtiofsd on host side by using virtio descriptors.
16
17use std::any::Any;
18use std::collections::VecDeque;
19use std::io::{self, IoSlice, Read};
20use std::marker::PhantomData;
21use std::mem::{size_of, MaybeUninit};
22use std::ptr::copy_nonoverlapping;
23use std::{cmp, fmt};
24
25use lazy_static::lazy_static;
26use libc::{sysconf, _SC_PAGESIZE};
27use vm_memory::{ByteValued, VolatileSlice};
28
29#[cfg(feature = "async-io")]
30use crate::file_buf::FileVolatileBuf;
31use crate::file_buf::FileVolatileSlice;
32#[cfg(feature = "async-io")]
33use crate::file_traits::AsyncFileReadWriteVolatile;
34use crate::file_traits::FileReadWriteVolatile;
35use crate::BitmapSlice;
36
37mod fs_cache_req_handler;
38#[cfg(feature = "fusedev")]
39mod fusedev;
40#[cfg(feature = "virtiofs")]
41mod virtiofs;
42
43pub use self::fs_cache_req_handler::FsCacheReqHandler;
44#[cfg(feature = "fusedev")]
45pub use self::fusedev::{FuseBuf, FuseChannel, FuseDevWriter, FuseSession};
46#[cfg(feature = "virtiofs")]
47pub use self::virtiofs::VirtioFsWriter;
48
49/// Transport layer specific error codes.
50#[derive(Debug)]
51pub enum Error {
52    /// Virtio queue descriptor chain overflows.
53    DescriptorChainOverflow,
54    /// Failed to find memory region for guest physical address.
55    FindMemoryRegion,
56    /// Invalid virtio queue descriptor chain.
57    InvalidChain,
58    /// Invalid paramater.
59    InvalidParameter,
60    /// Generic IO error.
61    IoError(io::Error),
62    /// Out of bounds when splitting VolatileSplice.
63    SplitOutOfBounds(usize),
64    /// Failed to access volatile memory.
65    VolatileMemoryError(vm_memory::VolatileMemoryError),
66    #[cfg(feature = "fusedev")]
67    /// Session errors
68    SessionFailure(String),
69    #[cfg(feature = "virtiofs")]
70    /// Failed to access guest memory.
71    GuestMemoryError(vm_memory::GuestMemoryError),
72    #[cfg(feature = "virtiofs")]
73    /// Invalid Indirect Virtio descriptors.
74    ConvertIndirectDescriptor(virtio_queue::Error),
75}
76
77impl fmt::Display for Error {
78    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
79        use self::Error::*;
80
81        match self {
82            DescriptorChainOverflow => write!(
83                f,
84                "the combined length of all the buffers in a `DescriptorChain` would overflow"
85            ),
86            FindMemoryRegion => write!(f, "no memory region for this address range"),
87            InvalidChain => write!(f, "invalid descriptor chain"),
88            InvalidParameter => write!(f, "invalid parameter"),
89            IoError(e) => write!(f, "descriptor I/O error: {e}"),
90            SplitOutOfBounds(off) => write!(f, "`DescriptorChain` split is out of bounds: {off}"),
91            VolatileMemoryError(e) => write!(f, "volatile memory error: {e}"),
92
93            #[cfg(feature = "fusedev")]
94            SessionFailure(e) => write!(f, "fuse session failure: {e}"),
95
96            #[cfg(feature = "virtiofs")]
97            ConvertIndirectDescriptor(e) => write!(f, "invalid indirect descriptor: {e}"),
98            #[cfg(feature = "virtiofs")]
99            GuestMemoryError(e) => write!(f, "descriptor guest memory error: {e}"),
100        }
101    }
102}
103
104impl From<Box<dyn Any + Send>> for Error {
105    fn from(value: Box<dyn Any + Send>) -> Self {
106        let err = value.downcast::<Error>().unwrap();
107        *err
108    }
109}
110
111/// Specialized version of [std::result::Result] for transport layer operations.
112pub type Result<T> = std::result::Result<T, Error>;
113
114impl std::error::Error for Error {}
115
116#[derive(Clone)]
117struct IoBuffers<'a, S> {
118    buffers: VecDeque<VolatileSlice<'a, S>>,
119    bytes_consumed: usize,
120}
121
122impl<S: BitmapSlice> Default for IoBuffers<'_, S> {
123    fn default() -> Self {
124        IoBuffers {
125            buffers: VecDeque::new(),
126            bytes_consumed: 0,
127        }
128    }
129}
130
131impl<S: BitmapSlice> IoBuffers<'_, S> {
132    fn available_bytes(&self) -> usize {
133        // This is guaranteed not to overflow because the total length of the chain
134        // is checked during all creations of `IoBuffers` (see
135        // `Reader::new()` and `Writer::new()`).
136        self.buffers
137            .iter()
138            .fold(0usize, |count, buf| count + buf.len())
139    }
140
141    fn bytes_consumed(&self) -> usize {
142        self.bytes_consumed
143    }
144
145    fn allocate_file_volatile_slice(&self, count: usize) -> Vec<FileVolatileSlice> {
146        let mut rem = count;
147        let mut bufs: Vec<FileVolatileSlice> = Vec::with_capacity(self.buffers.len());
148
149        for buf in &self.buffers {
150            if rem == 0 {
151                break;
152            }
153
154            // If buffer contains more data than `rem`, truncate buffer to `rem`, otherwise
155            // more data is written out and causes data corruption.
156            let local_buf = if buf.len() > rem {
157                // Safe because we just check rem < buf.len()
158                FileVolatileSlice::from_volatile_slice(&buf.subslice(0, rem).unwrap())
159            } else {
160                FileVolatileSlice::from_volatile_slice(buf)
161            };
162            bufs.push(local_buf);
163
164            // Don't need check_sub() as we just made sure rem >= local_buf.len()
165            rem -= local_buf.len();
166        }
167
168        bufs
169    }
170
171    #[cfg(feature = "async-io")]
172    unsafe fn prepare_io_buf(&self, count: usize) -> Vec<FileVolatileBuf> {
173        let mut rem = count;
174        let mut bufs = Vec::with_capacity(self.buffers.len());
175
176        for buf in &self.buffers {
177            if rem == 0 {
178                break;
179            }
180
181            // If buffer contains more data than `rem`, truncate buffer to `rem`, otherwise
182            // more data is written out and causes data corruption.
183            let local_buf = if buf.len() > rem {
184                // Safe because we just check rem < buf.len()
185                buf.subslice(0, rem).unwrap()
186            } else {
187                buf.clone()
188            };
189            // Safe because we just change the interface to access underlying buffers.
190            bufs.push(FileVolatileBuf::from_raw_ptr(
191                local_buf.as_ptr(),
192                local_buf.len(),
193                local_buf.len(),
194            ));
195
196            // Don't need check_sub() as we just made sure rem >= local_buf.len()
197            rem -= local_buf.len() as usize;
198        }
199
200        bufs
201    }
202
203    #[cfg(all(feature = "async-io", feature = "virtiofs"))]
204    unsafe fn prepare_mut_io_buf(&self, count: usize) -> Vec<FileVolatileBuf> {
205        let mut rem = count;
206        let mut bufs = Vec::with_capacity(self.buffers.len());
207
208        for buf in &self.buffers {
209            if rem == 0 {
210                break;
211            }
212
213            // If buffer contains more data than `rem`, truncate buffer to `rem`, otherwise
214            // more data is written out and causes data corruption.
215            let local_buf = if buf.len() > rem {
216                // Safe because we just check rem < buf.len()
217                buf.subslice(0, rem).unwrap()
218            } else {
219                buf.clone()
220            };
221            bufs.push(FileVolatileBuf::from_raw_ptr(
222                local_buf.as_ptr(),
223                0,
224                local_buf.len(),
225            ));
226
227            // Don't need check_sub() as we just made sure rem >= local_buf.len()
228            rem -= local_buf.len() as usize;
229        }
230
231        bufs
232    }
233
234    fn mark_dirty(&self, count: usize) {
235        let mut rem = count;
236
237        for buf in &self.buffers {
238            if rem == 0 {
239                break;
240            }
241
242            // If buffer contains more data than `rem`, truncate buffer to `rem`, otherwise
243            // more data is written out and causes data corruption.
244            let local_buf = if buf.len() > rem {
245                // Safe because we just check rem < buf.len()
246                buf.subslice(0, rem).unwrap()
247            } else {
248                buf.clone()
249            };
250            local_buf.bitmap().mark_dirty(0, local_buf.len());
251
252            // Don't need check_sub() as we just made sure rem >= local_buf.len()
253            rem -= local_buf.len();
254        }
255    }
256
257    fn mark_used(&mut self, bytes_consumed: usize) -> io::Result<()> {
258        // This can happen if a driver tricks a device into reading/writing more data than
259        // fits in a `usize`.
260        let total_bytes_consumed =
261            self.bytes_consumed
262                .checked_add(bytes_consumed)
263                .ok_or_else(|| {
264                    io::Error::new(io::ErrorKind::InvalidData, Error::DescriptorChainOverflow)
265                })?;
266
267        let mut rem = bytes_consumed;
268        while let Some(buf) = self.buffers.pop_front() {
269            if rem < buf.len() {
270                // Split the slice and push the remainder back into the buffer list. Safe because we
271                // know that `rem` is not out of bounds due to the check and we checked the bounds
272                // on `buf` when we added it to the buffer list.
273                self.buffers.push_front(buf.offset(rem).unwrap());
274                break;
275            }
276
277            // No need for checked math because we know that `buf.size() <= rem`.
278            rem -= buf.len();
279        }
280
281        self.bytes_consumed = total_bytes_consumed;
282
283        Ok(())
284    }
285
286    /// Consumes at most `count` bytes from the `DescriptorChain`. Callers must provide a function
287    /// that takes a `&[FileVolatileSlice]` and returns the total number of bytes consumed. This
288    /// function guarantees that the combined length of all the slices in the `&[FileVolatileSlice]` is
289    /// less than or equal to `count`. `mark_dirty` is used for tracing dirty pages.
290    ///
291    /// # Errors
292    ///
293    /// If the provided function returns any error then no bytes are consumed from the buffer and
294    /// the error is returned to the caller.
295    fn consume<F>(&mut self, mark_dirty: bool, count: usize, f: F) -> io::Result<usize>
296    where
297        F: FnOnce(&[FileVolatileSlice]) -> io::Result<usize>,
298    {
299        let bufs = self.allocate_file_volatile_slice(count);
300        if bufs.is_empty() {
301            Ok(0)
302        } else {
303            let bytes_consumed = f(&bufs)?;
304            if mark_dirty {
305                self.mark_dirty(bytes_consumed);
306            }
307            self.mark_used(bytes_consumed)?;
308            Ok(bytes_consumed)
309        }
310    }
311
312    fn consume_for_read<F>(&mut self, count: usize, f: F) -> io::Result<usize>
313    where
314        F: FnOnce(&[FileVolatileSlice]) -> io::Result<usize>,
315    {
316        self.consume(false, count, f)
317    }
318
319    fn split_at(&mut self, offset: usize) -> Result<Self> {
320        let mut rem = offset;
321        let pos = self.buffers.iter().position(|buf| {
322            if rem < buf.len() {
323                true
324            } else {
325                rem -= buf.len();
326                false
327            }
328        });
329
330        if let Some(at) = pos {
331            let mut other = self.buffers.split_off(at);
332
333            if rem > 0 {
334                // There must be at least one element in `other` because we checked
335                // its `size` value in the call to `position` above.
336                let front = other.pop_front().expect("empty VecDeque after split");
337                self.buffers
338                    .push_back(front.subslice(0, rem).map_err(Error::VolatileMemoryError)?);
339                other.push_front(front.offset(rem).map_err(Error::VolatileMemoryError)?);
340            }
341
342            Ok(IoBuffers {
343                buffers: other,
344                bytes_consumed: 0,
345            })
346        } else if rem == 0 {
347            Ok(IoBuffers {
348                buffers: VecDeque::new(),
349                bytes_consumed: 0,
350            })
351        } else {
352            Err(Error::SplitOutOfBounds(offset))
353        }
354    }
355}
356
357/// Reader to access FUSE requests from the transport layer data buffers.
358///
359/// Note that virtio spec requires driver to place any device-writable
360/// descriptors after any device-readable descriptors (2.6.4.2 in Virtio Spec v1.1).
361/// Reader will skip iterating over descriptor chain when first writable
362/// descriptor is encountered.
363#[derive(Clone)]
364pub struct Reader<'a, S = ()> {
365    buffers: IoBuffers<'a, S>,
366}
367
368impl<S: BitmapSlice> Default for Reader<'_, S> {
369    fn default() -> Self {
370        Reader {
371            buffers: IoBuffers::default(),
372        }
373    }
374}
375
376impl<S: BitmapSlice> Reader<'_, S> {
377    /// Reads an object from the descriptor chain buffer.
378    pub fn read_obj<T: ByteValued>(&mut self) -> io::Result<T> {
379        let mut obj = MaybeUninit::<T>::uninit();
380
381        // Safe because `MaybeUninit` guarantees that the pointer is valid for
382        // `size_of::<T>()` bytes.
383        let buf = unsafe {
384            ::std::slice::from_raw_parts_mut(obj.as_mut_ptr() as *mut u8, size_of::<T>())
385        };
386
387        self.read_exact(buf)?;
388
389        // Safe because any type that implements `ByteValued` can be considered initialized
390        // even if it is filled with random data.
391        Ok(unsafe { obj.assume_init() })
392    }
393
394    /// Reads data from the descriptor chain buffer into a file descriptor.
395    /// Returns the number of bytes read from the descriptor chain buffer.
396    /// The number of bytes read can be less than `count` if there isn't
397    /// enough data in the descriptor chain buffer.
398    pub fn read_to<F: FileReadWriteVolatile>(
399        &mut self,
400        mut dst: F,
401        count: usize,
402    ) -> io::Result<usize> {
403        self.buffers
404            .consume_for_read(count, |bufs| dst.write_vectored_volatile(bufs))
405    }
406
407    /// Reads data from the descriptor chain buffer into a File at offset `off`.
408    /// Returns the number of bytes read from the descriptor chain buffer.
409    /// The number of bytes read can be less than `count` if there isn't
410    /// enough data in the descriptor chain buffer.
411    pub fn read_to_at<F: FileReadWriteVolatile>(
412        &mut self,
413        mut dst: F,
414        count: usize,
415        off: u64,
416    ) -> io::Result<usize> {
417        self.buffers
418            .consume_for_read(count, |bufs| dst.write_vectored_at_volatile(bufs, off))
419    }
420
421    /// Reads exactly size of data from the descriptor chain buffer into a file descriptor.
422    pub fn read_exact_to<F: FileReadWriteVolatile>(
423        &mut self,
424        mut dst: F,
425        mut count: usize,
426    ) -> io::Result<()> {
427        while count > 0 {
428            match self.read_to(&mut dst, count) {
429                Ok(0) => {
430                    return Err(io::Error::new(
431                        io::ErrorKind::UnexpectedEof,
432                        "failed to fill whole buffer",
433                    ))
434                }
435                Ok(n) => count -= n,
436                Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
437                Err(e) => return Err(e),
438            }
439        }
440
441        Ok(())
442    }
443
444    /// Returns number of bytes available for reading.
445    ///
446    /// May return an error if the combined lengths of all the buffers in the DescriptorChain
447    /// would cause an integer overflow.
448    pub fn available_bytes(&self) -> usize {
449        self.buffers.available_bytes()
450    }
451
452    /// Returns number of bytes already read from the descriptor chain buffer.
453    pub fn bytes_read(&self) -> usize {
454        self.buffers.bytes_consumed()
455    }
456
457    /// Splits this `Reader` into two at the given offset in the `DescriptorChain` buffer.
458    /// After the split, `self` will be able to read up to `offset` bytes while the returned
459    /// `Reader` can read up to `available_bytes() - offset` bytes.  Returns an error if
460    /// `offset > self.available_bytes()`.
461    pub fn split_at(&mut self, offset: usize) -> Result<Self> {
462        self.buffers
463            .split_at(offset)
464            .map(|buffers| Reader { buffers })
465    }
466}
467
468impl<S: BitmapSlice> io::Read for Reader<'_, S> {
469    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
470        self.buffers.consume_for_read(buf.len(), |bufs| {
471            let mut rem = buf;
472            let mut total = 0;
473            for buf in bufs {
474                let copy_len = cmp::min(rem.len(), buf.len());
475
476                // Safe because we have already verified that `buf` points to valid memory.
477                unsafe {
478                    copy_nonoverlapping(buf.as_ptr() as *const u8, rem.as_mut_ptr(), copy_len);
479                }
480                rem = &mut rem[copy_len..];
481                total += copy_len;
482            }
483            Ok(total)
484        })
485    }
486}
487
488#[cfg(feature = "async-io")]
489mod async_io {
490    use super::*;
491
492    impl<'a, S: BitmapSlice> Reader<'a, S> {
493        /// Read data from the data buffer into a File at offset `off` in asynchronous mode.
494        ///
495        /// Return the number of bytes read from the data buffer. The number of bytes read can
496        /// be less than `count` if there isn't enough data in the buffer.
497        pub async fn async_read_to_at<F: AsyncFileReadWriteVolatile>(
498            &mut self,
499            dst: &F,
500            count: usize,
501            off: u64,
502        ) -> io::Result<usize> {
503            // Safe because `bufs` doesn't out-live `self`.
504            let bufs = unsafe { self.buffers.prepare_io_buf(count) };
505            if bufs.is_empty() {
506                Ok(0)
507            } else {
508                let (res, _) = dst.async_write_vectored_at_volatile(bufs, off).await;
509                match res {
510                    Ok(cnt) => {
511                        self.buffers.mark_used(cnt)?;
512                        Ok(cnt)
513                    }
514                    Err(e) => Err(e),
515                }
516            }
517        }
518    }
519}
520
521/// Writer to send reply message to '/dev/fuse` or virtiofs queue.
522pub enum Writer<'a, S: BitmapSlice = ()> {
523    #[cfg(feature = "fusedev")]
524    /// Writer for FuseDev transport driver.
525    FuseDev(FuseDevWriter<'a, S>),
526    #[cfg(feature = "virtiofs")]
527    /// Writer for virtiofs transport driver.
528    VirtioFs(VirtioFsWriter<'a, S>),
529    /// Writer for Noop transport driver.
530    Noop(PhantomData<&'a S>),
531}
532
533impl<'a, S: BitmapSlice> Writer<'a, S> {
534    /// Write data to the descriptor chain buffer from a File at offset `off`.
535    ///
536    /// Return the number of bytes written to the descriptor chain buffer.
537    pub fn write_from_at<F: FileReadWriteVolatile>(
538        &mut self,
539        src: F,
540        count: usize,
541        off: u64,
542    ) -> io::Result<usize> {
543        match self {
544            #[cfg(feature = "fusedev")]
545            Writer::FuseDev(w) => w.write_from_at(src, count, off),
546            #[cfg(feature = "virtiofs")]
547            Writer::VirtioFs(w) => w.write_from_at(src, count, off),
548            _ => Err(std::io::Error::from_raw_os_error(libc::EINVAL)),
549        }
550    }
551
552    /// Split this `Writer` into two at the given offset in the `DescriptorChain` buffer.
553    ///
554    /// After the split, `self` will be able to write up to `offset` bytes while the returned
555    /// `Writer` can write up to `available_bytes() - offset` bytes.  Return an error if
556    /// `offset > self.available_bytes()`.
557    pub fn split_at(&mut self, offset: usize) -> Result<Self> {
558        match self {
559            #[cfg(feature = "fusedev")]
560            Writer::FuseDev(w) => w.split_at(offset).map(|w| w.into()),
561            #[cfg(feature = "virtiofs")]
562            Writer::VirtioFs(w) => w.split_at(offset).map(|w| w.into()),
563            _ => Err(Error::InvalidParameter),
564        }
565    }
566
567    /// Return number of bytes available for writing.
568    ///
569    /// May return an error if the combined lengths of all the buffers in the DescriptorChain would
570    /// cause an overflow.
571    pub fn available_bytes(&self) -> usize {
572        match self {
573            #[cfg(feature = "fusedev")]
574            Writer::FuseDev(w) => w.available_bytes(),
575            #[cfg(feature = "virtiofs")]
576            Writer::VirtioFs(w) => w.available_bytes(),
577            _ => 0,
578        }
579    }
580
581    /// Return number of bytes already written to the descriptor chain buffer.
582    pub fn bytes_written(&self) -> usize {
583        match self {
584            #[cfg(feature = "fusedev")]
585            Writer::FuseDev(w) => w.bytes_written(),
586            #[cfg(feature = "virtiofs")]
587            Writer::VirtioFs(w) => w.bytes_written(),
588            _ => 0,
589        }
590    }
591
592    /// Commit all internal buffers of self and others
593    pub fn commit(&mut self, other: Option<&Self>) -> io::Result<usize> {
594        match self {
595            #[cfg(feature = "fusedev")]
596            Writer::FuseDev(w) => w.commit(other),
597            #[cfg(feature = "virtiofs")]
598            Writer::VirtioFs(w) => w.commit(other),
599            _ => Ok(0),
600        }
601    }
602}
603
604impl<'a, S: BitmapSlice> io::Write for Writer<'a, S> {
605    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
606        match self {
607            #[cfg(feature = "fusedev")]
608            Writer::FuseDev(w) => w.write(buf),
609            #[cfg(feature = "virtiofs")]
610            Writer::VirtioFs(w) => w.write(buf),
611            _ => Err(std::io::Error::from_raw_os_error(libc::EINVAL)),
612        }
613    }
614
615    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
616        match self {
617            #[cfg(feature = "fusedev")]
618            Writer::FuseDev(w) => w.write_vectored(bufs),
619            #[cfg(feature = "virtiofs")]
620            Writer::VirtioFs(w) => w.write_vectored(bufs),
621            _ => Err(std::io::Error::from_raw_os_error(libc::EINVAL)),
622        }
623    }
624
625    fn flush(&mut self) -> io::Result<()> {
626        match self {
627            #[cfg(feature = "fusedev")]
628            Writer::FuseDev(w) => w.flush(),
629            #[cfg(feature = "virtiofs")]
630            Writer::VirtioFs(w) => w.flush(),
631            _ => Ok(()),
632        }
633    }
634}
635
636#[cfg(feature = "async-io")]
637impl<'a, S: BitmapSlice> Writer<'a, S> {
638    /// Write data from a buffer into this writer in asynchronous mode.
639    pub async fn async_write(&mut self, data: &[u8]) -> io::Result<usize> {
640        match self {
641            #[cfg(feature = "fusedev")]
642            Writer::FuseDev(w) => w.async_write(data).await,
643            #[cfg(feature = "virtiofs")]
644            Writer::VirtioFs(w) => w.async_write(data).await,
645            _ => Err(std::io::Error::from_raw_os_error(libc::EINVAL)),
646        }
647    }
648
649    /// Write data from two buffers into this writer in asynchronous mode.
650    pub async fn async_write2(&mut self, data: &[u8], data2: &[u8]) -> io::Result<usize> {
651        match self {
652            #[cfg(feature = "fusedev")]
653            Writer::FuseDev(w) => w.async_write2(data, data2).await,
654            #[cfg(feature = "virtiofs")]
655            Writer::VirtioFs(w) => w.async_write2(data, data2).await,
656            _ => Err(std::io::Error::from_raw_os_error(libc::EINVAL)),
657        }
658    }
659
660    /// Write data from three buffers into this writer in asynchronous mode.
661    pub async fn async_write3(
662        &mut self,
663        data: &[u8],
664        data2: &[u8],
665        data3: &[u8],
666    ) -> io::Result<usize> {
667        match self {
668            #[cfg(feature = "fusedev")]
669            Writer::FuseDev(w) => w.async_write3(data, data2, data3).await,
670            #[cfg(feature = "virtiofs")]
671            Writer::VirtioFs(w) => w.async_write3(data, data2, data3).await,
672            _ => Err(std::io::Error::from_raw_os_error(libc::EINVAL)),
673        }
674    }
675
676    /// Attempt to write an entire buffer into this writer in asynchronous mode.
677    pub async fn async_write_all(&mut self, buf: &[u8]) -> io::Result<()> {
678        match self {
679            #[cfg(feature = "fusedev")]
680            Writer::FuseDev(w) => w.async_write_all(buf).await,
681            #[cfg(feature = "virtiofs")]
682            Writer::VirtioFs(w) => w.async_write_all(buf).await,
683            _ => Err(std::io::Error::from_raw_os_error(libc::EINVAL)),
684        }
685    }
686
687    /// Asynchronously write data to the descriptor chain buffer from a File at offset `off`.
688    ///
689    /// Return the number of bytes written to the descriptor chain buffer.
690    pub async fn async_write_from_at<F: AsyncFileReadWriteVolatile>(
691        &mut self,
692        src: &F,
693        count: usize,
694        off: u64,
695    ) -> io::Result<usize> {
696        match self {
697            #[cfg(feature = "fusedev")]
698            Writer::FuseDev(w) => w.async_write_from_at(src, count, off).await,
699            #[cfg(feature = "virtiofs")]
700            Writer::VirtioFs(w) => w.async_write_from_at(src, count, off).await,
701            _ => Err(std::io::Error::from_raw_os_error(libc::EINVAL)),
702        }
703    }
704
705    /// Commit all internal buffers of self and others
706    pub async fn async_commit(&mut self, other: Option<&Writer<'a, S>>) -> io::Result<usize> {
707        match self {
708            #[cfg(feature = "fusedev")]
709            Writer::FuseDev(w) => w.async_commit(other).await,
710            #[cfg(feature = "virtiofs")]
711            Writer::VirtioFs(w) => w.async_commit(other).await,
712            _ => Err(std::io::Error::from_raw_os_error(libc::EINVAL)),
713        }
714    }
715}
716
717#[cfg(feature = "fusedev")]
718impl<'a, S: BitmapSlice> From<FuseDevWriter<'a, S>> for Writer<'a, S> {
719    fn from(w: FuseDevWriter<'a, S>) -> Self {
720        Writer::FuseDev(w)
721    }
722}
723
724#[cfg(feature = "virtiofs")]
725impl<'a, S: BitmapSlice> From<VirtioFsWriter<'a, S>> for Writer<'a, S> {
726    fn from(w: VirtioFsWriter<'a, S>) -> Self {
727        Writer::VirtioFs(w)
728    }
729}
730
731lazy_static! {
732    static ref PAGESIZE: usize = unsafe { sysconf(_SC_PAGESIZE) as usize };
733}
734
735/// Safe wrapper for `sysconf(_SC_PAGESIZE)`.
736#[inline(always)]
737pub fn pagesize() -> usize {
738    *PAGESIZE
739}
740
741#[cfg(test)]
742mod tests {
743    use crate::transport::IoBuffers;
744    use std::collections::VecDeque;
745    use vm_memory::{
746        bitmap::{AtomicBitmap, Bitmap},
747        VolatileSlice,
748    };
749
750    #[test]
751    fn test_io_buffers() {
752        let mut buf1 = vec![0x0u8; 16];
753        let mut buf2 = vec![0x0u8; 16];
754        let mut bufs = VecDeque::new();
755        unsafe {
756            bufs.push_back(VolatileSlice::new(buf1.as_mut_ptr(), buf1.len()));
757            bufs.push_back(VolatileSlice::new(buf2.as_mut_ptr(), buf2.len()));
758        }
759        let mut buffers = IoBuffers {
760            buffers: bufs,
761            bytes_consumed: 0,
762        };
763
764        assert_eq!(buffers.available_bytes(), 32);
765        assert_eq!(buffers.bytes_consumed(), 0);
766
767        assert_eq!(
768            buffers.consume_for_read(2, |buf| Ok(buf[0].len())).unwrap(),
769            2
770        );
771        assert_eq!(buffers.available_bytes(), 30);
772        assert_eq!(buffers.bytes_consumed(), 2);
773
774        let mut buffers2 = buffers.split_at(10).unwrap();
775        assert_eq!(buffers.available_bytes(), 10);
776        assert_eq!(buffers.bytes_consumed(), 2);
777        assert_eq!(buffers2.available_bytes(), 20);
778        assert_eq!(buffers2.bytes_consumed(), 0);
779
780        assert_eq!(
781            buffers2
782                .consume_for_read(10, |buf| Ok(buf[0].len() + buf[1].len()))
783                .unwrap(),
784            10
785        );
786        assert_eq!(
787            buffers2
788                .consume_for_read(20, |buf| Ok(buf[0].len()))
789                .unwrap(),
790            10
791        );
792
793        let _buffers3 = buffers2.split_at(0).unwrap();
794        assert!(buffers2.split_at(1).is_err());
795    }
796
797    #[test]
798    fn test_mark_dirty() {
799        let mut buf1 = vec![0x0u8; 16];
800        let bitmap1 = AtomicBitmap::new(16, 2);
801
802        assert_eq!(bitmap1.len(), 8);
803        for i in 0..8 {
804            assert_eq!(bitmap1.is_bit_set(i), false);
805        }
806
807        let mut buf2 = vec![0x0u8; 16];
808        let bitmap2 = AtomicBitmap::new(16, 2);
809        let mut bufs = VecDeque::new();
810
811        unsafe {
812            bufs.push_back(VolatileSlice::with_bitmap(
813                buf1.as_mut_ptr(),
814                buf1.len(),
815                bitmap1.slice_at(0),
816            ));
817            bufs.push_back(VolatileSlice::with_bitmap(
818                buf2.as_mut_ptr(),
819                buf2.len(),
820                bitmap2.slice_at(0),
821            ));
822        }
823        let mut buffers = IoBuffers {
824            buffers: bufs,
825            bytes_consumed: 0,
826        };
827
828        assert_eq!(buffers.available_bytes(), 32);
829        assert_eq!(buffers.bytes_consumed(), 0);
830
831        assert_eq!(
832            buffers.consume_for_read(8, |buf| Ok(buf[0].len())).unwrap(),
833            8
834        );
835
836        assert_eq!(buffers.available_bytes(), 24);
837        assert_eq!(buffers.bytes_consumed(), 8);
838
839        for i in 0..8 {
840            assert_eq!(bitmap1.is_bit_set(i), false);
841        }
842
843        assert_eq!(
844            buffers
845                .consume(true, 16, |buf| Ok(buf[0].len() + buf[1].len()))
846                .unwrap(),
847            16
848        );
849        assert_eq!(buffers.available_bytes(), 8);
850        assert_eq!(buffers.bytes_consumed(), 24);
851        for i in 0..8 {
852            if i >= 4 {
853                assert_eq!(bitmap1.is_bit_set(i), true);
854                continue;
855            } else {
856                assert_eq!(bitmap1.is_bit_set(i), false);
857            }
858        }
859        for i in 0..8 {
860            if i < 4 {
861                assert_eq!(bitmap2.is_bit_set(i), true);
862            } else {
863                assert_eq!(bitmap2.is_bit_set(i), false);
864            }
865        }
866    }
867}