Write `buf` via an aligned bounce buffer when O_DIRECT requires it.
(fd: RawFd, buf: &[u8], offset: u64, alignment: usize)
| 170 | |
| 171 | /// Write `buf` via an aligned bounce buffer when O_DIRECT requires it. |
| 172 | pub fn aligned_pwrite(fd: RawFd, buf: &[u8], offset: u64, alignment: usize) -> io::Result<()> { |
| 173 | if alignment == 0 |
| 174 | || ((buf.as_ptr() as usize).is_multiple_of(alignment) |
| 175 | && buf.len().is_multiple_of(alignment) |
| 176 | && (offset as usize).is_multiple_of(alignment)) |
| 177 | { |
| 178 | return pwrite_all(fd, buf, offset); |
| 179 | } |
| 180 | |
| 181 | let aligned_offset = offset & !(alignment as u64 - 1); |
| 182 | let head = (offset - aligned_offset) as usize; |
| 183 | let aligned_len = (head + buf.len()).next_multiple_of(alignment); |
| 184 | let mut bounce = AlignedBuf::new(aligned_len, alignment)?; |
| 185 | |
| 186 | // Read-modify-write: read the existing aligned region, overlay our data. |
| 187 | pread_exact(fd, bounce.as_mut_slice(aligned_len), aligned_offset)?; |
| 188 | bounce.as_mut_slice(aligned_len)[head..head + buf.len()].copy_from_slice(buf); |
| 189 | pwrite_all(fd, bounce.as_slice(aligned_len), aligned_offset) |
| 190 | } |
| 191 | |
| 192 | // -- iovec helper functions -- |
| 193 | // |