From 9288b52eadb5a88df93759dd728cb8dd82c0d1e7 Mon Sep 17 00:00:00 2001 From: Vitali Lovich Date: Wed, 22 Nov 2023 12:50:16 -0800 Subject: [PATCH] Trimmable buffer + expose some more DmaFile internals (#617) * Expose the inode / dev major / dev minor for the opened file * Expose DmaBuffer::trim_to_size This lets us overallocate a larger-than-needed buffer and then trim it down to size before writing. --------- Co-authored-by: Glauber Costa --- glommio/src/io/dma_file.rs | 28 ++++++++++++++++++++++++++++ glommio/src/sys/dma_buffer.rs | 6 +++++- 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/glommio/src/io/dma_file.rs b/glommio/src/io/dma_file.rs index 6b56ae737..0074e4443 100644 --- a/glommio/src/io/dma_file.rs +++ b/glommio/src/io/dma_file.rs @@ -1555,4 +1555,32 @@ pub(crate) mod test { .await .expect_err("O_TMPFILE requires opening with write permissions"); }); + + dma_file_test!(resize_dma_buf, path, _k, { + let file = OpenOptions::new() + .create_new(true) + .read(true) + .write(true) + .tmpfile(true) + .dma_open(path) + .await + .expect("Failed to open file"); + + let alignment = + (file.alignment()).max(file.stat().await.unwrap().fs_cluster_size.into()) as usize; + + let mut buffer = file.alloc_dma_buffer(2 * alignment); + buffer.as_bytes_mut()[0..alignment].fill(1); + buffer.as_bytes_mut()[alignment..].fill(2); + buffer.trim_to_size(alignment); + + assert_eq!(alignment, file.write_at(buffer, 0).await.unwrap()); + + let read = file.read_at_aligned(0, 2 * alignment).await.unwrap(); + assert_eq!(read.len(), alignment); + assert!(read.iter().all(|&b| b == 1)); + + let stat = file.stat().await.unwrap(); + assert_eq!(stat.file_size, alignment as u64, "{:?}", stat); + }); } diff --git a/glommio/src/sys/dma_buffer.rs b/glommio/src/sys/dma_buffer.rs index a38ad25f2..3f289fa6c 100644 --- a/glommio/src/sys/dma_buffer.rs +++ b/glommio/src/sys/dma_buffer.rs @@ -113,7 +113,11 @@ impl DmaBuffer { } } - pub(crate) fn trim_to_size(&mut self, newsize: usize) { + /// Reduce the length of this buffer to be `newsize`. This value must be <= the current + /// [`len`](#method.len) and is a destructive operation (length cannot be increased). + /// NOTE: When using this with DmaFile, you have to make sure that `newsize` is properly + /// aligned or the write will fail due to O_DIRECT requirements. + pub fn trim_to_size(&mut self, newsize: usize) { assert!(newsize <= self.size); self.size = newsize; }