I'm troubleshooting some disk issues with an embedded system, and about half the time when I reboot the SATA drive is missing. The device uses a ZFS mirror for the root partition and has one SATA drive and one NVME drive. Obviously when I reboot and the SATA drive is present it needs to resilver the mirror to update the drive with the new root contents.

How does ZFS choose which blocks/files to copy? Is it based on timestamps, or is there some kind of internal counter that is used to make sure new data isn't overwritten by old data?

1 Answer 1


I think ZFS mainly rely on checksums. When a block gets written it stores as well SHA256 checksum for it. Normally it would detect bit rot or logical problems, restoring original block from the one with correct checksum.

In your case i bet it's simplier, since half the time data looks missing at all (or at least not detected)

Edit: in case of data modified while disk is not detected, from C sources it looks like vdev_uberblock_compare will directly check for timestamp in order to determine newest superblock and resilver consequently.

  • Yes but if I remove a disk and update the other, the checksums will both be valid. One disk's data will be newer, but I don't see any documentation that specifies if it just uses timestamps on the data or some other method. For example if I'm updating the /EFI/Boot/Bootx64.efi file I don't see what makes ZFS decide which one to use for the resilver.
    – user
    Feb 7, 2020 at 14:12
  • Looked a bit deeper and think key is checksum + timestamp. Checksum is only computed on write operation, and since zfs does COW blocks get "never" rewritten. Then about timestamp, i neither found anything on docs, but if you look at the source code there are a lot of "vdev_uberblock_compare" calls, that looks to determine newest block on timestamp basis. Still a bit of grey area, but i would bet on these two. Feb 7, 2020 at 14:39
  • Well that sucks. I guess I'll need to start ordering the RTC modules with it then.
    – user
    Feb 7, 2020 at 14:44
  • Looks like in module/zfs/vdev_label.c the compare function vdev_uberblock_compare will check the transaction group (ub_txg) before the timestamp (ub_timestamp). From module/zfs/txg.c the transaction group is just a 64 bit consecutive identifier (counter basically?). So I guess it does use an internal counter, but falls back to a timestamp.
    – user
    Feb 7, 2020 at 15:17
  • If you want to update the answer with the new information I'll accept it.
    – user
    Feb 7, 2020 at 15:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.