1use 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
26pub trait FileSetLen {
31 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
43pub trait FileReadWriteVolatile {
45 fn read_volatile(&mut self, slice: FileVolatileSlice) -> Result<usize>;
48
49 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 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 slice = slice.offset(bytes_read).unwrap();
72 }
73 Ok(())
74 }
75
76 fn write_volatile(&mut self, slice: FileVolatileSlice) -> Result<usize>;
79
80 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 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 slice = slice.offset(bytes_written).unwrap();
103 }
104 Ok(())
105 }
106
107 fn read_at_volatile(&mut self, slice: FileVolatileSlice, offset: u64) -> Result<usize>;
110
111 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 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 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 fn write_at_volatile(&mut self, slice: FileVolatileSlice, offset: u64) -> Result<usize>;
154
155 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 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 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 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 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 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 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 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 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 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 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 #[async_trait::async_trait(?Send)]
470 pub trait AsyncFileReadWriteVolatile {
471 async fn async_read_at_volatile(
475 &self,
476 buf: FileVolatileBuf,
477 offset: u64,
478 ) -> (Result<usize>, FileVolatileBuf);
479
480 async fn async_read_vectored_at_volatile(
490 &self,
491 bufs: Vec<FileVolatileBuf>,
492 offset: u64,
493 ) -> (Result<usize>, Vec<FileVolatileBuf>);
494
495 async fn async_write_at_volatile(
498 &self,
499 buf: FileVolatileBuf,
500 offset: u64,
501 ) -> (Result<usize>, FileVolatileBuf);
502
503 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}