From a1061d72105febfd43ac7f733100c8c60e6d3da5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20du=20Garreau?= Date: Mon, 4 Oct 2021 12:55:50 +0200 Subject: [PATCH 1/4] Add vectored positioned I/O on Unix --- library/std/src/os/unix/fs.rs | 34 ++++++++++++++++++++++++++++++++ library/std/src/sys/unix/fd.rs | 36 ++++++++++++++++++++++++++++++++++ library/std/src/sys/unix/fs.rs | 8 ++++++++ 3 files changed, 78 insertions(+) diff --git a/library/std/src/os/unix/fs.rs b/library/std/src/os/unix/fs.rs index 0284a428b5d74..631944ca259bf 100644 --- a/library/std/src/os/unix/fs.rs +++ b/library/std/src/os/unix/fs.rs @@ -54,6 +54,20 @@ pub trait FileExt { #[stable(feature = "file_offset", since = "1.15.0")] fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result; + /// Like `read_at`, except that it reads into a slice of buffers. + /// + /// Data is copied to fill each buffer in order, with the final buffer + /// written to possibly being only partially filled. This method must behave + /// equivalently to a single call to read with concatenated buffers. + #[unstable(feature = "unix_file_vectored_at", issue = "89517")] + fn read_vectored_at( + &mut self, + bufs: &mut [io::IoSliceMut<'_>], + offset: u64, + ) -> io::Result { + io::default_read_vectored(|b| self.read_at(b, offset), bufs) + } + /// Reads the exact number of byte required to fill `buf` from the given offset. /// /// The offset is relative to the start of the file and thus independent @@ -155,6 +169,16 @@ pub trait FileExt { #[stable(feature = "file_offset", since = "1.15.0")] fn write_at(&self, buf: &[u8], offset: u64) -> io::Result; + /// Like `write_at`, except that it writes from a slice of buffers. + /// + /// Data is copied from each buffer in order, with the final buffer read + /// from possibly being only partially consumed. This method must behave as + /// a call to `write_at` with the buffers concatenated would. + #[unstable(feature = "unix_file_vectored_at", issue = "89517")] + fn write_vectored_at(&mut self, bufs: &[io::IoSlice<'_>], offset: u64) -> io::Result { + io::default_write_vectored(|b| self.write_at(b, offset), bufs) + } + /// Attempts to write an entire buffer starting from a given offset. /// /// The offset is relative to the start of the file and thus independent @@ -218,9 +242,19 @@ impl FileExt for fs::File { fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result { self.as_inner().read_at(buf, offset) } + fn read_vectored_at( + &mut self, + bufs: &mut [io::IoSliceMut<'_>], + offset: u64, + ) -> io::Result { + self.as_inner().read_vectored_at(bufs, offset) + } fn write_at(&self, buf: &[u8], offset: u64) -> io::Result { self.as_inner().write_at(buf, offset) } + fn write_vectored_at(&mut self, bufs: &[io::IoSlice<'_>], offset: u64) -> io::Result { + self.as_inner().write_vectored_at(bufs, offset) + } } /// Unix-specific extensions to [`fs::Permissions`]. diff --git a/library/std/src/sys/unix/fd.rs b/library/std/src/sys/unix/fd.rs index 0956726084e02..43721e7081f5f 100644 --- a/library/std/src/sys/unix/fd.rs +++ b/library/std/src/sys/unix/fd.rs @@ -127,6 +127,24 @@ impl FileDesc { } } + #[cfg(not(target_os = "espidf"))] + pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result { + let ret = cvt(unsafe { + libc::preadv( + self.as_raw_fd(), + bufs.as_ptr() as *const libc::iovec, + cmp::min(bufs.len(), max_iov()) as c_int, + offset as i64, + ) + })?; + Ok(ret as usize) + } + + #[cfg(target_os = "espidf")] + pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result { + return crate::io::default_read_vectored(|b| self.read_at(b, offset), bufs); + } + pub fn write(&self, buf: &[u8]) -> io::Result { let ret = cvt(unsafe { libc::write( @@ -189,6 +207,24 @@ impl FileDesc { } } + #[cfg(not(target_os = "espidf"))] + pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result { + let ret = cvt(unsafe { + libc::pwritev( + self.as_raw_fd(), + bufs.as_ptr() as *const libc::iovec, + cmp::min(bufs.len(), max_iov()) as c_int, + offset as i64, + ) + })?; + Ok(ret as usize) + } + + #[cfg(target_os = "espidf")] + pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result { + return crate::io::default_write_vectored(|b| self.write_at(b, offset), bufs); + } + #[cfg(target_os = "linux")] pub fn get_cloexec(&self) -> io::Result { unsafe { Ok((cvt(libc::fcntl(self.as_raw_fd(), libc::F_GETFD))? & libc::FD_CLOEXEC) != 0) } diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs index a4fff9b2e6473..3db62ba6465b5 100644 --- a/library/std/src/sys/unix/fs.rs +++ b/library/std/src/sys/unix/fs.rs @@ -864,6 +864,10 @@ impl File { self.0.read_at(buf, offset) } + pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result { + self.0.read_vectored_at(bufs, offset) + } + pub fn write(&self, buf: &[u8]) -> io::Result { self.0.write(buf) } @@ -881,6 +885,10 @@ impl File { self.0.write_at(buf, offset) } + pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result { + self.0.write_vectored_at(bufs, offset) + } + pub fn flush(&self) -> io::Result<()> { Ok(()) } From 402bf38a39efb5033e3eb7ce65be444e84338fe9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20du=20Garreau?= Date: Mon, 4 Oct 2021 14:43:32 +0200 Subject: [PATCH 2/4] Fix CI --- library/std/src/sys/unix/fd.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/std/src/sys/unix/fd.rs b/library/std/src/sys/unix/fd.rs index 43721e7081f5f..b5f08d3893cb5 100644 --- a/library/std/src/sys/unix/fd.rs +++ b/library/std/src/sys/unix/fd.rs @@ -134,7 +134,7 @@ impl FileDesc { self.as_raw_fd(), bufs.as_ptr() as *const libc::iovec, cmp::min(bufs.len(), max_iov()) as c_int, - offset as i64, + offset as _, ) })?; Ok(ret as usize) @@ -214,7 +214,7 @@ impl FileDesc { self.as_raw_fd(), bufs.as_ptr() as *const libc::iovec, cmp::min(bufs.len(), max_iov()) as c_int, - offset as i64, + offset as _, ) })?; Ok(ret as usize) From 2358f568835f3ca2c5137e6cd13b09f2cc3ea36b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20du=20Garreau?= Date: Wed, 6 Oct 2021 10:08:00 +0200 Subject: [PATCH 3/4] Remove unidiomatic `return`s --- library/std/src/sys/unix/fd.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/library/std/src/sys/unix/fd.rs b/library/std/src/sys/unix/fd.rs index b5f08d3893cb5..51f51f65c4b08 100644 --- a/library/std/src/sys/unix/fd.rs +++ b/library/std/src/sys/unix/fd.rs @@ -85,7 +85,7 @@ impl FileDesc { #[cfg(target_os = "espidf")] pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result { - return crate::io::default_read_vectored(|b| self.read(b), bufs); + io::default_read_vectored(|b| self.read(b), bufs) } #[inline] @@ -142,7 +142,7 @@ impl FileDesc { #[cfg(target_os = "espidf")] pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result { - return crate::io::default_read_vectored(|b| self.read_at(b, offset), bufs); + io::default_read_vectored(|b| self.read_at(b, offset), bufs) } pub fn write(&self, buf: &[u8]) -> io::Result { @@ -170,7 +170,7 @@ impl FileDesc { #[cfg(target_os = "espidf")] pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result { - return crate::io::default_write_vectored(|b| self.write(b), bufs); + io::default_write_vectored(|b| self.write(b), bufs) } #[inline] @@ -222,7 +222,7 @@ impl FileDesc { #[cfg(target_os = "espidf")] pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result { - return crate::io::default_write_vectored(|b| self.write_at(b, offset), bufs); + io::default_write_vectored(|b| self.write_at(b, offset), bufs) } #[cfg(target_os = "linux")] From 2265bef42061c16abf9f4ce690f0bc373c71bdf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20du=20Garreau?= Date: Sat, 9 Oct 2021 12:06:53 +0200 Subject: [PATCH 4/4] Use mutable pointers for readv and preadv --- library/std/src/sys/unix/fd.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/std/src/sys/unix/fd.rs b/library/std/src/sys/unix/fd.rs index 51f51f65c4b08..3b2401db81d9e 100644 --- a/library/std/src/sys/unix/fd.rs +++ b/library/std/src/sys/unix/fd.rs @@ -76,7 +76,7 @@ impl FileDesc { let ret = cvt(unsafe { libc::readv( self.as_raw_fd(), - bufs.as_ptr() as *const libc::iovec, + bufs.as_mut_ptr() as *mut libc::iovec as *const libc::iovec, cmp::min(bufs.len(), max_iov()) as c_int, ) })?; @@ -132,7 +132,7 @@ impl FileDesc { let ret = cvt(unsafe { libc::preadv( self.as_raw_fd(), - bufs.as_ptr() as *const libc::iovec, + bufs.as_mut_ptr() as *mut libc::iovec as *const libc::iovec, cmp::min(bufs.len(), max_iov()) as c_int, offset as _, )