ZFS snapshot integration causing cache miss: All files reported as 'Added' in each backup #1035

Closed
opened 2025-03-20 11:03:21 +00:00 by Flameish · 5 comments

What I'm trying to do and why

When using borgmatic with the zfs: configuration option to create snapshots, it fails to properly utilize the cache. All files are marked as "Added" during each backup, even if they already exist in the repository. When the zfs: option is removed, the cache works correctly and only new/changed files are added.

  • The backup source is a folder on a ZFS dataset
  • With zfs: in config: All files show as "Added" in each backup run
  • Without zfs: in config: Only new files show as "Added" (expected behavior)

I've attached two log files from back-to-back runs on the same test repository that demonstrate the difference in behavior. (--list --verbosity 2)

Steps to reproduce

No response

Actual behavior

No response

Expected behavior

No response

Other notes / implementation ideas

No response

borgmatic version

1.9.14

borgmatic installation method

pip

Borg version

borg 1.4.0

Python version

Python 3.11.9

Database version (if applicable)

No response

Operating system and version

TrueNAS Scale 25.04-RC.1 / Debian GNU/Linux 12 (bookworm)

### What I'm trying to do and why When using borgmatic with the zfs: configuration option to create snapshots, it fails to properly utilize the cache. All files are marked as "Added" during each backup, even if they already exist in the repository. When the zfs: option is removed, the cache works correctly and only new/changed files are added. - The backup source is a folder on a ZFS dataset - With zfs: in config: All files show as "Added" in each backup run - Without zfs: in config: Only new files show as "Added" (expected behavior) I've attached two log files from back-to-back runs on the same test repository that demonstrate the difference in behavior. (--list --verbosity 2) ### Steps to reproduce _No response_ ### Actual behavior _No response_ ### Expected behavior _No response_ ### Other notes / implementation ideas _No response_ ### borgmatic version 1.9.14 ### borgmatic installation method pip ### Borg version borg 1.4.0 ### Python version Python 3.11.9 ### Database version (if applicable) _No response_ ### Operating system and version TrueNAS Scale 25.04-RC.1 / Debian GNU/Linux 12 (bookworm)
11 KiB
11 KiB
Flameish changed title from ZFS snapshot feature doesn't recognize existing backup files to ZFS snapshot integration causing cache miss: All files reported as 'Added' in each backup 2025-03-20 11:17:05 +00:00
Owner

Thanks for the detailed ticket. Both logs you've posted appear to have all As in the file listing, so are both from when zfs: was enabled? Could I see a log from a run when it's not enabled?

In any case, my guess is that you're seeing this behavior because the temporary path for the ZFS snapshot varies from run to run because of that randomly generated component after /tmp. (Even though this does appear to be a file cache miss, Borg should still be deduplicating at the block level.) If you'd like to try removing the random component from the snapshot path, try setting borgmatic's user_runtime_directory option and then running borgmatic twice with zfs: enabled. On the second run, I'd expect you to see some Ms and not just As, indicating files cache hits.

Thanks for the detailed ticket. Both logs you've posted appear to have all `A`s in the file listing, so are both from when `zfs:` was enabled? Could I see a log from a run when it's not enabled? In any case, my guess is that you're seeing this behavior because the temporary path for the ZFS snapshot varies from run to run because of that randomly generated component after `/tmp`. (Even though this does appear to be a file cache miss, Borg should still be deduplicating at the block level.) If you'd like to try removing the random component from the snapshot path, try setting borgmatic's `user_runtime_directory` option and then running borgmatic *twice* with `zfs:` enabled. On the second run, I'd expect you to see some `M`s and not just `A`s, indicating files cache hits.
Owner

Hmm, I might actually be wrong about that. The Borg docs seem to indicate that the cache keys off of file timestamp, size, and and inode—not the file path. So maybe one of those values is changing across snapshots in such a way to trigger a Borg cache miss?

EDIT: Nope, I might've been right to begin with.. Apparently I needed to keep reading. From the linked docs:

Another possible reason is that files don’t always have the same path, for example if you mount a filesystem without stable mount points for each backup or if you are running the backup from a filesystem snapshot whose name is not stable. If the directory where you mount a filesystem is different every time, Borg assumes they are different files. This is true even if you backup these files with relative pathnames - borg uses full pathnames in files cache regardless.

