Bug #5695


dmu_sync'ed holes do not retain birth time

Added by Matthew Ahrens almost 9 years ago. Updated almost 9 years ago.

zfs - Zettabyte File System
Start date:
Due date:
% Done:


Estimated time:
Gerrit CR:
External Bug:


In dmu_sync_ready(), a hole block pointer will have it's logical size
explicitly set as it's necessary for replay purposes. To "undo" this,
dmu_sync_done() will zero out any hole that it finds. This becomes a
problem when using the "hole_birth" feature, as this will also wipe out
any birth time that might have happened to be set on the hole.

This can be easily reproduced with a script like the following:


    # Create the needed pool and enable the needed feature to reproduce         
    zpool create tank c1t1d0                                                    
    zpool set feature@hole_birth=enabled tank                                   

    # Create the dataset and reduce the recordsize to make it easier/faster     
    # to write out full blocks                                                  
    zfs create tank/fish                                                        
    zfs set recordsize=1K tank/fish                                             

    # Needed for zero blocks to be converted into holes. Otherwise, it would    
    # be difficult to create holes on-demand.                                   
    zfs set compress=on tank/fish                                               

    # Needed to force even small synchronous writes to go to the main pool,     
    # rather than the log device. This is necessary to reproduce the issue      
    # using such small block sizes.                                             
    zfs set logbias=throughput tank/fish                                        

    # Force synchronous writes to trigger the functions in question             
    # (i.e. dmu_sync_ready(), and dmu_sync_done())                              
    zfs set sync=always tank/fish                                               

    # Create a 4K file with the following format:                               
    #        1K     1K     1K     1K                                            
    #     +------+------+------+------+                                         
    #     | DATA | HOLE | DATA | HOLE |                                         
    #     +------+------+------+------+                                         
    dd if=/dev/urandom of=/tank/fish/sync-always count=4 bs=1K >/dev/null 2>&1 && sync
    dd if=/dev/zero    of=/tank/fish/sync-always count=1 bs=1K seek=1 conv=notrunc >/dev/null 2>&1 && sync
    dd if=/dev/zero    of=/tank/fish/sync-always count=1 bs=1K seek=3 conv=notrunc >/dev/null 2>&1 && sync

This script should create a file with two holes with non zero birth
times, but due to this bug that will not happen. Instead, the two holes
will have birth times of zeros.

As a fix, the logic to zero out a hole is only applied to old style
holes with a birth time of zero. Holes created with the "hole_birth"
feature enabled will have a non-zero birth time, and will be skipped
(thus preserving the ltime, type, and level information as well).

In addition, zdb was updated to also print the ltime, type, and level
information for these new style holes. Previously, only the logical
birth time would be printed.

Actions #1

Updated by Electric Monk almost 9 years ago

  • Status changed from New to Closed
  • % Done changed from 0 to 100

git commit 70163ac57e58ace1c5c94dfbe85dca5a974eff36

commit  70163ac57e58ace1c5c94dfbe85dca5a974eff36
Author: Prakash Surya <>
Date:   2015-03-24T16:55:41.000Z

    5695 dmu_sync'ed holes do not retain birth time
    Reviewed by: Matthew Ahrens <>
    Reviewed by: George Wilson <>
    Reviewed by: Christopher Siden <>
    Reviewed by: Bayard Bell <>
    Approved by: Dan McDonald <>


Also available in: Atom PDF