fuse_backend_rs/common/
file_traits.rs

1// Copyright 2018 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE-BSD-3-Clause file.
4
5//! File extension traits to transfer data between File objects and [VolatileSlice][2] buffers.
6//!
7//! Fuse filesystem servers use normal memory buffers to transfer data from/to File objects.
8//! For virtio-fs file servers, they need to transfer data between File objects and guest memory.
9//! The guest memory could be accessed through [GuestMemory][1] or [VolatileSlice][2] objects.
10//! And the [VolatileSlice][2] trait could also be used to access normal memory buffers too.
11//! So several [VolatileSlice][2] based File extension traits are introduced to deal with both
12//! guest memory and normal memory buffers.
13//!
14//! [1]: https://docs.rs/vm-memory/0.2.0/vm_memory/guest_memory/trait.GuestMemory.html
15//! [2]: https://docs.rs/vm-memory/0.2.0/vm_memory/volatile_memory/struct.VolatileSlice.html
16
17use std::fs::File;
18use std::io::{Error, ErrorKind, Result};
19use std::os::unix::io::AsRawFd;
20
21use libc::{c_int, c_void, read, readv, size_t, write, writev};
22
23use crate::file_buf::FileVolatileSlice;
24use crate::{off64_t, pread64, preadv64, pwrite64, pwritev64};
25
26/// A trait for setting the size of a file.
27///
28/// This is equivalent to File's `set_len` method, but wrapped in a trait so that it can be
29/// implemented for other types.
30pub trait FileSetLen {
31    /// Set the size of this file.
32    ///
33    /// This is the moral equivalent of `ftruncate()`.
34    fn set_len(&self, _len: u64) -> Result<()>;
35}
36
37impl FileSetLen for File {
38    fn set_len(&self, len: u64) -> Result<()> {
39        File::set_len(self, len)
40    }
41}
42
43/// A trait similar to `Read` and `Write`, but uses [FileVolatileSlice] objects as data buffers.
44pub trait FileReadWriteVolatile {
45    /// Read bytes from this file into the given slice, returning the number of bytes read on
46    /// success.
47    fn read_volatile(&mut self, slice: FileVolatileSlice) -> Result<usize>;
48
49    /// Like `read_volatile`, except it reads to a slice of buffers. Data is copied to fill each
50    /// buffer in order, with the final buffer written to possibly being only partially filled. This
51    /// method must behave as a single call to `read_volatile` with the buffers concatenated would.
52    /// The default implementation calls `read_volatile` with either the first nonempty buffer
53    /// provided, or returns `Ok(0)` if none exists.
54    fn read_vectored_volatile(&mut self, bufs: &[FileVolatileSlice]) -> Result<usize> {
55        bufs.iter()
56            .find(|b| !b.is_empty())
57            .map(|b| self.read_volatile(*b))
58            .unwrap_or(Ok(0))
59    }
60
61    /// Reads bytes from this into the given slice until all bytes in the slice are written, or an
62    /// error is returned.
63    fn read_exact_volatile(&mut self, mut slice: FileVolatileSlice) -> Result<()> {
64        while !slice.is_empty() {
65            let bytes_read = self.read_volatile(slice)?;
66            if bytes_read == 0 {
67                return Err(Error::from(ErrorKind::UnexpectedEof));
68            }
69            // Will panic if read_volatile read more bytes than we gave it, which would be worthy of
70            // a panic.
71            slice = slice.offset(bytes_read).unwrap();
72        }
73        Ok(())
74    }
75
76    /// Write bytes from the slice to the given file, returning the number of bytes written on
77    /// success.
78    fn write_volatile(&mut self, slice: FileVolatileSlice) -> Result<usize>;
79
80    /// Like `write_volatile`, except that it writes from a slice of buffers. Data is copied from
81    /// each buffer in order, with the final buffer read from possibly being only partially
82    /// consumed. This method must behave as a call to `write_volatile` with the buffers
83    /// concatenated would. The default implementation calls `write_volatile` with either the first
84    /// nonempty buffer provided, or returns `Ok(0)` if none exists.
85    fn write_vectored_volatile(&mut self, bufs: &[FileVolatileSlice]) -> Result<usize> {
86        bufs.iter()
87            .find(|b| !b.is_empty())
88            .map(|b| self.write_volatile(*b))
89            .unwrap_or(Ok(0))
90    }
91
92    /// Write bytes from the slice to the given file until all the bytes from the slice have been
93    /// written, or an error is returned.
94    fn write_all_volatile(&mut self, mut slice: FileVolatileSlice) -> Result<()> {
95        while !slice.is_empty() {
96            let bytes_written = self.write_volatile(slice)?;
97            if bytes_written == 0 {
98                return Err(Error::from(ErrorKind::WriteZero));
99            }
100            // Will panic if write_volatile read more bytes than we gave it, which would be worthy
101            // of a panic.
102            slice = slice.offset(bytes_written).unwrap();
103        }
104        Ok(())
105    }
106
107    /// Reads bytes from this file at `offset` into the given slice, returning the number of bytes
108    /// read on success.
109    fn read_at_volatile(&mut self, slice: FileVolatileSlice, offset: u64) -> Result<usize>;
110
111    /// Like `read_at_volatile`, except it reads to a slice of buffers. Data is copied to fill each
112    /// buffer in order, with the final buffer written to possibly being only partially filled. This
113    /// method must behave as a single call to `read_at_volatile` with the buffers concatenated
114    /// would. The default implementation calls `read_at_volatile` with either the first nonempty
115    /// buffer provided, or returns `Ok(0)` if none exists.
116    fn read_vectored_at_volatile(
117        &mut self,
118        bufs: &[FileVolatileSlice],
119        offset: u64,
120    ) -> Result<usize> {
121        if let Some(slice) = bufs.first() {
122            self.read_at_volatile(*slice, offset)
123        } else {
124            Ok(0)
125        }
126    }
127
128    /// Reads bytes from this file at `offset` into the given slice until all bytes in the slice are
129    /// read, or an error is returned.
130    fn read_exact_at_volatile(
131        &mut self,
132        mut slice: FileVolatileSlice,
133        mut offset: u64,
134    ) -> Result<()> {
135        while !slice.is_empty() {
136            match self.read_at_volatile(slice, offset) {
137                Ok(0) => return Err(Error::from(ErrorKind::UnexpectedEof)),
138                Ok(n) => {
139                    // Will panic if read_at_volatile read more bytes than we gave it, which would
140                    // be worthy of a panic.
141                    slice = slice.offset(n).unwrap();
142                    offset = offset.checked_add(n as u64).unwrap();
143                }
144                Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
145                Err(e) => return Err(e),
146            }
147        }
148        Ok(())
149    }
150
151    /// Writes bytes from this file at `offset` into the given slice, returning the number of bytes
152    /// written on success.
153    fn write_at_volatile(&mut self, slice: FileVolatileSlice, offset: u64) -> Result<usize>;
154
155    /// Like `write_at_at_volatile`, except that it writes from a slice of buffers. Data is copied
156    /// from each buffer in order, with the final buffer read from possibly being only partially
157    /// consumed. This method must behave as a call to `write_at_volatile` with the buffers
158    /// concatenated would. The default implementation calls `write_at_volatile` with either the
159    /// first nonempty buffer provided, or returns `Ok(0)` if none exists.
160    fn write_vectored_at_volatile(
161        &mut self,
162        bufs: &[FileVolatileSlice],
163        offset: u64,
164    ) -> Result<usize> {
165        if let Some(slice) = bufs.first() {
166            self.write_at_volatile(*slice, offset)
167        } else {
168            Ok(0)
169        }
170    }
171
172    /// Writes bytes from this file at `offset` into the given slice until all bytes in the slice
173    /// are written, or an error is returned.
174    fn write_all_at_volatile(
175        &mut self,
176        mut slice: FileVolatileSlice,
177        mut offset: u64,
178    ) -> Result<()> {
179        while !slice.is_empty() {
180            match self.write_at_volatile(slice, offset) {
181                Ok(0) => return Err(Error::from(ErrorKind::WriteZero)),
182                Ok(n) => {
183                    // Will panic if write_at_volatile read more bytes than we gave it, which would
184                    // be worthy of a panic.
185                    slice = slice.offset(n).unwrap();
186                    offset = offset.checked_add(n as u64).unwrap();
187                }
188                Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
189                Err(e) => return Err(e),
190            }
191        }
192        Ok(())
193    }
194}
195
196impl<T: FileReadWriteVolatile + ?Sized> FileReadWriteVolatile for &mut T {
197    fn read_volatile(&mut self, slice: FileVolatileSlice) -> Result<usize> {
198        (**self).read_volatile(slice)
199    }
200
201    fn read_vectored_volatile(&mut self, bufs: &[FileVolatileSlice]) -> Result<usize> {
202        (**self).read_vectored_volatile(bufs)
203    }
204
205    fn read_exact_volatile(&mut self, slice: FileVolatileSlice) -> Result<()> {
206        (**self).read_exact_volatile(slice)
207    }
208
209    fn write_volatile(&mut self, slice: FileVolatileSlice) -> Result<usize> {
210        (**self).write_volatile(slice)
211    }
212
213    fn write_vectored_volatile(&mut self, bufs: &[FileVolatileSlice]) -> Result<usize> {
214        (**self).write_vectored_volatile(bufs)
215    }
216
217    fn write_all_volatile(&mut self, slice: FileVolatileSlice) -> Result<()> {
218        (**self).write_all_volatile(slice)
219    }
220
221    fn read_at_volatile(&mut self, slice: FileVolatileSlice, offset: u64) -> Result<usize> {
222        (**self).read_at_volatile(slice, offset)
223    }
224
225    fn read_vectored_at_volatile(
226        &mut self,
227        bufs: &[FileVolatileSlice],
228        offset: u64,
229    ) -> Result<usize> {
230        (**self).read_vectored_at_volatile(bufs, offset)
231    }
232
233    fn read_exact_at_volatile(&mut self, slice: FileVolatileSlice, offset: u64) -> Result<()> {
234        (**self).read_exact_at_volatile(slice, offset)
235    }
236
237    fn write_at_volatile(&mut self, slice: FileVolatileSlice, offset: u64) -> Result<usize> {
238        (**self).write_at_volatile(slice, offset)
239    }
240
241    fn write_vectored_at_volatile(
242        &mut self,
243        bufs: &[FileVolatileSlice],
244        offset: u64,
245    ) -> Result<usize> {
246        (**self).write_vectored_at_volatile(bufs, offset)
247    }
248
249    fn write_all_at_volatile(&mut self, slice: FileVolatileSlice, offset: u64) -> Result<()> {
250        (**self).write_all_at_volatile(slice, offset)
251    }
252}
253
254macro_rules! volatile_impl {
255    ($ty:ty) => {
256        impl FileReadWriteVolatile for $ty {
257            fn read_volatile(&mut self, slice: FileVolatileSlice) -> Result<usize> {
258                // Safe because only bytes inside the slice are accessed and the kernel is expected
259                // to handle arbitrary memory for I/O.
260                let ret =
261                    unsafe { read(self.as_raw_fd(), slice.as_ptr() as *mut c_void, slice.len()) };
262
263                if ret >= 0 {
264                    Ok(ret as usize)
265                } else {
266                    Err(Error::last_os_error())
267                }
268            }
269
270            fn read_vectored_volatile(&mut self, bufs: &[FileVolatileSlice]) -> Result<usize> {
271                let iovecs: Vec<libc::iovec> = bufs
272                    .iter()
273                    .map(|s| libc::iovec {
274                        iov_base: s.as_ptr() as *mut c_void,
275                        iov_len: s.len() as size_t,
276                    })
277                    .collect();
278
279                if iovecs.is_empty() {
280                    return Ok(0);
281                }
282
283                // Safe because only bytes inside the buffers are accessed and the kernel is
284                // expected to handle arbitrary memory for I/O.
285                let ret = unsafe { readv(self.as_raw_fd(), &iovecs[0], iovecs.len() as c_int) };
286
287                if ret >= 0 {
288                    Ok(ret as usize)
289                } else {
290                    Err(Error::last_os_error())
291                }
292            }
293
294            fn write_volatile(&mut self, slice: FileVolatileSlice) -> Result<usize> {
295                // Safe because only bytes inside the slice are accessed and the kernel is expected
296                // to handle arbitrary memory for I/O.
297                let ret = unsafe {
298                    write(
299                        self.as_raw_fd(),
300                        slice.as_ptr() as *const c_void,
301                        slice.len(),
302                    )
303                };
304                if ret >= 0 {
305                    Ok(ret as usize)
306                } else {
307                    Err(Error::last_os_error())
308                }
309            }
310
311            fn write_vectored_volatile(&mut self, bufs: &[FileVolatileSlice]) -> Result<usize> {
312                let iovecs: Vec<libc::iovec> = bufs
313                    .iter()
314                    .map(|s| libc::iovec {
315                        iov_base: s.as_ptr() as *mut c_void,
316                        iov_len: s.len() as size_t,
317                    })
318                    .collect();
319
320                if iovecs.is_empty() {
321                    return Ok(0);
322                }
323
324                // Safe because only bytes inside the buffers are accessed and the kernel is
325                // expected to handle arbitrary memory for I/O.
326                let ret = unsafe { writev(self.as_raw_fd(), &iovecs[0], iovecs.len() as c_int) };
327                if ret >= 0 {
328                    Ok(ret as usize)
329                } else {
330                    Err(Error::last_os_error())
331                }
332            }
333
334            fn read_at_volatile(&mut self, slice: FileVolatileSlice, offset: u64) -> Result<usize> {
335                // Safe because only bytes inside the slice are accessed and the kernel is expected
336                // to handle arbitrary memory for I/O.
337                let ret = unsafe {
338                    pread64(
339                        self.as_raw_fd(),
340                        slice.as_ptr() as *mut c_void,
341                        slice.len(),
342                        offset as off64_t,
343                    )
344                };
345
346                if ret >= 0 {
347                    Ok(ret as usize)
348                } else {
349                    Err(Error::last_os_error())
350                }
351            }
352
353            fn read_vectored_at_volatile(
354                &mut self,
355                bufs: &[FileVolatileSlice],
356                offset: u64,
357            ) -> Result<usize> {
358                let iovecs: Vec<libc::iovec> = bufs
359                    .iter()
360                    .map(|s| libc::iovec {
361                        iov_base: s.as_ptr() as *mut c_void,
362                        iov_len: s.len() as size_t,
363                    })
364                    .collect();
365
366                if iovecs.is_empty() {
367                    return Ok(0);
368                }
369
370                // Safe because only bytes inside the buffers are accessed and the kernel is
371                // expected to handle arbitrary memory for I/O.
372                let ret = unsafe {
373                    preadv64(
374                        self.as_raw_fd(),
375                        &iovecs[0],
376                        iovecs.len() as c_int,
377                        offset as off64_t,
378                    )
379                };
380
381                if ret >= 0 {
382                    Ok(ret as usize)
383                } else {
384                    Err(Error::last_os_error())
385                }
386            }
387
388            fn write_at_volatile(
389                &mut self,
390                slice: FileVolatileSlice,
391                offset: u64,
392            ) -> Result<usize> {
393                // Safe because only bytes inside the slice are accessed and the kernel is expected
394                // to handle arbitrary memory for I/O.
395                let ret = unsafe {
396                    pwrite64(
397                        self.as_raw_fd(),
398                        slice.as_ptr() as *const c_void,
399                        slice.len(),
400                        offset as off64_t,
401                    )
402                };
403
404                if ret >= 0 {
405                    Ok(ret as usize)
406                } else {
407                    Err(Error::last_os_error())
408                }
409            }
410
411            fn write_vectored_at_volatile(
412                &mut self,
413                bufs: &[FileVolatileSlice],
414                offset: u64,
415            ) -> Result<usize> {
416                let iovecs: Vec<libc::iovec> = bufs
417                    .iter()
418                    .map(|s| libc::iovec {
419                        iov_base: s.as_ptr() as *mut c_void,
420                        iov_len: s.len() as size_t,
421                    })
422                    .collect();
423
424                if iovecs.is_empty() {
425                    return Ok(0);
426                }
427
428                // Safe because only bytes inside the buffers are accessed and the kernel is
429                // expected to handle arbitrary memory for I/O.
430                let ret = unsafe {
431                    pwritev64(
432                        self.as_raw_fd(),
433                        &iovecs[0],
434                        iovecs.len() as c_int,
435                        offset as off64_t,
436                    )
437                };
438                if ret >= 0 {
439                    Ok(ret as usize)
440                } else {
441                    Err(Error::last_os_error())
442                }
443            }
444        }
445    };
446}
447
448volatile_impl!(File);
449
450#[cfg(all(target_os = "linux", feature = "async-io"))]
451pub use async_io::AsyncFileReadWriteVolatile;
452
453#[cfg(all(target_os = "linux", feature = "async-io"))]
454mod async_io {
455    use std::sync::Arc;
456
457    use tokio::join;
458    use tokio_uring::buf::IoBuf;
459
460    use super::*;
461    use crate::async_file::File;
462    use crate::file_buf::FileVolatileBuf;
463
464    /// Extension of [FileReadWriteVolatile] to support io-uring based asynchronous IO.
465    ///
466    /// The asynchronous IO framework provided by [tokio-uring](https://docs.rs/tokio-uring/latest/tokio_uring/)
467    /// needs to take ownership of data buffers during asynchronous IO operations.
468    /// The [AsyncFileReadWriteVolatile] trait is designed to support io-uring based asynchronous IO.
469    #[async_trait::async_trait(?Send)]
470    pub trait AsyncFileReadWriteVolatile {
471        /// Read bytes from this file at `offset` into the given slice in asynchronous mode.
472        ///
473        /// Return the number of bytes read on success.
474        async fn async_read_at_volatile(
475            &self,
476            buf: FileVolatileBuf,
477            offset: u64,
478        ) -> (Result<usize>, FileVolatileBuf);
479
480        /// Asynchronous version of [FileReadWriteVolatile::read_vectored_at_volatile], to read data
481        /// into [FileVolatileSlice] buffers.
482        ///
483        /// Like `async_read_at_volatile()`, except it reads to a slice of buffers. Data is copied
484        /// to fill each buffer in order, with the final buffer written to possibly being only
485        /// partially filled. This method must behave as a single call to `read_at_volatile` with
486        /// the buffers concatenated would.
487        ///
488        /// Returns `Ok(0)` if none exists.
489        async fn async_read_vectored_at_volatile(
490            &self,
491            bufs: Vec<FileVolatileBuf>,
492            offset: u64,
493        ) -> (Result<usize>, Vec<FileVolatileBuf>);
494
495        /// Asynchronous version of [FileReadWriteVolatile::write_at_volatile], to write
496        /// data from a [FileVolatileSlice] buffer.
497        async fn async_write_at_volatile(
498            &self,
499            buf: FileVolatileBuf,
500            offset: u64,
501        ) -> (Result<usize>, FileVolatileBuf);
502
503        /// Asynchronous version of [FileReadWriteVolatile::write_vectored_at_volatile], to write
504        /// data from [FileVolatileSlice] buffers.
505        async fn async_write_vectored_at_volatile(
506            &self,
507            bufs: Vec<FileVolatileBuf>,
508            offset: u64,
509        ) -> (Result<usize>, Vec<FileVolatileBuf>);
510    }
511
512    #[async_trait::async_trait(?Send)]
513    impl AsyncFileReadWriteVolatile for File {
514        async fn async_read_at_volatile(
515            &self,
516            buf: FileVolatileBuf,
517            offset: u64,
518        ) -> (Result<usize>, FileVolatileBuf) {
519            self.async_read_at(buf, offset).await
520        }
521
522        async fn async_read_vectored_at_volatile(
523            &self,
524            mut bufs: Vec<FileVolatileBuf>,
525            mut offset: u64,
526        ) -> (Result<usize>, Vec<FileVolatileBuf>) {
527            if bufs.is_empty() {
528                return (Ok(0), bufs);
529            } else if bufs.len() == 1 {
530                let (res, buf) = self.async_read_at_volatile(bufs[0], offset).await;
531                bufs[0] = buf;
532                return (res, bufs);
533            }
534
535            let mut count = 0;
536            let mut pos = 0;
537            while bufs.len() - pos >= 4 {
538                let op1 = self.async_read_at_volatile(bufs[pos], offset);
539                offset += bufs[pos].bytes_total() as u64;
540                let op2 = self.async_read_at_volatile(bufs[pos + 1], offset);
541                offset += bufs[pos + 1].bytes_total() as u64;
542                let op3 = self.async_read_at_volatile(bufs[pos + 2], offset);
543                offset += bufs[pos + 2].bytes_total() as u64;
544                let op4 = self.async_read_at_volatile(bufs[pos + 3], offset);
545                offset += bufs[pos + 3].bytes_total() as u64;
546                let (res1, res2, res3, res4) = join!(op1, op2, op3, op4);
547
548                match res1 {
549                    (Err(e), _) => return (Err(e), bufs),
550                    (Ok(cnt), buf) => {
551                        count += cnt;
552                        bufs[pos] = buf;
553                        if cnt < bufs[pos].bytes_total() {
554                            return (Ok(count), bufs);
555                        }
556                    }
557                }
558                match res2 {
559                    (Err(e), _) => return (Err(e), bufs),
560                    (Ok(cnt), buf) => {
561                        count += cnt;
562                        bufs[pos + 1] = buf;
563                        if cnt < bufs[pos + 1].bytes_total() {
564                            return (Ok(count), bufs);
565                        }
566                    }
567                }
568                match res3 {
569                    (Err(e), _) => return (Err(e), bufs),
570                    (Ok(cnt), buf) => {
571                        count += cnt;
572                        bufs[pos + 2] = buf;
573                        if cnt < bufs[pos + 2].bytes_total() {
574                            return (Ok(count), bufs);
575                        }
576                    }
577                }
578                match res4 {
579                    (Err(e), _) => return (Err(e), bufs),
580                    (Ok(cnt), buf) => {
581                        count += cnt;
582                        bufs[pos + 3] = buf;
583                        if cnt < bufs[pos + 3].bytes_total() {
584                            return (Ok(count), bufs);
585                        }
586                    }
587                }
588                pos += 4;
589            }
590
591            if bufs.len() - pos == 3 {
592                let op1 = self.async_read_at_volatile(bufs[pos], offset);
593                offset += bufs[pos].bytes_total() as u64;
594                let op2 = self.async_read_at_volatile(bufs[pos + 1], offset);
595                offset += bufs[pos + 1].bytes_total() as u64;
596                let op3 = self.async_read_at_volatile(bufs[pos + 2], offset);
597                let (res1, res2, res3) = join!(op1, op2, op3);
598
599                match res1 {
600                    (Ok(cnt), buf) => {
601                        count += cnt;
602                        bufs[pos] = buf;
603                        if cnt < bufs[pos].bytes_total() {
604                            return (Ok(count), bufs);
605                        }
606                    }
607                    (Err(e), _) => return (Err(e), bufs),
608                }
609                match res2 {
610                    (Ok(cnt), buf) => {
611                        count += cnt;
612                        bufs[pos + 1] = buf;
613                        if cnt < bufs[pos + 1].bytes_total() {
614                            return (Ok(count), bufs);
615                        }
616                    }
617                    (Err(e), _) => return (Err(e), bufs),
618                }
619                match res3 {
620                    (Ok(cnt), buf) => {
621                        count += cnt;
622                        bufs[pos + 2] = buf;
623                        if cnt < bufs[pos + 2].bytes_total() {
624                            return (Ok(count), bufs);
625                        }
626                    }
627                    (Err(e), _) => return (Err(e), bufs),
628                }
629            } else if bufs.len() - pos == 2 {
630                let op1 = self.async_read_at_volatile(bufs[pos], offset);
631                offset += bufs[pos].bytes_total() as u64;
632                let op2 = self.async_read_at_volatile(bufs[pos + 1], offset);
633                let (res1, res2) = join!(op1, op2);
634
635                match res1 {
636                    (Ok(cnt), buf) => {
637                        count += cnt;
638                        bufs[pos] = buf;
639                        if cnt < bufs[pos].bytes_total() {
640                            return (Ok(count), bufs);
641                        }
642                    }
643                    (Err(e), _) => return (Err(e), bufs),
644                }
645                match res2 {
646                    (Ok(cnt), buf) => {
647                        count += cnt;
648                        bufs[pos + 1] = buf;
649                        if cnt < bufs[pos + 1].bytes_total() {
650                            return (Ok(count), bufs);
651                        }
652                    }
653                    (Err(e), _) => return (Err(e), bufs),
654                }
655            } else if bufs.len() - pos == 1 {
656                let res1 = self.async_read_at_volatile(bufs[pos], offset).await;
657                match res1 {
658                    (Ok(cnt), buf) => {
659                        count += cnt;
660                        bufs[pos] = buf;
661                        if cnt < bufs[pos].bytes_total() {
662                            return (Ok(count), bufs);
663                        }
664                    }
665                    (Err(e), _) => return (Err(e), bufs),
666                }
667            }
668
669            (Ok(count), bufs)
670        }
671
672        async fn async_write_at_volatile(
673            &self,
674            buf: FileVolatileBuf,
675            offset: u64,
676        ) -> (Result<usize>, FileVolatileBuf) {
677            self.async_write_at(buf, offset).await
678        }
679
680        async fn async_write_vectored_at_volatile(
681            &self,
682            mut bufs: Vec<FileVolatileBuf>,
683            mut offset: u64,
684        ) -> (Result<usize>, Vec<FileVolatileBuf>) {
685            if bufs.is_empty() {
686                return (Ok(0), bufs);
687            } else if bufs.len() == 1 {
688                let (res, buf) = self.async_write_at_volatile(bufs[0], offset).await;
689                bufs[0] = buf;
690                return (res, bufs);
691            }
692
693            let mut count = 0;
694            let mut pos = 0;
695            while bufs.len() - pos >= 4 {
696                let op1 = self.async_write_at_volatile(bufs[pos], offset);
697                offset += bufs[pos].bytes_total() as u64;
698                let op2 = self.async_write_at_volatile(bufs[pos + 1], offset);
699                offset += bufs[pos + 1].bytes_total() as u64;
700                let op3 = self.async_write_at_volatile(bufs[pos + 2], offset);
701                offset += bufs[pos + 2].bytes_total() as u64;
702                let op4 = self.async_write_at_volatile(bufs[pos + 3], offset);
703                offset += bufs[pos + 3].bytes_total() as u64;
704                let (res1, res2, res3, res4) = join!(op1, op2, op3, op4);
705
706                match res1 {
707                    (Err(e), _) => return (Err(e), bufs),
708                    (Ok(cnt), buf) => {
709                        count += cnt;
710                        bufs[pos] = buf;
711                        if cnt < bufs[pos].bytes_total() {
712                            return (Ok(count), bufs);
713                        }
714                    }
715                }
716                match res2 {
717                    (Err(e), _) => return (Err(e), bufs),
718                    (Ok(cnt), buf) => {
719                        count += cnt;
720                        bufs[pos + 1] = buf;
721                        if cnt < bufs[pos + 1].bytes_total() {
722                            return (Ok(count), bufs);
723                        }
724                    }
725                }
726                match res3 {
727                    (Err(e), _) => return (Err(e), bufs),
728                    (Ok(cnt), buf) => {
729                        count += cnt;
730                        bufs[pos + 2] = buf;
731                        if cnt < bufs[pos + 2].bytes_total() {
732                            return (Ok(count), bufs);
733                        }
734                    }
735                }
736                match res4 {
737                    (Err(e), _) => return (Err(e), bufs),
738                    (Ok(cnt), buf) => {
739                        count += cnt;
740                        bufs[pos + 3] = buf;
741                        if cnt < bufs[pos + 3].bytes_total() {
742                            return (Ok(count), bufs);
743                        }
744                    }
745                }
746                pos += 4;
747            }
748
749            if bufs.len() - pos == 3 {
750                let op1 = self.async_write_at_volatile(bufs[pos], offset);
751                offset += bufs[pos].bytes_total() as u64;
752                let op2 = self.async_write_at_volatile(bufs[pos + 1], offset);
753                offset += bufs[pos + 1].bytes_total() as u64;
754                let op3 = self.async_write_at_volatile(bufs[pos + 2], offset);
755                let (res1, res2, res3) = join!(op1, op2, op3);
756
757                match res1 {
758                    (Ok(cnt), buf) => {
759                        count += cnt;
760                        bufs[pos] = buf;
761                        if cnt < bufs[pos].bytes_total() {
762                            return (Ok(count), bufs);
763                        }
764                    }
765                    (Err(e), _) => return (Err(e), bufs),
766                }
767                match res2 {
768                    (Ok(cnt), buf) => {
769                        count += cnt;
770                        bufs[pos + 1] = buf;
771                        if cnt < bufs[pos + 1].bytes_total() {
772                            return (Ok(count), bufs);
773                        }
774                    }
775                    (Err(e), _) => return (Err(e), bufs),
776                }
777                match res3 {
778                    (Ok(cnt), buf) => {
779                        count += cnt;
780                        bufs[pos + 2] = buf;
781                        if cnt < bufs[pos + 2].bytes_total() {
782                            return (Ok(count), bufs);
783                        }
784                    }
785                    (Err(e), _) => return (Err(e), bufs),
786                }
787            } else if bufs.len() - pos == 2 {
788                let op1 = self.async_write_at_volatile(bufs[pos], offset);
789                offset += bufs[pos].bytes_total() as u64;
790                let op2 = self.async_write_at_volatile(bufs[pos + 1], offset);
791                let (res1, res2) = join!(op1, op2);
792
793                match res1 {
794                    (Ok(cnt), buf) => {
795                        count += cnt;
796                        bufs[pos] = buf;
797                        if cnt < bufs[pos].bytes_total() {
798                            return (Ok(count), bufs);
799                        }
800                    }
801                    (Err(e), _) => return (Err(e), bufs),
802                }
803                match res2 {
804                    (Ok(cnt), buf) => {
805                        count += cnt;
806                        bufs[pos + 1] = buf;
807                        if cnt < bufs[pos + 1].bytes_total() {
808                            return (Ok(count), bufs);
809                        }
810                    }
811                    (Err(e), _) => return (Err(e), bufs),
812                }
813            } else if bufs.len() - pos == 1 {
814                let res1 = self.async_write_at_volatile(bufs[pos], offset).await;
815                match res1 {
816                    (Ok(cnt), buf) => {
817                        count += cnt;
818                        bufs[pos] = buf;
819                        if cnt < bufs[pos].bytes_total() {
820                            return (Ok(count), bufs);
821                        }
822                    }
823                    (Err(e), _) => return (Err(e), bufs),
824                }
825            }
826
827            (Ok(count), bufs)
828        }
829    }
830
831    #[async_trait::async_trait(?Send)]
832    impl<T: AsyncFileReadWriteVolatile + ?Sized> AsyncFileReadWriteVolatile for Arc<T> {
833        async fn async_read_at_volatile(
834            &self,
835            buf: FileVolatileBuf,
836            offset: u64,
837        ) -> (Result<usize>, FileVolatileBuf) {
838            self.async_read_at_volatile(buf, offset).await
839        }
840
841        async fn async_read_vectored_at_volatile(
842            &self,
843            bufs: Vec<FileVolatileBuf>,
844            offset: u64,
845        ) -> (Result<usize>, Vec<FileVolatileBuf>) {
846            self.async_read_vectored_at_volatile(bufs, offset).await
847        }
848
849        async fn async_write_at_volatile(
850            &self,
851            buf: FileVolatileBuf,
852            offset: u64,
853        ) -> (Result<usize>, FileVolatileBuf) {
854            self.async_write_at_volatile(buf, offset).await
855        }
856
857        async fn async_write_vectored_at_volatile(
858            &self,
859            bufs: Vec<FileVolatileBuf>,
860            offset: u64,
861        ) -> (Result<usize>, Vec<FileVolatileBuf>) {
862            self.async_write_vectored_at_volatile(bufs, offset).await
863        }
864    }
865
866    #[cfg(test)]
867    mod tests {
868        use super::*;
869        use crate::async_runtime::block_on;
870        use crate::file_buf::FileVolatileSlice;
871
872        #[test]
873        fn io_uring_async_read_at_volatile() {
874            let tmpfile = vmm_sys_util::tempdir::TempDir::new().unwrap();
875            let path = tmpfile.as_path().to_path_buf().join("test.txt");
876            std::fs::write(&path, b"this is a test").unwrap();
877
878            let mut buf = vec![0; 4096];
879            block_on(async {
880                let vslice = unsafe { FileVolatileSlice::from_mut_slice(&mut buf) };
881                let vbuf = unsafe { vslice.borrow_as_buf(false) };
882                let file = File::async_open(&path, false, false).await.unwrap();
883                let (res, vbuf) = file.async_read_at_volatile(vbuf, 4).await;
884                assert_eq!(res.unwrap(), 10);
885                assert_eq!(vbuf.bytes_init(), 10);
886            });
887            assert_eq!(buf[0], b' ');
888            assert_eq!(buf[9], b't');
889        }
890
891        #[test]
892        fn io_uring_async_read_vectored_at_volatile() {
893            let tmpfile = vmm_sys_util::tempdir::TempDir::new().unwrap();
894            let path = tmpfile.as_path().to_path_buf().join("test.txt");
895            std::fs::write(&path, b"this is a test").unwrap();
896
897            let mut buf1 = vec![0; 4];
898            let mut buf2 = vec![0; 4];
899
900            block_on(async {
901                let vslice1 =
902                    unsafe { FileVolatileSlice::from_raw_ptr(buf1.as_mut_ptr(), buf1.len()) };
903                let vslice2 =
904                    unsafe { FileVolatileSlice::from_raw_ptr(buf2.as_mut_ptr(), buf2.len()) };
905                let vbufs = vec![unsafe { vslice1.borrow_as_buf(false) }, unsafe {
906                    vslice2.borrow_as_buf(false)
907                }];
908                let file = File::async_open(&path, false, false).await.unwrap();
909                let (res, vbufs) = file.async_read_vectored_at_volatile(vbufs, 4).await;
910                assert_eq!(res.unwrap(), 8);
911                assert_eq!(vbufs.len(), 2);
912            });
913            assert_eq!(buf1[0], b' ');
914            assert_eq!(buf2[3], b'e');
915
916            let mut buf1 = vec![0; 1024];
917            let mut buf2 = vec![0; 4];
918
919            block_on(async {
920                let vslice1 =
921                    unsafe { FileVolatileSlice::from_raw_ptr(buf1.as_mut_ptr(), buf1.len()) };
922                let vslice2 =
923                    unsafe { FileVolatileSlice::from_raw_ptr(buf2.as_mut_ptr(), buf2.len()) };
924                let vbufs = vec![unsafe { vslice1.borrow_as_buf(false) }, unsafe {
925                    vslice2.borrow_as_buf(false)
926                }];
927                let file = File::async_open(&path, false, false).await.unwrap();
928                let (res, vbufs) = file.async_read_vectored_at_volatile(vbufs, 4).await;
929                assert_eq!(res.unwrap(), 10);
930                assert_eq!(vbufs.len(), 2);
931                assert_eq!(vbufs[0].bytes_init(), 10);
932                assert_eq!(vbufs[1].bytes_init(), 0);
933            });
934            assert_eq!(buf1[0], b' ');
935            assert_eq!(buf1[9], b't');
936
937            block_on(async {
938                let vslice1 =
939                    unsafe { FileVolatileSlice::from_raw_ptr(buf1.as_mut_ptr(), buf1.len()) };
940                let vbufs = vec![unsafe { vslice1.borrow_as_buf(false) }];
941                let file = File::async_open(&path, false, false).await.unwrap();
942                let (res, _vbufs) = file.async_read_vectored_at_volatile(vbufs, 14).await;
943                assert_eq!(res.unwrap(), 0);
944            });
945
946            block_on(async {
947                let vbufs = vec![];
948                let file = File::async_open(&path, false, false).await.unwrap();
949                let (res, _vbufs) = file.async_read_vectored_at_volatile(vbufs, 0).await;
950                assert_eq!(res.unwrap(), 0);
951            });
952
953            block_on(async {
954                let vslice1 = unsafe { FileVolatileSlice::from_raw_ptr(buf1.as_mut_ptr(), 1) };
955                let vslice2 =
956                    unsafe { FileVolatileSlice::from_raw_ptr(buf1.as_mut_ptr().add(1), 1) };
957                let vslice3 =
958                    unsafe { FileVolatileSlice::from_raw_ptr(buf1.as_mut_ptr().add(2), 1) };
959                let vslice4 =
960                    unsafe { FileVolatileSlice::from_raw_ptr(buf1.as_mut_ptr().add(3), 1) };
961                let vslice5 =
962                    unsafe { FileVolatileSlice::from_raw_ptr(buf1.as_mut_ptr().add(4), 1) };
963                let vslice6 =
964                    unsafe { FileVolatileSlice::from_raw_ptr(buf1.as_mut_ptr().add(5), 1) };
965                let vslice7 =
966                    unsafe { FileVolatileSlice::from_raw_ptr(buf1.as_mut_ptr().add(6), 1) };
967                let vbufs = vec![
968                    unsafe { vslice1.borrow_as_buf(false) },
969                    unsafe { vslice2.borrow_as_buf(false) },
970                    unsafe { vslice3.borrow_as_buf(false) },
971                    unsafe { vslice4.borrow_as_buf(false) },
972                    unsafe { vslice5.borrow_as_buf(false) },
973                    unsafe { vslice6.borrow_as_buf(false) },
974                    unsafe { vslice7.borrow_as_buf(false) },
975                ];
976                let file = File::async_open(&path, false, false).await.unwrap();
977                let (res, vbufs) = file.async_read_vectored_at_volatile(vbufs, 4).await;
978                assert_eq!(res.unwrap(), 7);
979                assert_eq!(vbufs.len(), 7);
980                assert_eq!(buf1[0], b' ');
981                assert_eq!(buf1[1], b'i');
982                assert_eq!(buf1[2], b's');
983                assert_eq!(buf1[3], b' ');
984                assert_eq!(buf1[4], b'a');
985                assert_eq!(buf1[5], b' ');
986                assert_eq!(buf1[6], b't');
987            });
988
989            block_on(async {
990                let vslice1 = unsafe { FileVolatileSlice::from_raw_ptr(buf1.as_mut_ptr(), 1) };
991                let vslice2 =
992                    unsafe { FileVolatileSlice::from_raw_ptr(buf1.as_mut_ptr().add(1), 1) };
993                let vslice3 =
994                    unsafe { FileVolatileSlice::from_raw_ptr(buf1.as_mut_ptr().add(2), 1) };
995                let vslice4 =
996                    unsafe { FileVolatileSlice::from_raw_ptr(buf1.as_mut_ptr().add(3), 1) };
997                let vslice5 =
998                    unsafe { FileVolatileSlice::from_raw_ptr(buf1.as_mut_ptr().add(4), 1) };
999                let vslice6 =
1000                    unsafe { FileVolatileSlice::from_raw_ptr(buf1.as_mut_ptr().add(5), 1) };
1001                let vbufs = vec![
1002                    unsafe { vslice1.borrow_as_buf(false) },
1003                    unsafe { vslice2.borrow_as_buf(false) },
1004                    unsafe { vslice3.borrow_as_buf(false) },
1005                    unsafe { vslice4.borrow_as_buf(false) },
1006                    unsafe { vslice5.borrow_as_buf(false) },
1007                    unsafe { vslice6.borrow_as_buf(false) },
1008                ];
1009                let file = File::async_open(&path, false, false).await.unwrap();
1010                let (res, vbufs) = file.async_read_vectored_at_volatile(vbufs, 4).await;
1011                assert_eq!(res.unwrap(), 6);
1012                assert_eq!(vbufs.len(), 6);
1013            });
1014
1015            block_on(async {
1016                let vslice1 = unsafe { FileVolatileSlice::from_raw_ptr(buf1.as_mut_ptr(), 1) };
1017                let vslice2 =
1018                    unsafe { FileVolatileSlice::from_raw_ptr(buf1.as_mut_ptr().add(1), 1) };
1019                let vslice3 =
1020                    unsafe { FileVolatileSlice::from_raw_ptr(buf1.as_mut_ptr().add(2), 1) };
1021                let vslice4 =
1022                    unsafe { FileVolatileSlice::from_raw_ptr(buf1.as_mut_ptr().add(3), 1) };
1023                let vslice5 =
1024                    unsafe { FileVolatileSlice::from_raw_ptr(buf1.as_mut_ptr().add(4), 1) };
1025                let vbufs = vec![
1026                    unsafe { vslice1.borrow_as_buf(false) },
1027                    unsafe { vslice2.borrow_as_buf(false) },
1028                    unsafe { vslice3.borrow_as_buf(false) },
1029                    unsafe { vslice4.borrow_as_buf(false) },
1030                    unsafe { vslice5.borrow_as_buf(false) },
1031                ];
1032                let file = File::async_open(&path, false, false).await.unwrap();
1033                let (res, vbufs) = file.async_read_vectored_at_volatile(vbufs, 4).await;
1034                assert_eq!(res.unwrap(), 5);
1035                assert_eq!(vbufs.len(), 5);
1036            });
1037
1038            block_on(async {
1039                let vslice1 = unsafe { FileVolatileSlice::from_raw_ptr(buf1.as_mut_ptr(), 1) };
1040                let vslice2 =
1041                    unsafe { FileVolatileSlice::from_raw_ptr(buf1.as_mut_ptr().add(1), 1) };
1042                let vslice3 =
1043                    unsafe { FileVolatileSlice::from_raw_ptr(buf1.as_mut_ptr().add(2), 1) };
1044                let vslice4 =
1045                    unsafe { FileVolatileSlice::from_raw_ptr(buf1.as_mut_ptr().add(3), 1) };
1046                let vbufs = vec![
1047                    unsafe { vslice1.borrow_as_buf(false) },
1048                    unsafe { vslice2.borrow_as_buf(false) },
1049                    unsafe { vslice3.borrow_as_buf(false) },
1050                    unsafe { vslice4.borrow_as_buf(false) },
1051                ];
1052                let file = File::async_open(&path, false, false).await.unwrap();
1053                let (res, vbufs) = file.async_read_vectored_at_volatile(vbufs, 4).await;
1054                assert_eq!(res.unwrap(), 4);
1055                assert_eq!(vbufs.len(), 4);
1056            });
1057
1058            block_on(async {
1059                let vslice1 = unsafe { FileVolatileSlice::from_raw_ptr(buf1.as_mut_ptr(), 1) };
1060                let vslice2 =
1061                    unsafe { FileVolatileSlice::from_raw_ptr(buf1.as_mut_ptr().add(1), 1) };
1062                let vslice3 =
1063                    unsafe { FileVolatileSlice::from_raw_ptr(buf1.as_mut_ptr().add(2), 1) };
1064                let vbufs = vec![
1065                    unsafe { vslice1.borrow_as_buf(false) },
1066                    unsafe { vslice2.borrow_as_buf(false) },
1067                    unsafe { vslice3.borrow_as_buf(false) },
1068                ];
1069                let file = File::async_open(&path, false, false).await.unwrap();
1070                let (res, vbufs) = file.async_read_vectored_at_volatile(vbufs, 4).await;
1071                assert_eq!(res.unwrap(), 3);
1072                assert_eq!(vbufs.len(), 3);
1073            });
1074        }
1075    }
1076}
1077
1078#[cfg(test)]
1079mod tests {
1080    use super::*;
1081    use std::io::{Seek, SeekFrom, Write};
1082    use vmm_sys_util::tempfile::TempFile;
1083
1084    #[test]
1085    fn test_read_volatile() {
1086        let mut file = TempFile::new().unwrap().into_file();
1087
1088        let buf = [0xfu8; 32];
1089        file.write_all(&buf).unwrap();
1090        file.seek(SeekFrom::Start(0)).unwrap();
1091
1092        let mut buf2 = [0x0u8; 32];
1093        let slice =
1094            unsafe { FileVolatileSlice::from_raw_ptr(buf2.as_mut_ptr() as *mut u8, buf2.len()) };
1095        assert_eq!(file.read_volatile(slice).unwrap(), 32);
1096        assert_eq!(buf, buf2);
1097
1098        assert_eq!(file.read_volatile(slice).unwrap(), 0);
1099    }
1100
1101    #[test]
1102    fn test_read_vectored_volatile() {
1103        let mut file = TempFile::new().unwrap().into_file();
1104
1105        let buf = [0xfu8; 32];
1106        file.write_all(&buf).unwrap();
1107        file.seek(SeekFrom::Start(0)).unwrap();
1108
1109        let mut buf2 = [0x0u8; 32];
1110        let slices = unsafe {
1111            [
1112                FileVolatileSlice::from_raw_ptr(buf2.as_mut_ptr() as *mut u8, 16),
1113                FileVolatileSlice::from_raw_ptr((buf2.as_mut_ptr() as *mut u8).add(16), 16),
1114            ]
1115        };
1116        assert_eq!(file.read_vectored_volatile(&slices).unwrap(), 32);
1117        assert_eq!(buf, buf2);
1118
1119        assert_eq!(file.read_vectored_volatile(&slices).unwrap(), 0);
1120    }
1121
1122    #[test]
1123    fn test_read_exact_volatile() {
1124        let mut file = TempFile::new().unwrap().into_file();
1125
1126        let buf = [0xfu8; 32];
1127        file.write_all(&buf).unwrap();
1128        file.seek(SeekFrom::Start(0)).unwrap();
1129
1130        let mut buf2 = [0x0u8; 31];
1131        let slice =
1132            unsafe { FileVolatileSlice::from_raw_ptr(buf2.as_mut_ptr() as *mut u8, buf2.len()) };
1133        file.read_exact_volatile(slice).unwrap();
1134        assert_eq!(buf[..31], buf2);
1135
1136        file.read_exact_volatile(slice).unwrap_err();
1137    }
1138
1139    #[test]
1140    fn test_read_at_volatile() {
1141        let mut file = TempFile::new().unwrap().into_file();
1142
1143        let buf = [0xfu8; 32];
1144        file.write_all(&buf).unwrap();
1145
1146        let mut buf2 = [0x0u8; 32];
1147        let slice =
1148            unsafe { FileVolatileSlice::from_raw_ptr(buf2.as_mut_ptr() as *mut u8, buf2.len()) };
1149        assert_eq!(file.read_at_volatile(slice, 0).unwrap(), 32);
1150        assert_eq!(buf, buf2);
1151
1152        assert_eq!(file.read_at_volatile(slice, 30).unwrap(), 2);
1153        assert_eq!(file.read_at_volatile(slice, 32).unwrap(), 0);
1154    }
1155
1156    #[test]
1157    fn test_read_vectored_at_volatile() {
1158        let mut file = TempFile::new().unwrap().into_file();
1159
1160        let buf = [0xfu8; 32];
1161        file.write_all(&buf).unwrap();
1162
1163        let mut buf2 = [0x0u8; 32];
1164        let slices = unsafe {
1165            [
1166                FileVolatileSlice::from_raw_ptr(buf2.as_mut_ptr() as *mut u8, 16),
1167                FileVolatileSlice::from_raw_ptr((buf2.as_mut_ptr() as *mut u8).add(16), 16),
1168            ]
1169        };
1170        assert_eq!(file.read_vectored_at_volatile(&slices, 0).unwrap(), 32);
1171        assert_eq!(buf, buf2);
1172
1173        assert_eq!(file.read_vectored_at_volatile(&slices, 30).unwrap(), 2);
1174        assert_eq!(file.read_vectored_at_volatile(&slices, 32).unwrap(), 0);
1175    }
1176
1177    #[test]
1178    fn test_read_exact_at_volatile() {
1179        let mut file = TempFile::new().unwrap().into_file();
1180
1181        let buf = [0xfu8; 32];
1182        file.write_all(&buf).unwrap();
1183
1184        let mut buf2 = [0x0u8; 32];
1185        let slice =
1186            unsafe { FileVolatileSlice::from_raw_ptr(buf2.as_mut_ptr() as *mut u8, buf2.len()) };
1187        file.read_exact_at_volatile(slice, 0).unwrap();
1188        assert_eq!(buf, buf2);
1189
1190        file.read_exact_at_volatile(slice, 30).unwrap_err();
1191        file.read_exact_at_volatile(slice, 32).unwrap_err();
1192    }
1193
1194    #[test]
1195    fn test_write_volatile() {
1196        let mut file = TempFile::new().unwrap().into_file();
1197
1198        let mut buf = [0xfu8; 32];
1199        let slice1 =
1200            unsafe { FileVolatileSlice::from_raw_ptr(buf.as_mut_ptr() as *mut u8, buf.len()) };
1201        file.write_volatile(slice1).unwrap();
1202        file.seek(SeekFrom::Start(0)).unwrap();
1203
1204        let mut buf2 = [0x0u8; 32];
1205        let slice =
1206            unsafe { FileVolatileSlice::from_raw_ptr(buf2.as_mut_ptr() as *mut u8, buf2.len()) };
1207        assert_eq!(file.read_volatile(slice).unwrap(), 32);
1208        assert_eq!(buf, buf2);
1209
1210        assert_eq!(file.read_volatile(slice).unwrap(), 0);
1211    }
1212
1213    #[test]
1214    fn test_write_vectored_volatile() {
1215        let mut file = TempFile::new().unwrap().into_file();
1216
1217        let mut buf = [0xfu8; 32];
1218        let slices1 = unsafe {
1219            [
1220                FileVolatileSlice::from_raw_ptr(buf.as_mut_ptr() as *mut u8, 16),
1221                FileVolatileSlice::from_raw_ptr((buf.as_mut_ptr() as *mut u8).add(16), 16),
1222            ]
1223        };
1224        file.write_vectored_volatile(&slices1).unwrap();
1225        file.seek(SeekFrom::Start(0)).unwrap();
1226
1227        let mut buf2 = [0x0u8; 32];
1228        let slices = unsafe {
1229            [
1230                FileVolatileSlice::from_raw_ptr(buf2.as_mut_ptr() as *mut u8, 16),
1231                FileVolatileSlice::from_raw_ptr((buf2.as_mut_ptr() as *mut u8).add(16), 16),
1232            ]
1233        };
1234        assert_eq!(file.read_vectored_volatile(&slices).unwrap(), 32);
1235        assert_eq!(buf, buf2);
1236
1237        assert_eq!(file.read_vectored_volatile(&slices).unwrap(), 0);
1238    }
1239
1240    #[test]
1241    fn test_write_exact_volatile() {
1242        let mut file = TempFile::new().unwrap().into_file();
1243
1244        let mut buf = [0xfu8; 32];
1245        let slice1 =
1246            unsafe { FileVolatileSlice::from_raw_ptr(buf.as_mut_ptr() as *mut u8, buf.len()) };
1247        file.write_all_volatile(slice1).unwrap();
1248        file.seek(SeekFrom::Start(0)).unwrap();
1249
1250        let mut buf2 = [0x0u8; 32];
1251        let slice =
1252            unsafe { FileVolatileSlice::from_raw_ptr(buf2.as_mut_ptr() as *mut u8, buf2.len()) };
1253        file.read_exact_volatile(slice).unwrap();
1254        assert_eq!(buf, buf2);
1255
1256        file.read_exact_volatile(slice).unwrap_err();
1257    }
1258
1259    #[test]
1260    fn test_write_at_volatile() {
1261        let mut file = TempFile::new().unwrap().into_file();
1262
1263        let mut buf = [0xfu8; 32];
1264        let slice1 =
1265            unsafe { FileVolatileSlice::from_raw_ptr(buf.as_mut_ptr() as *mut u8, buf.len()) };
1266        file.write_volatile(slice1).unwrap();
1267        file.seek(SeekFrom::Start(0)).unwrap();
1268
1269        let mut buf2 = [0x0u8; 32];
1270        let slice =
1271            unsafe { FileVolatileSlice::from_raw_ptr(buf2.as_mut_ptr() as *mut u8, buf2.len()) };
1272        assert_eq!(file.read_at_volatile(slice, 0).unwrap(), 32);
1273        assert_eq!(buf, buf2);
1274
1275        assert_eq!(file.read_at_volatile(slice, 30).unwrap(), 2);
1276        assert_eq!(file.read_at_volatile(slice, 32).unwrap(), 0);
1277    }
1278
1279    #[test]
1280    fn test_write_vectored_at_volatile() {
1281        let mut file = TempFile::new().unwrap().into_file();
1282
1283        let mut buf = [0xfu8; 32];
1284        let slices1 = unsafe {
1285            [
1286                FileVolatileSlice::from_raw_ptr(buf.as_mut_ptr() as *mut u8, 16),
1287                FileVolatileSlice::from_raw_ptr((buf.as_mut_ptr() as *mut u8).add(16), 16),
1288            ]
1289        };
1290        file.write_vectored_volatile(&slices1).unwrap();
1291        file.seek(SeekFrom::Start(0)).unwrap();
1292
1293        let mut buf2 = [0x0u8; 32];
1294        let slices = unsafe {
1295            [
1296                FileVolatileSlice::from_raw_ptr(buf2.as_mut_ptr() as *mut u8, 16),
1297                FileVolatileSlice::from_raw_ptr((buf2.as_mut_ptr() as *mut u8).add(16), 16),
1298            ]
1299        };
1300        assert_eq!(file.read_vectored_at_volatile(&slices, 0).unwrap(), 32);
1301        assert_eq!(buf, buf2);
1302
1303        assert_eq!(file.read_vectored_at_volatile(&slices, 30).unwrap(), 2);
1304        assert_eq!(file.read_vectored_at_volatile(&slices, 32).unwrap(), 0);
1305    }
1306
1307    #[test]
1308    fn test_write_exact_at_volatile() {
1309        let mut file = TempFile::new().unwrap().into_file();
1310
1311        let mut buf = [0xfu8; 32];
1312        let slice1 =
1313            unsafe { FileVolatileSlice::from_raw_ptr(buf.as_mut_ptr() as *mut u8, buf.len()) };
1314        file.write_all_volatile(slice1).unwrap();
1315        file.seek(SeekFrom::Start(0)).unwrap();
1316
1317        let mut buf2 = [0x0u8; 32];
1318        let slice =
1319            unsafe { FileVolatileSlice::from_raw_ptr(buf2.as_mut_ptr() as *mut u8, buf2.len()) };
1320        file.read_exact_at_volatile(slice, 0).unwrap();
1321        assert_eq!(buf, buf2);
1322
1323        file.read_exact_at_volatile(slice, 30).unwrap_err();
1324        file.read_exact_at_volatile(slice, 32).unwrap_err();
1325    }
1326}