From 1078eef0318fb3b7f4141496e6a5b10ec1deef13 Mon Sep 17 00:00:00 2001 From: Devon Date: Sun, 25 Aug 2024 15:26:00 -0500 Subject: [PATCH 1/5] fallocate: zeroed out partial start and end page --- linux/fs/squirrelfs/h_file.rs | 73 ++++++++++++++++++++++++++++++++--- 1 file changed, 68 insertions(+), 5 deletions(-) diff --git a/linux/fs/squirrelfs/h_file.rs b/linux/fs/squirrelfs/h_file.rs index c36fb140a..2e8978fd5 100644 --- a/linux/fs/squirrelfs/h_file.rs +++ b/linux/fs/squirrelfs/h_file.rs @@ -3,6 +3,7 @@ use crate::defs::*; use crate::h_inode::*; use crate::typestate::*; use crate::volatile::*; +use crate::namei::*; use crate::{end_timing, fence_vec, init_timing, start_timing}; use core::{ffi, marker::Sync, ptr, sync::atomic::Ordering}; use kernel::prelude::*; @@ -20,6 +21,16 @@ impl file::OpenAdapter for Adapter { } } +enum FALLOC_FLAG { + FALLOC_FL_KEEP_SIZE = 0x01, + FALLOC_FL_PUNCH_HOLE = 0x02, + // FALLOC_FL_NO_HIDE_STALE = 0x04, + FALLOC_FL_COLLAPSE_RANGE = 0x08, + FALLOC_FL_ZERO_RANGE = 0x10, + FALLOC_FL_INSERT_RANGE = 0x20, + // FALLOC_FL_UNSHARE_RANGE = 0x40, +} + pub(crate) struct FileOps; #[vtable] impl file::Operations for FileOps { @@ -129,12 +140,64 @@ impl file::Operations for FileOps { fn fallocate( _data: (), - _file: &file::File, - _mode: i32, - _offset: i64, - _len: i64, + file: &file::File, + mode: i32, + offset: i64, + len: i64, ) -> Result { - Err(EINVAL) + let inode : &mut fs::INode = unsafe { &mut *file.inode().cast() }; + let sb = inode.i_sb(); + let fs_info_raw = unsafe { (*sb).s_fs_info }; + let sbi = unsafe { &mut *(fs_info_raw as *mut SbInfo) }; + let end_offset : i64 = len + offset; + + let pi = sbi.get_init_reg_inode_by_vfs_inode(inode.get_inner())?; + let initial_size: i64 = pi.get_size() as i64; + + if mode == 0 && end_offset > initial_size { + return match squirrelfs_truncate(sbi, pi, end_offset){ + Ok(_) => Ok(1), + Err(e) => Err(e) + } + } + else if mode & FALLOC_FLAG::FALLOC_FL_PUNCH_HOLE as i32 == 0x2 { + pr_info!("Punching a hole"); + let page_size : i64 = SQUIRRELFS_PAGESIZE.try_into()?; + let mut start_page = offset / page_size; + let mut end_page = (offset + len) / page_size; + + let start_page_offset = start_page * page_size; + let end_page_offset = (end_page + 1) * page_size; + + // zero out the first page that is partial + if start_page_offset < offset { + let partial_start_length = page_size - (offset % page_size); + let pages = DataPageListWrapper::get_data_page_list(pi.get_inode_info()?, partial_start_length.try_into()?, offset.try_into()?)?; + match pages { + Ok(pages) => { + pages.zero_pages(sbi, partial_start_length.try_into()?, offset.try_into()?)?; + start_page += 1; + }, + Err(e) => return Err(EINVAL), + } + } + + // zero out end page that is partial + if end_page_offset > end_offset { + let partial_end_length = end_offset % page_size; + let partial_end_offset = end_page_offset - page_size; + let pages = DataPageListWrapper::get_data_page_list(pi.get_inode_info()?, partial_end_length.try_into()?, + partial_end_offset.try_into()?)?; + match pages { + Ok(pages) => { + pages.zero_pages(sbi, partial_end_length.try_into()?, partial_end_offset.try_into()?)?; + end_page -= 1; + }, + Err(e) => return Err(EINVAL), + } + } + } + Ok(1) } fn ioctl(data: (), file: &file::File, cmd: &mut file::IoctlCommand) -> Result { From 9ecf5cfabe161fa512249cadaf0277c2b7d28ae4 Mon Sep 17 00:00:00 2001 From: Devon Date: Sun, 25 Aug 2024 15:26:15 -0500 Subject: [PATCH 2/5] truncate public --- linux/fs/squirrelfs/namei.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux/fs/squirrelfs/namei.rs b/linux/fs/squirrelfs/namei.rs index 77b276203..c8bdc967f 100644 --- a/linux/fs/squirrelfs/namei.rs +++ b/linux/fs/squirrelfs/namei.rs @@ -1926,7 +1926,7 @@ fn squirrelfs_symlink<'a>( } // TODO: return a type indicating that the truncate has completed -fn squirrelfs_truncate<'a>( +pub(crate) fn squirrelfs_truncate<'a>( sbi: &SbInfo, pi: InodeWrapper<'a, Clean, Start, RegInode>, size: i64, From 4c687551eda16f494f05142f587555f4c7637fb3 Mon Sep 17 00:00:00 2001 From: Devon Date: Sun, 25 Aug 2024 18:24:24 -0500 Subject: [PATCH 3/5] fallocate: fixed zero out end of partial file --- linux/fs/squirrelfs/h_file.rs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/linux/fs/squirrelfs/h_file.rs b/linux/fs/squirrelfs/h_file.rs index 2e8978fd5..d619ab596 100644 --- a/linux/fs/squirrelfs/h_file.rs +++ b/linux/fs/squirrelfs/h_file.rs @@ -164,14 +164,17 @@ impl file::Operations for FileOps { pr_info!("Punching a hole"); let page_size : i64 = SQUIRRELFS_PAGESIZE.try_into()?; let mut start_page = offset / page_size; - let mut end_page = (offset + len) / page_size; + let mut end_page = initial_size / page_size; let start_page_offset = start_page * page_size; let end_page_offset = (end_page + 1) * page_size; // zero out the first page that is partial if start_page_offset < offset { - let partial_start_length = page_size - (offset % page_size); + pr_info!("Start"); + pr_info!("{:?}", start_page_offset); + let partial_start_length = if page_size - (offset % page_size) > len {len} else {page_size - (offset % page_size)}; + pr_info!("{:?}", partial_start_length); let pages = DataPageListWrapper::get_data_page_list(pi.get_inode_info()?, partial_start_length.try_into()?, offset.try_into()?)?; match pages { Ok(pages) => { @@ -181,11 +184,13 @@ impl file::Operations for FileOps { Err(e) => return Err(EINVAL), } } - + + pr_info!("{:?}, {:?}", end_page_offset, end_offset); // zero out end page that is partial if end_page_offset > end_offset { + pr_info!("End"); let partial_end_length = end_offset % page_size; - let partial_end_offset = end_page_offset - page_size; + let partial_end_offset = if end_page_offset - page_size > offset {end_page_offset - page_size} else {offset}; let pages = DataPageListWrapper::get_data_page_list(pi.get_inode_info()?, partial_end_length.try_into()?, partial_end_offset.try_into()?)?; match pages { From c861cf430953cd0113e026815e57a071cf0e46c9 Mon Sep 17 00:00:00 2001 From: Devon Date: Sun, 25 Aug 2024 20:55:36 -0500 Subject: [PATCH 4/5] fallocate: fixed partial zero of last page in file through fixing ceiling division --- linux/fs/squirrelfs/h_file.rs | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/linux/fs/squirrelfs/h_file.rs b/linux/fs/squirrelfs/h_file.rs index d619ab596..94bc720ad 100644 --- a/linux/fs/squirrelfs/h_file.rs +++ b/linux/fs/squirrelfs/h_file.rs @@ -164,7 +164,8 @@ impl file::Operations for FileOps { pr_info!("Punching a hole"); let page_size : i64 = SQUIRRELFS_PAGESIZE.try_into()?; let mut start_page = offset / page_size; - let mut end_page = initial_size / page_size; + let mut end_page = if initial_size % page_size == 0 {initial_size / page_size - 1} + else {initial_size / page_size }; let start_page_offset = start_page * page_size; let end_page_offset = (end_page + 1) * page_size; @@ -176,13 +177,15 @@ impl file::Operations for FileOps { let partial_start_length = if page_size - (offset % page_size) > len {len} else {page_size - (offset % page_size)}; pr_info!("{:?}", partial_start_length); let pages = DataPageListWrapper::get_data_page_list(pi.get_inode_info()?, partial_start_length.try_into()?, offset.try_into()?)?; - match pages { + let (_bytes_written, pages) = match pages { Ok(pages) => { - pages.zero_pages(sbi, partial_start_length.try_into()?, offset.try_into()?)?; + let (bytes_written, pages) = pages.zero_pages(sbi, partial_start_length.try_into()?, offset.try_into()?)?; start_page += 1; + (bytes_written, pages) }, Err(e) => return Err(EINVAL), - } + }; + pages.fence(); } pr_info!("{:?}, {:?}", end_page_offset, end_offset); @@ -191,15 +194,20 @@ impl file::Operations for FileOps { pr_info!("End"); let partial_end_length = end_offset % page_size; let partial_end_offset = if end_page_offset - page_size > offset {end_page_offset - page_size} else {offset}; + pr_info!("{:?}, {:?}", partial_end_length, partial_end_offset); let pages = DataPageListWrapper::get_data_page_list(pi.get_inode_info()?, partial_end_length.try_into()?, partial_end_offset.try_into()?)?; - match pages { + let (_bytes_written, pages) = match pages { Ok(pages) => { - pages.zero_pages(sbi, partial_end_length.try_into()?, partial_end_offset.try_into()?)?; + pr_info!("here"); + let (bytes_written, pages) = pages.zero_pages(sbi, partial_end_length.try_into()?, partial_end_offset.try_into()?)?; end_page -= 1; + pr_info!(""); + (bytes_written, pages) }, Err(e) => return Err(EINVAL), - } + }; + pages.fence(); } } Ok(1) From 39dc3599f77066492d2131abb3238a3c5f7d95ae Mon Sep 17 00:00:00 2001 From: Devon Date: Sun, 25 Aug 2024 21:55:46 -0500 Subject: [PATCH 5/5] fallocate: deallocate pages but still seg fault on remove and cannot read --- linux/fs/squirrelfs/h_file.rs | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/linux/fs/squirrelfs/h_file.rs b/linux/fs/squirrelfs/h_file.rs index 94bc720ad..bf1e227ba 100644 --- a/linux/fs/squirrelfs/h_file.rs +++ b/linux/fs/squirrelfs/h_file.rs @@ -172,10 +172,7 @@ impl file::Operations for FileOps { // zero out the first page that is partial if start_page_offset < offset { - pr_info!("Start"); - pr_info!("{:?}", start_page_offset); let partial_start_length = if page_size - (offset % page_size) > len {len} else {page_size - (offset % page_size)}; - pr_info!("{:?}", partial_start_length); let pages = DataPageListWrapper::get_data_page_list(pi.get_inode_info()?, partial_start_length.try_into()?, offset.try_into()?)?; let (_bytes_written, pages) = match pages { Ok(pages) => { @@ -188,27 +185,35 @@ impl file::Operations for FileOps { pages.fence(); } - pr_info!("{:?}, {:?}", end_page_offset, end_offset); // zero out end page that is partial if end_page_offset > end_offset { - pr_info!("End"); let partial_end_length = end_offset % page_size; let partial_end_offset = if end_page_offset - page_size > offset {end_page_offset - page_size} else {offset}; - pr_info!("{:?}, {:?}", partial_end_length, partial_end_offset); let pages = DataPageListWrapper::get_data_page_list(pi.get_inode_info()?, partial_end_length.try_into()?, partial_end_offset.try_into()?)?; let (_bytes_written, pages) = match pages { Ok(pages) => { - pr_info!("here"); let (bytes_written, pages) = pages.zero_pages(sbi, partial_end_length.try_into()?, partial_end_offset.try_into()?)?; end_page -= 1; - pr_info!(""); (bytes_written, pages) }, Err(e) => return Err(EINVAL), }; pages.fence(); } + + if start_page <= end_page { + let full_pages_offset = start_page * page_size; + let full_pages_length = (end_page - start_page + 1) * page_size; + let (new_size, pi) = pi.dec_size(initial_size.try_into()?); + let pages = DataPageListWrapper::get_data_pages_to_truncate(&pi, full_pages_length.try_into()?, + full_pages_offset.try_into()?)?; + let pages = pages.unmap(sbi)?.fence(); + let pages = pages.dealloc(sbi)?.fence().mark_free(); + sbi.page_allocator.dealloc_data_page_list(&pages)?; + let pi_info = pi.get_inode_info()?; + pi_info.remove_pages(&pages)?; + } } Ok(1) }