Description
Describe the feature you would like to see added to OpenZFS
I propose adding an iterative approach for deleting large files in ZFS pools with deduplication enabled. Instead of calling unlink
to remove the entire file at once, we can implement a mechanism that reduces the file size from the end, freeing blocks incrementally.
How will this feature improve OpenZFS?
This feature addresses the issue of Out-Of-Memory (OOM) errors that occur when deleting large files. Currently, when unlink
is called, ZFS loads all entries from the Deduplication Data Table (DDT) related to the file into memory, which can lead to memory overload, especially on systems with limited RAM. By implementing an iterative file reduction process, we can significantly reduce memory consumption and improve stability.
Additional context
The proposed algorithm includes the following steps:
- Iterative File Truncation: Implement internal logic to incrementally truncate the file from the end, allowing ZFS to load only the necessary metadata associated with the current data size, thus minimizing memory usage.
- Final
unlink
Call: Once the file is completely truncated, perform a finalunlink
to remove any remaining metadata.
Benefits:
- Reduces the risk of OOM errors on systems with limited memory.
- Easy integration into the existing ZFS architecture without needing changes to system calls.
- Enhances overall system performance by managing memory more effectively.
Experimental Evidence
The following experiment demonstrates the basis for this proposed improvement:
Environment:
- Virtual machine with 8 vCPUs, 8 GB of RAM, and 3 NVMe drives configured into a 1.5 TB ZFS pool with deduplication enabled and
recordsize=16K
. - Debian 12.7 with ZFS version 2.1.11 from the Debian repository.
Procedure:
-
Populate the pool with a file containing random data to fully utilize the DDT:
fio --name=test --numjobs=1 --iodepth=8 --bs=1M --rw=write --ioengine=libaio --fallocate=0 --filename=/zpool/test.io --filesize=1T
-
Attempt to delete the file using
rm /zpool/test.io
, resulting in an OOM event. -
Reboot and delete the file iteratively, reducing its size by 1 GB in each iteration before final deletion:
filename=/zpool/test.io for i in $(seq $(du -BG $filename | cut -f1 | tr -d 'G') -1 0); do truncate -s "$i"G $filename echo truncated to $i G done rm -v $filename
Observation:
Memory consumption can be monitored with watch arc_summary
throughout the process.