dmu_sync'ed holes do not retain birth time
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:
#!/bin/sh # 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.
Updated by Electric Monk almost 5 years ago
- % Done changed from 0 to 100
- Status changed from New to Closed
commit 70163ac57e58ace1c5c94dfbe85dca5a974eff36 Author: Prakash Surya <email@example.com> Date: 2015-03-24T16:55:41.000Z 5695 dmu_sync'ed holes do not retain birth time Reviewed by: Matthew Ahrens <firstname.lastname@example.org> Reviewed by: George Wilson <email@example.com> Reviewed by: Christopher Siden <firstname.lastname@example.org> Reviewed by: Bayard Bell <email@example.com> Approved by: Dan McDonald <firstname.lastname@example.org>