Hmm, I might actually be wrong about that. [The Borg docs](https://borgbackup.readthedocs.io/en/stable/faq.html#it-always-chunks-all-my-files-even-unchanged-ones) seem to indicate that the cache keys off of file timestamp, size, and and inode—not the file path. So maybe one of those values is changing across snapshots in such a way to trigger a Borg cache miss? EDIT: Nope, I might've been right to begin with.. Apparently I needed to keep reading. From the linked docs: > Another possible reason is that files don’t always have the same path, for example if you mount a filesystem without stable mount points for each backup or if you are running the backup from a filesystem snapshot whose name is not stable. If the directory where you mount a filesystem is different every time, Borg assumes they are different files. This is true even if you backup these files with relative pathnames - borg uses full pathnames in files cache regardless.
Author

Thank you for your swift response.

so are both from when zfs: was enabled?

Yes, both previous logs are with zfs: enabled. I've attached a log (of the second run since the first adds all files) with zfs: disabled.

Borg should still be deduplicating at the block level

It does indeed deduplicate it but my backup run time went from 2 minutes to 2 hours since it's re-adding all files.

So maybe one of those values is changing across snapshots

No, the stats command says timestamp, size, and inode are the same in the original and snapshot.

my guess is that you're seeing this behavior because the temporary path for the ZFS snapshot varies from run to run

This was my guess as well. Two test runs with your suggested user_runtime_directory configuration supports this. But this path still seems to have a random id in it, or will this always be the same? Running it multiple times did not seem to change this through.

A /mnt/pool1/backup/tmp/borgmatic/zfs_snapshots/1124e7414b499df4c9c5/mnt/pool1/backup/tmp/borgmatic/bootstrap/manifest.json`

Thank you for your swift response. > so are both from when zfs: was enabled? Yes, both previous logs are with zfs: enabled. I've attached a log (of the second run since the first adds all files) with zfs: **disabled**. > Borg should still be deduplicating at the block level It does indeed deduplicate it but my backup run time went from 2 minutes to 2 hours since it's re-adding all files. > So maybe one of those values is changing across snapshots No, the `stats` command says timestamp, size, and inode are the same in the original and snapshot. > my guess is that you're seeing this behavior because the temporary path for the ZFS snapshot varies from run to run This was my guess as well. Two test runs with your suggested `user_runtime_directory` configuration supports this. But this path still seems to have a random id in it, or will this always be the same? Running it multiple times did not seem to change this through. A /mnt/pool1/backup/tmp/borgmatic/zfs_snapshots/**1124e7414b499df4c9c5**/mnt/pool1/backup/tmp/borgmatic/bootstrap/manifest.json`
Owner

Yeah, that string you bolded is a hash made from the dataset mount point path itself, so it should be constant for a given dataset and shouldn't change from run to run. It's there as a means of preventing multiple snapshots of overlapping paths (e.g. nested datasets) from colliding and causing mount/unmount problems. See #1001 for more about why this was necessary.

So if setting user_runtime_directory "fixes" the file cache issue, I should probably address this ticket by documenting the "fix." The reason that the runtime directory normally has a temporary path component is for security reasons—so another process can't interfere with the path that borgmatic is using for temporary runtime files like snapshots. But if a user sets their own runtime path, then it's assumed they know what they're doing and can secure the directory properly (unlike a shared temporary directory like /tmp).

EDIT: In Borg 1.x, it looks like Borg uses the full absolute path of the source file for the files cache key. But in Borg 2.x, Borg uses the "path as seen in the archive" instead.

Yeah, that string you bolded is a hash made from the dataset mount point path itself, so it should be constant for a given dataset and shouldn't change from run to run. It's there as a means of preventing multiple snapshots of overlapping paths (e.g. nested datasets) from colliding and causing mount/unmount problems. See #1001 for more about why this was necessary. So if [setting `user_runtime_directory`]([url](https://torsion.org/borgmatic/docs/how-to/backup-your-databases/#runtime-directory)) "fixes" the file cache issue, I should probably address this ticket by documenting the "fix." The reason that the runtime directory normally has a temporary path component is for security reasons—so another process can't interfere with the path that borgmatic is using for temporary runtime files like snapshots. But if a user sets their own runtime path, then it's assumed they know what they're doing and can secure the directory properly (unlike a shared temporary directory like `/tmp`). EDIT: In Borg 1.x, it looks like Borg uses the full absolute path of the source file for the files cache key. But in Borg 2.x, Borg uses the "path as seen in the archive" instead.
Owner

Okay, I went ahead and documented this potential issue for each of the data store snapshot hooks, including ZFS. The updated docs should be live shortly: https://torsion.org/borgmatic/docs/how-to/snapshot-your-filesystems/

Interestingly, it sounds like this whole thing is a non-issue with Borg 2.x, as it's smarter about how it creates files cache keys.

Thanks again for the ticket!

Okay, I went ahead and documented this potential issue for each of the data store snapshot hooks, including ZFS. The updated docs should be live shortly: https://torsion.org/borgmatic/docs/how-to/snapshot-your-filesystems/ Interestingly, it sounds like this whole thing is a non-issue with Borg 2.x, as it's smarter about how it creates files cache keys. Thanks again for the ticket!
Sign in to join this conversation.
No milestone
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
borgmatic-collective/borgmatic#1035
No description provided.