Why df Doesn’t Immediately Reflect Disk Space After Large File Deletion (Linux Filesystem Behavior Explained)


7 views

When you run df -h after deleting a large file (like your 2.3GB log file), you might notice the freed space doesn't immediately appear. This happens because:


# Example showing the discrepancy
$ ls -lh large_file.log
-rw-r--r-- 1 user user 2.3G Jan 10 10:00 large_file.log
$ rm large_file.log
$ df -h /  # Still shows old usage stats

Most modern Linux filesystems (ext4, xfs, btrfs) handle deletes asynchronously:

  • The directory entry is removed immediately
  • Actual blocks are marked as free but not yet accounted
  • Kernel maintains cached stats until sync occurs

Try these methods to get accurate readings:


# Method 1: Force sync with filesystem
$ sync
$ df -h

# Method 2: Use lsof to check for held files
$ lsof | grep deleted

# Method 3: Check specific mount point
$ df -h /var/log  # If your file was in /var/log

The delay becomes critical in:

  • Automated cleanup scripts
  • Disk monitoring alerts
  • CI/CD pipeline storage checks

For real-time monitoring consider:


# ncdu for interactive analysis
$ ncdu /path/to/directory

# du for immediate directory stats
$ du -sh /path  # Compare before/after delete

For sysadmins needing faster updates:


# Check current commit interval (ext4)
$ cat /proc/fs/ext4/*/options | grep commit

# Temporary adjustment (seconds)
$ mount -o remount,commit=30 /dev/sdX1

Yesterday I ran into a puzzling situation - after deleting a 2.3GB Apache log file on our production Ubuntu 22.04 server, df -h kept showing the same disk usage. As someone who regularly monitors disk space, this behavior seemed counterintuitive. Here's what really happens under the hood.

When you rm a file in Linux, the space isn't immediately reclaimed because:

  • The file descriptor might still be held by a running process
  • Linux uses delayed allocation for better performance
  • Some filesystems (like ext4) maintain journaling structures
# Real example showing the behavior
$ ls -lh /var/log/apache2/access.log
-rw-r----- 1 root adm 2.3G Jun 15 09:45 /var/log/apache2/access.log

$ df -h /var
Filesystem      Size  Used Avail Use% Mounted on
/dev/sda1        50G   45G  2.5G  95% /var

$ rm /var/log/apache2/access.log

# Immediately after deletion
$ df -h /var
Filesystem      Size  Used Avail Use% Mounted on
/dev/sda1        50G   45G  2.5G  95% /var

# After 1-2 minutes
$ df -h /var
Filesystem      Size  Used Avail Use% Mounted on
/dev/sda1        50G   42G  5.5G  89% /var

If you need instant results (like in automation scripts), try these methods:

# Method 1: Sync filesystem buffers
$ sync && df -h

# Method 2: Find and kill processes holding the file
$ lsof | grep deleted
$ kill -9 [pid]

# Method 3: Use alternative tools
$ du -sh /var  # Shows actual directory usage
$ ncdu /var    # Interactive disk usage analyzer

Different filesystems handle this differently:

  • ext4: Typically updates within 30-60 seconds
  • XFS: Often shows changes immediately due to its allocation groups
  • Btrfs: May show delayed updates due to copy-on-write nature

For mission-critical systems where accurate disk monitoring is essential:

# Cron job to force regular sync (add to /etc/crontab)
*/5 * * * * root /bin/sync

# Nagios/Icinga monitoring adjustment
define service {
    service_description     Disk Space
    check_command           check_disk!20%!10%!/
    check_interval          5      # Check every 5 minutes instead of 1
}