fuse_backend_rs/transport/virtiofs/
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//! Traits and Structs to implement the virtiofs transport driver.
10//!
11//! Virtio-fs is a shared file system that lets virtual machines access a directory tree
12//! on the host. Unlike existing approaches, it is designed to offer local file system
13//! semantics and performance. Virtualization allows multiple virtual machines (VMs) to
14//! run on a single physical host. Although VMs are isolated and run separate operating
15//! system instances, their proximity on the physical host allows for fast shared memory
16//! access.
17//!
18//! Virtio-fs uses FUSE as the foundation. FUSE has no dependencies on a networking stack
19//! and exposes a rich native Linux file system interface that allows virtio-fs to act
20//! like a local file system. Both the semantics and the performance of communication of
21//! co-located VMs are different from the networking model for which remote file systems
22//! were designed.
23//!
24//! Unlike traditional FUSE where the file system daemon runs in userspace, the virtio-fs
25//! daemon runs on the host. A VIRTIO device carries FUSE messages and provides extensions
26//! for advanced features not available in traditional FUSE.
27//! The main extension to the FUSE protocol is the virtio-fs DAX Window, which supports
28//! memory mapping the contents of files. The virtio-fs VIRTIO device implements this
29//! as a shared memory region exposed through a PCI/MMIO BAR. This feature is
30//! virtualization-specific and is not available outside of virtio-fs.
31//!
32//! Although virtio-fs uses FUSE as the protocol, it does not function as a new transport
33//! for existing FUSE applications. It is not possible to run existing FUSE file systems
34//! unmodified because virtio-fs has a different security model and extends the FUSE protocol.
35//! Existing FUSE file systems trust the client because it is the kernel. There would be no
36//! reason for the kernel to attack the file system since the kernel already has full control
37//! of the host. In virtio-fs the client is the untrusted VM and the file system daemon must
38//! not trust it. Therefore, virtio-fs server uses a hardened FUSE implementation that does
39//! not trust the client.
40
41use std::cmp;
42use std::collections::VecDeque;
43use std::io::{self, IoSlice, Write};
44use std::ops::Deref;
45use std::ptr::copy_nonoverlapping;
46
47use virtio_queue::DescriptorChain;
48use vm_memory::bitmap::{BitmapSlice, MS};
49use vm_memory::{Address, ByteValued, GuestMemory, GuestMemoryRegion, MemoryRegionAddress};
50
51use super::{Error, FileReadWriteVolatile, FileVolatileSlice, IoBuffers, Reader, Result, Writer};
52
53impl<S: BitmapSlice> IoBuffers<'_, S> {
54    /// Consumes for write.
55    fn consume_for_write<F>(&mut self, count: usize, f: F) -> io::Result<usize>
56    where
57        F: FnOnce(&[FileVolatileSlice]) -> io::Result<usize>,
58    {
59        self.consume(true, count, f)
60    }
61}
62
63impl<'a> Reader<'a> {
64    /// Construct a new Reader wrapper over `desc_chain`.
65    pub fn from_descriptor_chain<M>(
66        mem: &'a M::Target,
67        desc_chain: DescriptorChain<M>,
68    ) -> Result<Reader<'a, MS<'a, M::Target>>>
69    where
70        M: Deref,
71        M::Target: GuestMemory + Sized,
72    {
73        let mut total_len: usize = 0;
74        // Allocate VecDeque with 64 capacity and hope it could hold all slices to avoid expending
75        // VecDeque repeatedly.
76        let mut buffers = VecDeque::with_capacity(64);
77        for desc in desc_chain.readable() {
78            // Verify that summing the descriptor sizes does not overflow.
79            // This can happen if a driver tricks a device into reading more data than
80            // fits in a `usize`.
81            total_len = total_len
82                .checked_add(desc.len() as usize)
83                .ok_or(Error::DescriptorChainOverflow)?;
84
85            let region = mem
86                .find_region(desc.addr())
87                .ok_or(Error::FindMemoryRegion)?;
88            let offset = desc
89                .addr()
90                .checked_sub(region.start_addr().raw_value())
91                .unwrap();
92
93            buffers.push_back(
94                region
95                    .get_slice(MemoryRegionAddress(offset.raw_value()), desc.len() as usize)
96                    .map_err(Error::GuestMemoryError)?,
97            );
98        }
99
100        Ok(Reader {
101            buffers: IoBuffers {
102                buffers,
103                bytes_consumed: 0,
104            },
105        })
106    }
107}
108
109/// Provide high-level interface over the sequence of memory regions
110/// defined by writable descriptors in the Virtio descriptor chain.
111///
112/// Note that virtio spec requires driver to place any device-writable
113/// descriptors after any device-readable descriptors (2.6.4.2 in Virtio Spec v1.1).
114/// Writer will start iterating the descriptors from the first writable one and will
115/// assume that all following descriptors are writable.
116#[derive(Clone)]
117pub struct VirtioFsWriter<'a, S = ()> {
118    buffers: IoBuffers<'a, S>,
119}
120
121impl<'a> VirtioFsWriter<'a> {
122    /// Construct a new [Writer] wrapper over `desc_chain`.
123    pub fn new<M>(
124        mem: &'a M::Target,
125        desc_chain: DescriptorChain<M>,
126    ) -> Result<VirtioFsWriter<'a, MS<'a, M::Target>>>
127    where
128        M: Deref,
129        M::Target: GuestMemory + Sized,
130    {
131        let mut total_len: usize = 0;
132        // Allocate VecDeque with 64 capacity and hope it could hold all slices to avoid expending
133        // VecDeque repeatedly.
134        let mut buffers = VecDeque::with_capacity(64);
135        for desc in desc_chain.writable() {
136            // Verify that summing the descriptor sizes does not overflow.
137            // This can happen if a driver tricks a device into writing more data than
138            // fits in a `usize`.
139            total_len = total_len
140                .checked_add(desc.len() as usize)
141                .ok_or(Error::DescriptorChainOverflow)?;
142
143            let region = mem
144                .find_region(desc.addr())
145                .ok_or(Error::FindMemoryRegion)?;
146            let offset = desc
147                .addr()
148                .checked_sub(region.start_addr().raw_value())
149                .unwrap();
150
151            buffers.push_back(
152                region
153                    .get_slice(MemoryRegionAddress(offset.raw_value()), desc.len() as usize)
154                    .map_err(Error::GuestMemoryError)?,
155            )
156        }
157
158        Ok(VirtioFsWriter {
159            buffers: IoBuffers {
160                buffers,
161                bytes_consumed: 0,
162            },
163        })
164    }
165}
166
167impl<'a, S: BitmapSlice> VirtioFsWriter<'a, S> {
168    /// Write an object to the descriptor chain buffer.
169    pub fn write_obj<T: ByteValued>(&mut self, val: T) -> io::Result<()> {
170        self.write_all(val.as_slice())
171    }
172
173    /// Write data to the descriptor chain buffer from a file descriptor.
174    ///
175    /// Return the number of bytes written to the descriptor chain buffer.
176    pub fn write_from<F: FileReadWriteVolatile>(
177        &mut self,
178        mut src: F,
179        count: usize,
180    ) -> io::Result<usize> {
181        self.check_available_space(count, 0, 0)?;
182        self.buffers
183            .consume_for_write(count, |bufs| src.read_vectored_volatile(bufs))
184    }
185
186    /// Write data to the descriptor chain buffer from a File at offset `off`.
187    ///
188    /// Return the number of bytes written to the descriptor chain buffer.
189    pub fn write_from_at<F: FileReadWriteVolatile>(
190        &mut self,
191        mut src: F,
192        count: usize,
193        off: u64,
194    ) -> io::Result<usize> {
195        self.check_available_space(count, 0, 0)?;
196        self.buffers
197            .consume_for_write(count, |bufs| src.read_vectored_at_volatile(bufs, off))
198    }
199
200    /// Write all data to the descriptor chain buffer from a file descriptor.
201    pub fn write_all_from<F: FileReadWriteVolatile>(
202        &mut self,
203        mut src: F,
204        mut count: usize,
205    ) -> io::Result<()> {
206        self.check_available_space(count, 0, 0)?;
207        while count > 0 {
208            match self.write_from(&mut src, count) {
209                Ok(0) => {
210                    return Err(io::Error::new(
211                        io::ErrorKind::WriteZero,
212                        "failed to write whole buffer",
213                    ))
214                }
215                Ok(n) => count -= n,
216                Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
217                Err(e) => return Err(e),
218            }
219        }
220
221        Ok(())
222    }
223
224    /// Return number of bytes available for writing.
225    ///
226    /// May return an error if the combined lengths of all the buffers in the DescriptorChain would
227    /// cause an overflow.
228    pub fn available_bytes(&self) -> usize {
229        self.buffers.available_bytes()
230    }
231
232    /// Return number of bytes already written to the descriptor chain buffer.
233    pub fn bytes_written(&self) -> usize {
234        self.buffers.bytes_consumed()
235    }
236
237    /// Split this `Writer` into two at the given offset in the `DescriptorChain` buffer.
238    /// After the split, `self` will be able to write up to `offset` bytes while the returned
239    /// `Writer` can write up to `available_bytes() - offset` bytes.  Returns an error if
240    /// `offset > self.available_bytes()`.
241    pub fn split_at(&mut self, offset: usize) -> Result<Self> {
242        self.buffers
243            .split_at(offset)
244            .map(|buffers| VirtioFsWriter { buffers })
245    }
246
247    /// Commit all internal buffers of self and others
248    ///
249    /// This is provided just to be compatible with fusedev
250    pub fn commit(&mut self, _other: Option<&Writer<'a, S>>) -> io::Result<usize> {
251        Ok(0)
252    }
253
254    fn check_available_space(&self, len1: usize, len2: usize, len3: usize) -> io::Result<()> {
255        let len = len1
256            .checked_add(len2)
257            .ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "buffer size is too big"))?;
258        let len = len
259            .checked_add(len3)
260            .ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "buffer size is too big"))?;
261        if len > self.available_bytes() {
262            Err(io::Error::new(
263                io::ErrorKind::InvalidData,
264                format!(
265                    "data out of range, available {} requested {}",
266                    self.available_bytes(),
267                    len
268                ),
269            ))
270        } else {
271            Ok(())
272        }
273    }
274}
275
276impl<S: BitmapSlice> io::Write for VirtioFsWriter<'_, S> {
277    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
278        self.check_available_space(buf.len(), 0, 0)?;
279
280        self.buffers.consume_for_write(buf.len(), |bufs| {
281            let mut rem = buf;
282            let mut total = 0;
283            for buf in bufs {
284                let copy_len = cmp::min(rem.len(), buf.len());
285
286                // Safe because we have already verified that `buf` points to valid memory.
287                unsafe {
288                    copy_nonoverlapping(rem.as_ptr(), buf.as_ptr(), copy_len);
289                }
290                rem = &rem[copy_len..];
291                total += copy_len;
292            }
293            Ok(total)
294        })
295    }
296
297    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
298        self.check_available_space(bufs.iter().fold(0, |acc, x| acc + x.len()), 0, 0)?;
299
300        let mut count = 0;
301        for buf in bufs.iter().filter(|b| !b.is_empty()) {
302            count += self.write(buf)?;
303        }
304        Ok(count)
305    }
306
307    fn flush(&mut self) -> io::Result<()> {
308        // Nothing to flush since the writes go straight into the buffer.
309        Ok(())
310    }
311}
312
313// For Virtio-fs, the output is written to memory buffer, so no need for async io at all.
314// Just relay the operation to corresponding sync io handler.
315#[cfg(feature = "async-io")]
316mod async_io {
317    use super::*;
318    use crate::transport::AsyncFileReadWriteVolatile;
319
320    impl<'a, S: BitmapSlice> VirtioFsWriter<'a, S> {
321        /// Write data from a buffer into this writer in asynchronous mode.
322        pub async fn async_write(&mut self, data: &[u8]) -> io::Result<usize> {
323            self.write(data)
324        }
325
326        /// Write data from two buffers into this writer in asynchronous mode.
327        pub async fn async_write2(&mut self, data: &[u8], data2: &[u8]) -> io::Result<usize> {
328            self.check_available_space(data.len(), data2.len(), 0)?;
329            let mut cnt = self.write(data)?;
330            cnt += self.write(data2)?;
331
332            Ok(cnt)
333        }
334
335        /// Write data from three buffers into this writer in asynchronous mode.
336        pub async fn async_write3(
337            &mut self,
338            data: &[u8],
339            data2: &[u8],
340            data3: &[u8],
341        ) -> io::Result<usize> {
342            self.check_available_space(data.len(), data2.len(), data3.len())?;
343            let mut cnt = self.write(data)?;
344            cnt += self.write(data2)?;
345            cnt += self.write(data3)?;
346
347            Ok(cnt)
348        }
349
350        /// Attempts to write an entire buffer into this writer in asynchronous mode.
351        pub async fn async_write_all(&mut self, buf: &[u8]) -> io::Result<()> {
352            self.write_all(buf)
353        }
354
355        /// Writes data to the descriptor chain buffer from a File at offset `off`.
356        /// Returns the number of bytes written to the descriptor chain buffer.
357        pub async fn async_write_from_at<F: AsyncFileReadWriteVolatile>(
358            &mut self,
359            src: &F,
360            count: usize,
361            off: u64,
362        ) -> io::Result<usize> {
363            self.check_available_space(count, 0, 0)?;
364            // Safe because `bufs` doesn't out-live `self`.
365            let bufs = unsafe { self.buffers.prepare_mut_io_buf(count) };
366            if bufs.is_empty() {
367                Ok(0)
368            } else {
369                let (res, _) = src.async_read_vectored_at_volatile(bufs, off).await;
370                match res {
371                    Ok(cnt) => {
372                        self.buffers.mark_dirty(cnt);
373                        self.buffers.mark_used(cnt)?;
374                        Ok(cnt)
375                    }
376                    Err(e) => Err(e),
377                }
378            }
379        }
380
381        /// Commit all internal buffers of self and others
382        /// We need this because the lifetime of others is usually shorter than self.
383        pub async fn async_commit(&mut self, other: Option<&Writer<'a, S>>) -> io::Result<usize> {
384            self.commit(other)
385        }
386    }
387}
388
389/// Disabled since vm-virtio doesn't export any DescriptorChain constructors.
390/// Should re-enable once it does.
391#[cfg(testff)]
392mod tests {
393    use super::*;
394    use std::io::{Read, Seek, SeekFrom, Write};
395    use vm_memory::{Address, ByteValued, Bytes, GuestAddress, GuestMemoryMmap, Le16, Le32, Le64};
396    use vmm_sys_util::tempfile::TempFile;
397
398    const VIRTQ_DESC_F_NEXT: u16 = 0x1;
399    const VIRTQ_DESC_F_WRITE: u16 = 0x2;
400
401    #[derive(Copy, Clone, PartialEq, Eq)]
402    pub enum DescriptorType {
403        Readable,
404        Writable,
405    }
406
407    #[derive(Copy, Clone, Debug, Default)]
408    #[repr(C)]
409    struct virtq_desc {
410        addr: Le64,
411        len: Le32,
412        flags: Le16,
413        next: Le16,
414    }
415
416    // Safe because it only has data and has no implicit padding.
417    unsafe impl ByteValued for virtq_desc {}
418
419    /// Test utility function to create a descriptor chain in guest memory.
420    pub fn create_descriptor_chain(
421        memory: &GuestMemoryMmap,
422        descriptor_array_addr: GuestAddress,
423        mut buffers_start_addr: GuestAddress,
424        descriptors: Vec<(DescriptorType, u32)>,
425        spaces_between_regions: u32,
426    ) -> Result<DescriptorChain<GuestMemoryMmap>> {
427        let descriptors_len = descriptors.len();
428        for (index, (type_, size)) in descriptors.into_iter().enumerate() {
429            let mut flags = 0;
430            if let DescriptorType::Writable = type_ {
431                flags |= VIRTQ_DESC_F_WRITE;
432            }
433            if index + 1 < descriptors_len {
434                flags |= VIRTQ_DESC_F_NEXT;
435            }
436
437            let index = index as u16;
438            let desc = virtq_desc {
439                addr: buffers_start_addr.raw_value().into(),
440                len: size.into(),
441                flags: flags.into(),
442                next: (index + 1).into(),
443            };
444
445            let offset = size + spaces_between_regions;
446            buffers_start_addr = buffers_start_addr
447                .checked_add(u64::from(offset))
448                .ok_or(Error::InvalidChain)?;
449
450            let _ = memory.write_obj(
451                desc,
452                descriptor_array_addr
453                    .checked_add(u64::from(index) * std::mem::size_of::<virtq_desc>() as u64)
454                    .ok_or(Error::InvalidChain)?,
455            );
456        }
457
458        DescriptorChain::<&GuestMemoryMmap>::new(memory, descriptor_array_addr, 0x100, 0)
459            .ok_or(Error::InvalidChain)
460    }
461
462    #[test]
463    fn reader_test_simple_chain() {
464        use DescriptorType::*;
465
466        let memory_start_addr = GuestAddress(0x0);
467        let memory = GuestMemoryMmap::from_ranges(&vec![(memory_start_addr, 0x10000)]).unwrap();
468
469        let chain = create_descriptor_chain(
470            &memory,
471            GuestAddress(0x0),
472            GuestAddress(0x100),
473            vec![
474                (Readable, 8),
475                (Readable, 16),
476                (Readable, 18),
477                (Readable, 64),
478            ],
479            0,
480        )
481        .expect("create_descriptor_chain failed");
482        let mut reader = Reader::new(&memory, chain).expect("failed to create Reader");
483        assert_eq!(reader.available_bytes(), 106);
484        assert_eq!(reader.bytes_read(), 0);
485
486        let mut buffer = [0 as u8; 64];
487        if let Err(_) = reader.read_exact(&mut buffer) {
488            panic!("read_exact should not fail here");
489        }
490
491        assert_eq!(reader.available_bytes(), 42);
492        assert_eq!(reader.bytes_read(), 64);
493
494        match reader.read(&mut buffer) {
495            Err(_) => panic!("read should not fail here"),
496            Ok(length) => assert_eq!(length, 42),
497        }
498
499        assert_eq!(reader.available_bytes(), 0);
500        assert_eq!(reader.bytes_read(), 106);
501    }
502
503    #[test]
504    fn writer_test_simple_chain() {
505        use DescriptorType::*;
506
507        let memory_start_addr = GuestAddress(0x0);
508        let memory = GuestMemoryMmap::from_ranges(&vec![(memory_start_addr, 0x10000)]).unwrap();
509
510        let chain = create_descriptor_chain(
511            &memory,
512            GuestAddress(0x0),
513            GuestAddress(0x100),
514            vec![
515                (Writable, 8),
516                (Writable, 16),
517                (Writable, 18),
518                (Writable, 64),
519            ],
520            0,
521        )
522        .expect("create_descriptor_chain failed");
523        let mut writer = VirtioFsWriter::new(&memory, chain).expect("failed to create Writer");
524        assert_eq!(writer.available_bytes(), 106);
525        assert_eq!(writer.bytes_written(), 0);
526
527        let mut buffer = [0 as u8; 64];
528        if let Err(_) = writer.write_all(&mut buffer) {
529            panic!("write_all should not fail here");
530        }
531
532        assert_eq!(writer.available_bytes(), 42);
533        assert_eq!(writer.bytes_written(), 64);
534
535        let mut buffer = [0 as u8; 42];
536        match writer.write(&mut buffer) {
537            Err(_) => panic!("write should not fail here"),
538            Ok(length) => assert_eq!(length, 42),
539        }
540
541        assert_eq!(writer.available_bytes(), 0);
542        assert_eq!(writer.bytes_written(), 106);
543    }
544
545    #[test]
546    fn reader_test_incompatible_chain() {
547        use DescriptorType::*;
548
549        let memory_start_addr = GuestAddress(0x0);
550        let memory = GuestMemoryMmap::from_ranges(&vec![(memory_start_addr, 0x10000)]).unwrap();
551
552        let chain = create_descriptor_chain(
553            &memory,
554            GuestAddress(0x0),
555            GuestAddress(0x100),
556            vec![(Writable, 8)],
557            0,
558        )
559        .expect("create_descriptor_chain failed");
560        let mut reader = Reader::new(&memory, chain).expect("failed to create Reader");
561        assert_eq!(reader.available_bytes(), 0);
562        assert_eq!(reader.bytes_read(), 0);
563
564        assert!(reader.read_obj::<u8>().is_err());
565
566        assert_eq!(reader.available_bytes(), 0);
567        assert_eq!(reader.bytes_read(), 0);
568    }
569
570    #[test]
571    fn writer_test_incompatible_chain() {
572        use DescriptorType::*;
573
574        let memory_start_addr = GuestAddress(0x0);
575        let memory = GuestMemoryMmap::from_ranges(&vec![(memory_start_addr, 0x10000)]).unwrap();
576
577        let chain = create_descriptor_chain(
578            &memory,
579            GuestAddress(0x0),
580            GuestAddress(0x100),
581            vec![(Readable, 8)],
582            0,
583        )
584        .expect("create_descriptor_chain failed");
585        let mut writer = VirtioFsWriter::new(&memory, chain).expect("failed to create Writer");
586        assert_eq!(writer.available_bytes(), 0);
587        assert_eq!(writer.bytes_written(), 0);
588
589        assert!(writer.write_obj(0u8).is_err());
590
591        assert_eq!(writer.available_bytes(), 0);
592        assert_eq!(writer.bytes_written(), 0);
593    }
594
595    #[test]
596    fn reader_writer_shared_chain() {
597        use DescriptorType::*;
598
599        let memory_start_addr = GuestAddress(0x0);
600        let memory = GuestMemoryMmap::from_ranges(&vec![(memory_start_addr, 0x10000)]).unwrap();
601
602        let chain = create_descriptor_chain(
603            &memory,
604            GuestAddress(0x0),
605            GuestAddress(0x100),
606            vec![
607                (Readable, 16),
608                (Readable, 16),
609                (Readable, 96),
610                (Writable, 64),
611                (Writable, 1),
612                (Writable, 3),
613            ],
614            0,
615        )
616        .expect("create_descriptor_chain failed");
617        let mut reader = Reader::new(&memory, chain.clone()).expect("failed to create Reader");
618        let mut writer = VirtioFsWriter::new(&memory, chain).expect("failed to create Writer");
619
620        assert_eq!(reader.bytes_read(), 0);
621        assert_eq!(writer.bytes_written(), 0);
622
623        let mut buffer = Vec::with_capacity(200);
624
625        assert_eq!(
626            reader
627                .read_to_end(&mut buffer)
628                .expect("read should not fail here"),
629            128
630        );
631
632        // The writable descriptors are only 68 bytes long.
633        writer
634            .write_all(&buffer[..68])
635            .expect("write should not fail here");
636
637        assert_eq!(reader.available_bytes(), 0);
638        assert_eq!(reader.bytes_read(), 128);
639        assert_eq!(writer.available_bytes(), 0);
640        assert_eq!(writer.bytes_written(), 68);
641    }
642
643    #[test]
644    fn reader_writer_shattered_object() {
645        use DescriptorType::*;
646
647        let memory_start_addr = GuestAddress(0x0);
648        let memory = GuestMemoryMmap::from_ranges(&vec![(memory_start_addr, 0x10000)]).unwrap();
649
650        let secret: Le32 = 0x12345678.into();
651
652        // Create a descriptor chain with memory regions that are properly separated.
653        let chain_writer = create_descriptor_chain(
654            &memory,
655            GuestAddress(0x0),
656            GuestAddress(0x100),
657            vec![(Writable, 1), (Writable, 1), (Writable, 1), (Writable, 1)],
658            123,
659        )
660        .expect("create_descriptor_chain failed");
661        let mut writer =
662            VirtioFsWriter::new(&memory, chain_writer).expect("failed to create Writer");
663        assert!(writer.flush().is_ok());
664        if let Err(_) = writer.write_obj(secret) {
665            panic!("write_obj should not fail here");
666        }
667        assert!(writer.flush().is_ok());
668
669        // Now create new descriptor chain pointing to the same memory and try to read it.
670        let chain_reader = create_descriptor_chain(
671            &memory,
672            GuestAddress(0x0),
673            GuestAddress(0x100),
674            vec![(Readable, 1), (Readable, 1), (Readable, 1), (Readable, 1)],
675            123,
676        )
677        .expect("create_descriptor_chain failed");
678        let mut reader = Reader::new(&memory, chain_reader).expect("failed to create Reader");
679        match reader.read_obj::<Le32>() {
680            Err(_) => panic!("read_obj should not fail here"),
681            Ok(read_secret) => assert_eq!(read_secret, secret),
682        }
683    }
684
685    #[test]
686    fn reader_unexpected_eof() {
687        use DescriptorType::*;
688
689        let memory_start_addr = GuestAddress(0x0);
690        let memory = GuestMemoryMmap::from_ranges(&vec![(memory_start_addr, 0x10000)]).unwrap();
691
692        let chain = create_descriptor_chain(
693            &memory,
694            GuestAddress(0x0),
695            GuestAddress(0x100),
696            vec![(Readable, 256), (Readable, 256)],
697            0,
698        )
699        .expect("create_descriptor_chain failed");
700
701        let mut reader = Reader::new(&memory, chain).expect("failed to create Reader");
702
703        let mut buf = Vec::with_capacity(1024);
704        buf.resize(1024, 0);
705
706        assert_eq!(
707            reader
708                .read_exact(&mut buf[..])
709                .expect_err("read more bytes than available")
710                .kind(),
711            io::ErrorKind::UnexpectedEof
712        );
713    }
714
715    #[test]
716    fn split_border() {
717        use DescriptorType::*;
718
719        let memory_start_addr = GuestAddress(0x0);
720        let memory = GuestMemoryMmap::from_ranges(&vec![(memory_start_addr, 0x10000)]).unwrap();
721
722        let chain = create_descriptor_chain(
723            &memory,
724            GuestAddress(0x0),
725            GuestAddress(0x100),
726            vec![
727                (Readable, 16),
728                (Readable, 16),
729                (Readable, 96),
730                (Writable, 64),
731                (Writable, 1),
732                (Writable, 3),
733            ],
734            0,
735        )
736        .expect("create_descriptor_chain failed");
737        let mut reader = Reader::new(&memory, chain).expect("failed to create Reader");
738
739        let other = reader.split_at(32).expect("failed to split Reader");
740        assert_eq!(reader.available_bytes(), 32);
741        assert_eq!(other.available_bytes(), 96);
742    }
743
744    #[test]
745    fn split_middle() {
746        use DescriptorType::*;
747
748        let memory_start_addr = GuestAddress(0x0);
749        let memory = GuestMemoryMmap::from_ranges(&vec![(memory_start_addr, 0x10000)]).unwrap();
750
751        let chain = create_descriptor_chain(
752            &memory,
753            GuestAddress(0x0),
754            GuestAddress(0x100),
755            vec![
756                (Readable, 16),
757                (Readable, 16),
758                (Readable, 96),
759                (Writable, 64),
760                (Writable, 1),
761                (Writable, 3),
762            ],
763            0,
764        )
765        .expect("create_descriptor_chain failed");
766        let mut reader = Reader::new(&memory, chain).expect("failed to create Reader");
767
768        let other = reader.split_at(24).expect("failed to split Reader");
769        assert_eq!(reader.available_bytes(), 24);
770        assert_eq!(other.available_bytes(), 104);
771    }
772
773    #[test]
774    fn split_end() {
775        use DescriptorType::*;
776
777        let memory_start_addr = GuestAddress(0x0);
778        let memory = GuestMemoryMmap::from_ranges(&vec![(memory_start_addr, 0x10000)]).unwrap();
779
780        let chain = create_descriptor_chain(
781            &memory,
782            GuestAddress(0x0),
783            GuestAddress(0x100),
784            vec![
785                (Readable, 16),
786                (Readable, 16),
787                (Readable, 96),
788                (Writable, 64),
789                (Writable, 1),
790                (Writable, 3),
791            ],
792            0,
793        )
794        .expect("create_descriptor_chain failed");
795        let mut reader = Reader::new(&memory, chain).expect("failed to create Reader");
796
797        let other = reader.split_at(128).expect("failed to split Reader");
798        assert_eq!(reader.available_bytes(), 128);
799        assert_eq!(other.available_bytes(), 0);
800    }
801
802    #[test]
803    fn split_beginning() {
804        use DescriptorType::*;
805
806        let memory_start_addr = GuestAddress(0x0);
807        let memory = GuestMemoryMmap::from_ranges(&vec![(memory_start_addr, 0x10000)]).unwrap();
808
809        let chain = create_descriptor_chain(
810            &memory,
811            GuestAddress(0x0),
812            GuestAddress(0x100),
813            vec![
814                (Readable, 16),
815                (Readable, 16),
816                (Readable, 96),
817                (Writable, 64),
818                (Writable, 1),
819                (Writable, 3),
820            ],
821            0,
822        )
823        .expect("create_descriptor_chain failed");
824        let mut reader = Reader::new(&memory, chain).expect("failed to create Reader");
825
826        let other = reader.split_at(0).expect("failed to split Reader");
827        assert_eq!(reader.available_bytes(), 0);
828        assert_eq!(other.available_bytes(), 128);
829    }
830
831    #[test]
832    fn split_outofbounds() {
833        use DescriptorType::*;
834
835        let memory_start_addr = GuestAddress(0x0);
836        let memory = GuestMemoryMmap::from_ranges(&vec![(memory_start_addr, 0x10000)]).unwrap();
837
838        let chain = create_descriptor_chain(
839            &memory,
840            GuestAddress(0x0),
841            GuestAddress(0x100),
842            vec![
843                (Readable, 16),
844                (Readable, 16),
845                (Readable, 96),
846                (Writable, 64),
847                (Writable, 1),
848                (Writable, 3),
849            ],
850            0,
851        )
852        .expect("create_descriptor_chain failed");
853        let mut reader = Reader::new(&memory, chain).expect("failed to create Reader");
854
855        if let Ok(_) = reader.split_at(256) {
856            panic!("successfully split Reader with out of bounds offset");
857        }
858    }
859
860    #[test]
861    fn read_full() {
862        use DescriptorType::*;
863
864        let memory_start_addr = GuestAddress(0x0);
865        let memory = GuestMemoryMmap::from_ranges(&vec![(memory_start_addr, 0x10000)]).unwrap();
866
867        let chain = create_descriptor_chain(
868            &memory,
869            GuestAddress(0x0),
870            GuestAddress(0x100),
871            vec![(Readable, 16), (Readable, 16), (Readable, 16)],
872            0,
873        )
874        .expect("create_descriptor_chain failed");
875        let mut reader = Reader::new(&memory, chain).expect("failed to create Reader");
876
877        let mut buf = vec![0u8; 64];
878        assert_eq!(
879            reader.read(&mut buf[..]).expect("failed to read to buffer"),
880            48
881        );
882    }
883
884    #[test]
885    fn write_full() {
886        use DescriptorType::*;
887
888        let memory_start_addr = GuestAddress(0x0);
889        let memory = GuestMemoryMmap::from_ranges(&vec![(memory_start_addr, 0x10000)]).unwrap();
890
891        let chain = create_descriptor_chain(
892            &memory,
893            GuestAddress(0x0),
894            GuestAddress(0x100),
895            vec![(Writable, 16), (Writable, 16), (Writable, 16)],
896            0,
897        )
898        .expect("create_descriptor_chain failed");
899        let mut writer = VirtioFsWriter::new(&memory, chain).expect("failed to create Writer");
900
901        let buf = vec![0xdeu8; 40];
902        assert_eq!(
903            writer.write(&buf[..]).expect("failed to write from buffer"),
904            40
905        );
906        assert_eq!(writer.available_bytes(), 8);
907        assert_eq!(writer.bytes_written(), 40);
908
909        // Write more data than capacity
910        writer.write(&buf[..]).unwrap_err();
911        assert_eq!(writer.available_bytes(), 8);
912        assert_eq!(writer.bytes_written(), 40);
913    }
914
915    #[test]
916    fn write_vectored() {
917        use DescriptorType::*;
918
919        let memory_start_addr = GuestAddress(0x0);
920        let memory = GuestMemoryMmap::from_ranges(&vec![(memory_start_addr, 0x10000)]).unwrap();
921
922        let chain = create_descriptor_chain(
923            &memory,
924            GuestAddress(0x0),
925            GuestAddress(0x100),
926            vec![(Writable, 16), (Writable, 16), (Writable, 16)],
927            0,
928        )
929        .expect("create_descriptor_chain failed");
930        let mut writer = VirtioFsWriter::new(&memory, chain).expect("failed to create Writer");
931
932        let buf = vec![0xdeu8; 48];
933        let slices = [
934            IoSlice::new(&buf[..32]),
935            IoSlice::new(&buf[32..40]),
936            IoSlice::new(&buf[40..]),
937        ];
938        assert_eq!(
939            writer
940                .write_vectored(&slices)
941                .expect("failed to write from buffer"),
942            48
943        );
944        assert_eq!(writer.available_bytes(), 0);
945        assert_eq!(writer.bytes_written(), 48);
946
947        // Write more data than capacity
948        let buf = vec![0xdeu8; 40];
949        writer.write(&buf[..]).unwrap_err();
950        assert_eq!(writer.available_bytes(), 0);
951        assert_eq!(writer.bytes_written(), 48);
952    }
953
954    #[test]
955    fn read_exact_to() {
956        use DescriptorType::*;
957
958        let memory_start_addr = GuestAddress(0x0);
959        let memory = GuestMemoryMmap::from_ranges(&vec![(memory_start_addr, 0x10000)]).unwrap();
960
961        let chain = create_descriptor_chain(
962            &memory,
963            GuestAddress(0x0),
964            GuestAddress(0x100),
965            vec![(Readable, 16), (Readable, 16), (Readable, 16)],
966            0,
967        )
968        .expect("create_descriptor_chain failed");
969        let mut reader = Reader::new(&memory, chain).expect("failed to create Writer");
970
971        let mut file = TempFile::new().unwrap().into_file();
972        reader
973            .read_exact_to(&mut file, 47)
974            .expect("failed to read to file");
975
976        assert_eq!(reader.available_bytes(), 1);
977        assert_eq!(reader.bytes_read(), 47);
978    }
979
980    #[test]
981    fn read_to_at() {
982        use DescriptorType::*;
983
984        let memory_start_addr = GuestAddress(0x0);
985        let memory = GuestMemoryMmap::from_ranges(&vec![(memory_start_addr, 0x10000)]).unwrap();
986
987        let chain = create_descriptor_chain(
988            &memory,
989            GuestAddress(0x0),
990            GuestAddress(0x100),
991            vec![(Readable, 16), (Readable, 16), (Readable, 16)],
992            0,
993        )
994        .expect("create_descriptor_chain failed");
995        let mut reader = Reader::new(&memory, chain).expect("failed to create Writer");
996
997        let mut file = TempFile::new().unwrap().into_file();
998        assert_eq!(
999            reader
1000                .read_to_at(&mut file, 48, 16)
1001                .expect("failed to read to file"),
1002            48
1003        );
1004
1005        assert_eq!(reader.available_bytes(), 0);
1006        assert_eq!(reader.bytes_read(), 48);
1007    }
1008
1009    #[test]
1010    fn write_all_from() {
1011        use DescriptorType::*;
1012
1013        let memory_start_addr = GuestAddress(0x0);
1014        let memory = GuestMemoryMmap::from_ranges(&vec![(memory_start_addr, 0x10000)]).unwrap();
1015
1016        let chain = create_descriptor_chain(
1017            &memory,
1018            GuestAddress(0x0),
1019            GuestAddress(0x100),
1020            vec![(Writable, 16), (Writable, 16), (Writable, 16)],
1021            0,
1022        )
1023        .expect("create_descriptor_chain failed");
1024        let mut writer = VirtioFsWriter::new(&memory, chain).expect("failed to create Writer");
1025
1026        let mut file = TempFile::new().unwrap().into_file();
1027        let buf = vec![0xdeu8; 64];
1028        file.write_all(&buf).unwrap();
1029        file.seek(SeekFrom::Start(0)).unwrap();
1030        writer
1031            .write_all_from(&mut file, 47)
1032            .expect("failed to write from buffer");
1033
1034        assert_eq!(writer.available_bytes(), 1);
1035        assert_eq!(writer.bytes_written(), 47);
1036    }
1037
1038    #[test]
1039    fn write_from_at() {
1040        use DescriptorType::*;
1041
1042        let memory_start_addr = GuestAddress(0x0);
1043        let memory = GuestMemoryMmap::from_ranges(&vec![(memory_start_addr, 0x10000)]).unwrap();
1044
1045        let chain = create_descriptor_chain(
1046            &memory,
1047            GuestAddress(0x0),
1048            GuestAddress(0x100),
1049            vec![(Writable, 16), (Writable, 16), (Writable, 16)],
1050            0,
1051        )
1052        .expect("create_descriptor_chain failed");
1053        let mut writer = VirtioFsWriter::new(&memory, chain).expect("failed to create Writer");
1054
1055        let mut file = TempFile::new().unwrap().into_file();
1056        let buf = vec![0xdeu8; 64];
1057        file.write_all(&buf).unwrap();
1058        file.seek(SeekFrom::Start(0)).unwrap();
1059        assert_eq!(
1060            writer
1061                .write_from_at(&mut file, 48, 16)
1062                .expect("failed to write from buffer"),
1063            48
1064        );
1065
1066        assert_eq!(writer.available_bytes(), 0);
1067        assert_eq!(writer.bytes_written(), 48);
1068    }
1069
1070    #[cfg(feature = "async-io")]
1071    mod async_io {
1072        use futures::executor::{block_on, ThreadPool};
1073        use futures::task::SpawnExt;
1074        use ringbahn::drive::demo::DemoDriver;
1075        use std::os::unix::io::AsRawFd;
1076
1077        use super::*;
1078
1079        #[test]
1080        fn async_read_to_at() {
1081            let file = TempFile::new().unwrap().into_file();
1082            let fd = file.as_raw_fd();
1083            let executor = ThreadPool::new().unwrap();
1084
1085            let handle = executor
1086                .spawn_with_handle(async move {
1087                    use DescriptorType::*;
1088
1089                    let memory_start_addr = GuestAddress(0x0);
1090                    let memory =
1091                        GuestMemoryMmap::from_ranges(&vec![(memory_start_addr, 0x10000)]).unwrap();
1092
1093                    let chain = create_descriptor_chain(
1094                        &memory,
1095                        GuestAddress(0x0),
1096                        GuestAddress(0x100),
1097                        vec![(Readable, 16), (Readable, 16), (Readable, 16)],
1098                        0,
1099                    )
1100                    .expect("create_descriptor_chain failed");
1101                    let mut reader = Reader::new(&memory, chain).expect("failed to create Writer");
1102                    let drive = DemoDriver::default();
1103
1104                    reader.async_read_to_at(drive, fd, 48, 16).await
1105                })
1106                .unwrap();
1107            assert_eq!(block_on(handle).unwrap(), 48);
1108        }
1109
1110        #[test]
1111        fn async_write() {
1112            let executor = ThreadPool::new().unwrap();
1113            let handle = executor
1114                .spawn_with_handle(async move {
1115                    use DescriptorType::*;
1116
1117                    let memory_start_addr = GuestAddress(0x0);
1118                    let memory =
1119                        GuestMemoryMmap::from_ranges(&vec![(memory_start_addr, 0x10000)]).unwrap();
1120
1121                    let chain = create_descriptor_chain(
1122                        &memory,
1123                        GuestAddress(0x0),
1124                        GuestAddress(0x100),
1125                        vec![(Writable, 16), (Writable, 16), (Writable, 16)],
1126                        0,
1127                    )
1128                    .expect("create_descriptor_chain failed");
1129                    let mut writer =
1130                        VirtioFsWriter::new(&memory, chain).expect("failed to create Writer");
1131                    let drive = DemoDriver::default();
1132                    let buf = vec![0xdeu8; 64];
1133
1134                    writer.async_write(drive, &buf[..]).await
1135                })
1136                .unwrap();
1137            // expect errors
1138            block_on(handle).unwrap_err();
1139
1140            let handle = executor
1141                .spawn_with_handle(async move {
1142                    use DescriptorType::*;
1143
1144                    let memory_start_addr = GuestAddress(0x0);
1145                    let memory =
1146                        GuestMemoryMmap::from_ranges(&vec![(memory_start_addr, 0x10000)]).unwrap();
1147
1148                    let chain = create_descriptor_chain(
1149                        &memory,
1150                        GuestAddress(0x0),
1151                        GuestAddress(0x100),
1152                        vec![(Writable, 16), (Writable, 16), (Writable, 16)],
1153                        0,
1154                    )
1155                    .expect("create_descriptor_chain failed");
1156                    let mut writer =
1157                        VirtioFsWriter::new(&memory, chain).expect("failed to create Writer");
1158                    let drive = DemoDriver::default();
1159
1160                    let buf = vec![0xdeu8; 48];
1161                    writer.async_write(drive, &buf[..]).await
1162                })
1163                .unwrap();
1164
1165            assert_eq!(block_on(handle).unwrap(), 48);
1166        }
1167
1168        #[test]
1169        fn async_write2() {
1170            let executor = ThreadPool::new().unwrap();
1171            let handle = executor
1172                .spawn_with_handle(async move {
1173                    use DescriptorType::*;
1174
1175                    let memory_start_addr = GuestAddress(0x0);
1176                    let memory =
1177                        GuestMemoryMmap::from_ranges(&vec![(memory_start_addr, 0x10000)]).unwrap();
1178
1179                    let chain = create_descriptor_chain(
1180                        &memory,
1181                        GuestAddress(0x0),
1182                        GuestAddress(0x100),
1183                        vec![(Writable, 16), (Writable, 16), (Writable, 16)],
1184                        0,
1185                    )
1186                    .expect("create_descriptor_chain failed");
1187                    let mut writer =
1188                        VirtioFsWriter::new(&memory, chain).expect("failed to create Writer");
1189                    let drive = DemoDriver::default();
1190                    let buf = vec![0xdeu8; 48];
1191
1192                    writer.async_write2(drive, &buf[..32], &buf[32..]).await
1193                })
1194                .unwrap();
1195
1196            assert_eq!(block_on(handle).unwrap(), 48);
1197        }
1198
1199        #[test]
1200        fn async_write3() {
1201            let executor = ThreadPool::new().unwrap();
1202            let handle = executor
1203                .spawn_with_handle(async move {
1204                    use DescriptorType::*;
1205
1206                    let memory_start_addr = GuestAddress(0x0);
1207                    let memory =
1208                        GuestMemoryMmap::from_ranges(&vec![(memory_start_addr, 0x10000)]).unwrap();
1209
1210                    let chain = create_descriptor_chain(
1211                        &memory,
1212                        GuestAddress(0x0),
1213                        GuestAddress(0x100),
1214                        vec![(Writable, 16), (Writable, 16), (Writable, 16)],
1215                        0,
1216                    )
1217                    .expect("create_descriptor_chain failed");
1218                    let mut writer =
1219                        VirtioFsWriter::new(&memory, chain).expect("failed to create Writer");
1220                    let drive = DemoDriver::default();
1221                    let buf = vec![0xdeu8; 48];
1222
1223                    writer
1224                        .async_write3(drive, &buf[..32], &buf[32..40], &buf[40..])
1225                        .await
1226                })
1227                .unwrap();
1228
1229            assert_eq!(block_on(handle).unwrap(), 48);
1230        }
1231
1232        #[test]
1233        fn async_write_from_at() {
1234            let mut file = TempFile::new().unwrap().into_file();
1235            let fd = file.as_raw_fd();
1236            let buf = vec![0xdeu8; 64];
1237
1238            file.write_all(&buf).unwrap();
1239            file.seek(SeekFrom::Start(0)).unwrap();
1240
1241            let executor = ThreadPool::new().unwrap();
1242            let handle = executor
1243                .spawn_with_handle(async move {
1244                    use DescriptorType::*;
1245
1246                    let memory_start_addr = GuestAddress(0x0);
1247                    let memory =
1248                        GuestMemoryMmap::from_ranges(&vec![(memory_start_addr, 0x10000)]).unwrap();
1249
1250                    let chain = create_descriptor_chain(
1251                        &memory,
1252                        GuestAddress(0x0),
1253                        GuestAddress(0x100),
1254                        vec![(Writable, 16), (Writable, 16), (Writable, 16)],
1255                        0,
1256                    )
1257                    .expect("create_descriptor_chain failed");
1258                    let mut writer =
1259                        VirtioFsWriter::new(&memory, chain).expect("failed to create Writer");
1260                    let drive = DemoDriver::default();
1261
1262                    writer.async_write_from_at(drive, fd, 40, 16).await
1263                })
1264                .unwrap();
1265
1266            assert_eq!(block_on(handle).unwrap(), 40);
1267        }
1268    }
1269}