With nested Btrfs subvolumes / LVM volumes in "source_directories", only the parent gets snapshotted #1156

Closed
opened 2025-10-02 21:08:26 +00:00 by witten · 2 comments
Owner

What I'm trying to do and why

When Btrfs subvolumes or LVM volumes consisting of nested (parent and child) paths are included in source_directories or patterns, only the parent subvolume/volumes gets snapshotted.

Steps to reproduce

  1. Create a root subvolume, e.g. at /mnt/subvolume.
  2. Create a subvolume within that subvolume, e.g. at /mnt/subvolume/subsub.
  3. Configure both subvolumes in source_directories and enable Btrfs support:
...
source_directories:
    - /mnt/subvolume/subsub
    - /mnt/subvolume

btrfs:

Actual behavior

Only /mnt/subvolume gets snapshotted:

...
1.2.borg: Snapshotting Btrfs subvolumes
1.2.borg: findmnt -t btrfs --json --list
1.2.borg: btrfs subvolume list /mnt/subvolume
1.2.borg: btrfs property get -t subvol /mnt/subvolume ro
1.2.borg: btrfs property get -t subvol /mnt/subvolume/subsub ro
1.2.borg: Creating Btrfs snapshot for /mnt/subvolume subvolume
1.2.borg: btrfs subvolume snapshot -r /mnt/subvolume /mnt/subvolume/.borgmatic-snapshot-582652/mnt/subvolume
Create readonly snapshot of '/mnt/subvolume' in '/mnt/subvolume/.borgmatic-snapshot-582652/mnt/subvolume'
1.2.borg: Writing patterns to /tmp/borgmatic-qw4gs0wo/borgmatic/tmpbu6nka8w:
R /mnt/subvolume/.borgmatic-snapshot-582652/./mnt/subvolume
R /root/tmp/test.yaml
R /tmp/borgmatic-qw4gs0wo/./borgmatic/bootstrap
! fm:/mnt/subvolume/.borgmatic-snapshot-582652/mnt/subvolume/.borgmatic-snapshot-582652
...

Expected behavior

Both subvolumes/volumes should get snapshotted independently. Snapshotting just the parent isn't sufficient, because Btrfs snapshots are per-volume and don't recurse to "child" subvolumes. Similar with LVM.

Other notes / implementation ideas

The problem here almost certainly stems from the way that borgmatic does aggressive source pattern deduplication; borgmatic sees that /mnt/subvolume contains /mnt/subvolume/subsub and therefore removes /mnt/subvolume/subsub from the source patterns with the idea that Borg will recurse into subsub. What this logic doesn't take into account is that with Btrfs, Borg won't recurse into subsub because it'll be dealing with a Btrfs snapshot of /mnt/subvolume—which doesn't contain subsub because subsub is a separate subvolume.

The purpose of aggressive deduplication is to prevent Borg hangs, e.g. when it tries to read a special file like a named pipe twice. (Named pipes are used for database backups.) So we can't just dial back the deduplication across the board. And at least currently, at the point the deduplication runs, we don't yet know whether a given pattern is a Btrfs subvolume or something else.

Ugh.

borgmatic version

main

borgmatic installation method

uv tool install --editable

Borg version

1.4.1

Python version

3.13.7

Database version (if applicable)

No response

Operating system and version

Manjaro stable

### What I'm trying to do and why When Btrfs subvolumes or LVM volumes consisting of nested (parent and child) paths are included in `source_directories` or patterns, only the parent subvolume/volumes gets snapshotted. ### Steps to reproduce 1. Create a root subvolume, e.g. at `/mnt/subvolume`. 2. Create a subvolume within that subvolume, e.g. at `/mnt/subvolume/subsub`. 3. Configure both subvolumes in `source_directories` and enable Btrfs support: ```yaml ... source_directories: - /mnt/subvolume/subsub - /mnt/subvolume btrfs: ``` ### Actual behavior Only `/mnt/subvolume` gets snapshotted: ``` ... 1.2.borg: Snapshotting Btrfs subvolumes 1.2.borg: findmnt -t btrfs --json --list 1.2.borg: btrfs subvolume list /mnt/subvolume 1.2.borg: btrfs property get -t subvol /mnt/subvolume ro 1.2.borg: btrfs property get -t subvol /mnt/subvolume/subsub ro 1.2.borg: Creating Btrfs snapshot for /mnt/subvolume subvolume 1.2.borg: btrfs subvolume snapshot -r /mnt/subvolume /mnt/subvolume/.borgmatic-snapshot-582652/mnt/subvolume Create readonly snapshot of '/mnt/subvolume' in '/mnt/subvolume/.borgmatic-snapshot-582652/mnt/subvolume' 1.2.borg: Writing patterns to /tmp/borgmatic-qw4gs0wo/borgmatic/tmpbu6nka8w: R /mnt/subvolume/.borgmatic-snapshot-582652/./mnt/subvolume R /root/tmp/test.yaml R /tmp/borgmatic-qw4gs0wo/./borgmatic/bootstrap ! fm:/mnt/subvolume/.borgmatic-snapshot-582652/mnt/subvolume/.borgmatic-snapshot-582652 ... ``` ### Expected behavior Both subvolumes/volumes should get snapshotted independently. Snapshotting just the parent isn't sufficient, because Btrfs snapshots are per-volume and don't recurse to "child" subvolumes. Similar with LVM. ### Other notes / implementation ideas The problem here almost certainly stems from the way that borgmatic does aggressive source pattern deduplication; borgmatic sees that `/mnt/subvolume` contains `/mnt/subvolume/subsub` and therefore removes `/mnt/subvolume/subsub` from the source patterns with the idea that Borg will recurse into `subsub`. What this logic doesn't take into account is that with Btrfs, Borg won't recurse into `subsub` because it'll be dealing with a Btrfs snapshot of `/mnt/subvolume`—which doesn't contain `subsub` because `subsub` is a separate subvolume. The purpose of aggressive deduplication is to prevent Borg hangs, e.g. when it tries to read a special file like a named pipe twice. (Named pipes are used for database backups.) So we can't just dial back the deduplication across the board. And at least currently, at the point the deduplication runs, we don't yet know whether a given pattern is a Btrfs subvolume or something else. Ugh. ### borgmatic version main ### borgmatic installation method uv tool install --editable ### Borg version 1.4.1 ### Python version 3.13.7 ### Database version (if applicable) _No response_ ### Operating system and version Manjaro stable
witten changed title from With nested Btrfs subvolumes in "source_directories", only the parent gets snapshotted to With nested Btrfs subvolumes / LVM volumes in "source_directories", only the parent gets snapshotted 2025-10-03 23:24:53 +00:00
Author
Owner

Fixed in main and will be part of the next release.

Fixed in main and will be part of the next release.
Author
Owner

Released in borgmatic 2.0.9!

Released in borgmatic 2.0.9!
Sign in to join this conversation.
No milestone
No assignees
1 participant
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#1156
No description provided.