Skip to content

Optimized Large File Deletion to Prevent OOM #16708

Closed
@serjponomarev

Description

@serjponomarev

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:

  1. 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.
  2. Final unlink Call: Once the file is completely truncated, perform a final unlink 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:

  1. 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
  2. Attempt to delete the file using rm /zpool/test.io, resulting in an OOM event.

  3. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type: FeatureFeature request or new feature

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions