From 0febb4996407bbb15aa9f671a3fd8f6e5bb59e3b Mon Sep 17 00:00:00 2001 From: sundengyu Date: Tue, 2 Jul 2024 13:12:56 +0800 Subject: [PATCH] fix(truncate): truncate will grow blocksize when extending Signed-off-by: sundengyu --- .github/workflows/ci.yml | 10 ++-- src/lib.rs | 79 +++++++++++++++++++++++++-- uzfs-sys/scripts/build_libuzfs_src.sh | 2 +- 3 files changed, 80 insertions(+), 11 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 570761f..d597a74 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,7 +13,7 @@ jobs: strategy: matrix: os: [ubuntu-latest] - rust: [stable] + rust: [nightly-2023-12-28] steps: - uses: hecrj/setup-rust-action@master @@ -31,11 +31,11 @@ jobs: run: rustup component add rustfmt - uses: Swatinem/rust-cache@v1 - run: cargo fmt --all -- --check - - uses: actions-rs/clippy-check@v1 - with: - token: ${{ secrets.GITHUB_TOKEN }} - args: --all-features - name: Check all targets run: make - name: Run tests run: make test + - uses: actions-rs/clippy-check@v1 + with: + token: ${{ secrets.GITHUB_TOKEN }} + args: --all-features diff --git a/src/lib.rs b/src/lib.rs index da8ce98..ba28daa 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1962,7 +1962,7 @@ mod tests { let _ = std::fs::remove_file(dev_path); } - #[tokio::test] + #[tokio::test(flavor = "multi_thread")] #[serial] async fn uzfs_write_read_test() { let dsname = "uzfs-test-pool/ds"; @@ -1971,20 +1971,20 @@ mod tests { uzfs_env_init().await; let concurrency = 64; - let mut handles = Vec::with_capacity(concurrency); let ds = Arc::new( Dataset::init(dsname, &dev_path, DatasetType::Data, 65536, false) .await .unwrap(), ); - for _ in 0..10000 { + for _ in 0..10 { + let mut handles = Vec::with_capacity(concurrency); let obj = ds.create_objects(1).await.unwrap().0[0]; let blksize = 16 << 10; for i in 0..concurrency { let ds = ds.clone(); let offset = blksize * i; - handles.push(async move { + handles.push(tokio::spawn(async move { let data: Vec<_> = (0..blksize).map(|_| rand::thread_rng().gen()).collect(); ds.write_object(obj, offset as u64, false, vec![&data]) .await @@ -1994,7 +1994,11 @@ mod tests { .await .unwrap(); assert!(read == data); - }); + })); + } + + for handle in handles { + handle.await.unwrap(); } ds.delete_object(obj).await.unwrap(); } @@ -2002,4 +2006,69 @@ mod tests { ds.close().await.unwrap(); uzfs_env_fini().await; } + + #[tokio::test] + #[serial] + async fn uzfs_truncate_test() { + let dsname = "uzfs-test-pool/ds"; + let uzfs_test_env = UzfsTestEnv::new(100 * 1024 * 1024); + let dev_path = uzfs_test_env.get_dev_path().unwrap(); + uzfs_env_init().await; + + let blksize = 65536; + let ds = Arc::new( + Dataset::init(dsname, &dev_path, DatasetType::Data, blksize, false) + .await + .unwrap(), + ); + + let iters = 10000; + let objs = ds.create_objects(iters).await.unwrap().0; + let max_end_size = blksize * 2; + let mut total_data: Vec = vec![0; max_end_size as usize]; + for obj in objs { + let write_size = rand::thread_rng().gen_range(512..max_end_size) as u64; + let truncate_size = rand::thread_rng().gen_range(512..max_end_size) as u64; + total_data.fill(0); + + let data = vec![1; write_size as usize]; + let end_size = if rand::thread_rng().gen_bool(0.5) { + total_data[..data.len()].copy_from_slice(&data); + total_data[(truncate_size as usize)..].fill(0); + ds.write_object(obj, 0, false, vec![&data]).await.unwrap(); + ds.truncate_object(obj, 0, truncate_size).await.unwrap(); + truncate_size + } else { + total_data[(truncate_size as usize)..].fill(0); + total_data[..data.len()].copy_from_slice(&data); + ds.truncate_object(obj, 0, truncate_size).await.unwrap(); + ds.write_object(obj, 0, false, vec![&data]).await.unwrap(); + std::cmp::max(write_size, truncate_size) + }; + + let read_off = rand::thread_rng().gen_range(0..end_size); + let read_size = rand::thread_rng().gen_range(0..(max_end_size as u64 - read_off)); + let actually_read = std::cmp::min(end_size - read_off, read_size); + let data = ds.read_object(obj, read_off, read_size).await.unwrap(); + assert_eq!(actually_read, data.len() as u64); + assert_eq!( + data, + total_data[(read_off as usize)..((read_off + actually_read) as usize)] + ); + + let obj_attr = ds.get_object_attr(obj).await.unwrap(); + assert_eq!(obj_attr.size, end_size); + let obj_blksize = obj_attr.blksize; + if obj_blksize < blksize { + assert!(obj_blksize >= end_size as u32); + } else { + assert_eq!(obj_blksize, blksize); + } + + ds.delete_object(obj).await.unwrap(); + } + + ds.close().await.unwrap(); + uzfs_env_fini().await; + } } diff --git a/uzfs-sys/scripts/build_libuzfs_src.sh b/uzfs-sys/scripts/build_libuzfs_src.sh index 8b642f9..aa98f9c 100755 --- a/uzfs-sys/scripts/build_libuzfs_src.sh +++ b/uzfs-sys/scripts/build_libuzfs_src.sh @@ -7,7 +7,7 @@ ENABLE_DEBUG=$2 ENABLE_ASAN=$3 ZFS_DIR=${TOP_SRCDIR}/zfs -ZFS_TAG=uzfs-1.0.0-rc22 +ZFS_TAG=uzfs-1.0.0-rc23 ZFS_PKG=zfs-${ZFS_TAG} ZFS_ZIP=${ZFS_PKG}.zip INSTALL_DIR=${TOP_SRCDIR}/install