Recreate not removing excluded files when using lvm snapshots #1053

Closed
opened 2025-04-03 19:42:14 +00:00 by bb · 7 comments
Contributor

What I'm trying to do and why

I tried the new recreate command after adding a few additional exclude_patterns to my config. I expected the excluded files to be gone after recreeate, but they stayed available. The main motivation was freeing up space used by big temporary files I didn't exclude during the first few backups.

Steps to reproduce

  1. Create one or more backups using a config file:
  2. the config file by adding some exclude_patterns, e.g. - /home/foo/bar*/tmp/*.zst
  3. Create another backup to confirm that the exclude patterns actually match
  4. Observe that the newly excluded files are still existent in the old archives but not existent in the newly created archive, e.g. by running borgmatic -c foo.yaml -v 2 list --find "/home/foo/bar*/tmp/*.zst"
  5. Run borgmatic recreate to get rid of all newly excluded files in all archives:borgmatic -c foo -v 2 recreate (observe that borgmatic is actually looking into each old archive)
  6. run borgmatic -c foo.yaml -v 2 prune compact (I'm actually not sure if this is needed. Is it? I guess it's not needed for listing, but it might be needed to actually free up the space. Would be great if this was documented.
    • EDIT: it's not needed to get files out of the listing. It's not needed to get the new deduplicated size shown in info. But it is needed to actually free up the space. Running compact logged Remote: compaction freed about 28.37 GB repository space. after applying the workaround mentioned below.)

Actual behavior

list --find still finds the excluded files in the older archives

Expected behavior

list --find finds nothing

Other notes / implementation ideas

low prio issue I run into while testing: existing temporary target

While trying this and that, I interrupted borgmatic using ctrl-c. Later, a recreate was failing due to Archive foo-2025-03-22T03:30:03.675584.recreate already exists. Maybe it could delete that or just chose another name (at least when not using --target)

low prio question

While waiting to recreate a dozen archives, I wondered why I cannot run read-only operations like info, list without acquiring an exclusive lock.

observation and possible reason for this issue

list --find lists the files like this:
tmp/borgmatic-b7547a4w/borgmatic/lvm_snapshots/3751af5bd81011e6d21d/home/foo/bar-baz/tmp/baz_latest.tar.zst

I guess recreate needs to respect the lvm-specific prefix. This may also be relevant for the other snapshotting mechanisms like zfs, btffs.

verification and workaround

To verify this theory, I changed the exclude from - /home/foo/bar*/tmp/*.zst to - '**/home/foo/bar*/tmp/*.zst' and re-ran recreate. This actually removed the files from the old archives. After that, compact freed up the space.

borgmatic version

2.0.0.dev0 (HEAD is d5d04b89dc)

borgmatic installation method

pipx install --editable .

Borg version

borg 1.4.0 (with borg 1.2.8 on the server; the server is a Hetzner storage box)

Python version

Python 3.13.2

Database version (if applicable)

No response

Operating system and version

No response

### What I'm trying to do and why I tried the new recreate command after adding a few additional exclude_patterns to my config. I expected the excluded files to be gone after recreeate, but they stayed available. The main motivation was freeing up space used by big temporary files I didn't exclude during the first few backups. ### Steps to reproduce 1. Create one or more backups using a config file: 2. the config file by adding some `exclude_patterns`, e.g. ` - /home/foo/bar*/tmp/*.zst` 3. Create another backup to confirm that the exclude patterns actually match 4. Observe that the newly excluded files are still existent in the old archives but not existent in the newly created archive, e.g. by running `borgmatic -c foo.yaml -v 2 list --find "/home/foo/bar*/tmp/*.zst"` 5. Run borgmatic recreate to get rid of all newly excluded files in all archives:`borgmatic -c foo -v 2 recreate` (observe that borgmatic is actually looking into each old archive) 6. run `borgmatic -c foo.yaml -v 2 prune compact` (I'm actually not sure if this is needed. Is it? I guess it's not needed for listing, but it might be needed to actually free up the space. Would be great if this was documented. * EDIT: it's not needed to get files out of the listing. It's not needed to get the new deduplicated size shown in `info`. But it *is* needed to actually free up the space. Running compact logged `Remote: compaction freed about 28.37 GB repository space.` after applying the workaround mentioned below.) ### Actual behavior list --find still finds the excluded files in the older archives ### Expected behavior list --find finds nothing ### Other notes / implementation ideas #### low prio issue I run into while testing: existing temporary target While trying this and that, I interrupted borgmatic using ctrl-c. Later, a `recreate` was failing due to `Archive foo-2025-03-22T03:30:03.675584.recreate already exists`. Maybe it could delete that or just chose another name (at least when *not* using `--target`) #### low prio question While waiting to recreate a dozen archives, I wondered why I cannot run read-only operations like info, list without acquiring an exclusive lock. #### observation and possible reason for this issue `list --find` lists the files like this: `tmp/borgmatic-b7547a4w/borgmatic/lvm_snapshots/3751af5bd81011e6d21d/home/foo/bar-baz/tmp/baz_latest.tar.zst` **I guess `recreate` needs to respect the lvm-specific prefix.** This may also be relevant for the other snapshotting mechanisms like zfs, btffs. #### verification and workaround To verify this theory, I changed the exclude from ` - /home/foo/bar*/tmp/*.zst` to ` - '**/home/foo/bar*/tmp/*.zst'` and re-ran `recreate`. This actually removed the files from the old archives. After that, `compact` freed up the space. ### borgmatic version 2.0.0.dev0 (HEAD is d5d04b89dcc8b509d898a6559bab2999972b1e13) ### borgmatic installation method pipx install --editable . ### Borg version borg 1.4.0 (with borg 1.2.8 on the server; the server is a Hetzner storage box) ### Python version Python 3.13.2 ### Database version (if applicable) _No response_ ### Operating system and version _No response_
bb changed title from Recreate not pruning/compacting files when using lvm snapshots to Recreate not removing excluded files when using lvm snapshots 2025-04-03 19:42:58 +00:00
Owner

Wow, thanks for taking this unreleased feature for a spin! That's brave of you. I think your theory is correct that the exclude patterns aren't matching because of how the LVM snapshot paths are stored.

The good news is that the "fix" for LVM paths being stored that way is to upgrade your server to Borg 1.4.x+. With that version of Borg, borgmatic stores LVM snapshot paths without the tmp/borgmatic-b7547a4w/borgmatic/lvm_snapshots/3751af5bd81011e6d21d path prefix, so the archive file path looks just like any other file—which your exclude patterns will match. With older versions of Borg (like 1.2.8), the path stripping feature isn't available and so borgmatic falls back to storing the "full" snapshot path. (This is mentioned briefly in the docs.)

The bad news is that this doesn't help you with any of your already-snapshotted file paths. But the **/ exclude path work-around you discovered should address the problem. And because this is a problem solved "properly" by newer versions of Borg, I'm not really wild about modifying recreate or exclude patterns in general to compensate for it.

Other questions you had:

  • Yes, the compact is needed to actually free up space. I just added this to the --help at your suggestion.
  • The "archive already exists" issue: When I get a chance, I'll look into this to see if anything can be done!
  • Exclusive lock: I think this is just how Borg 1 works. You might consider using --bypass-lock, which sadly is still not implemented in borgmatic (#427), but Borg supports it natively. I will say that I don't think this is an issue with Borg 2.
Wow, thanks for taking this unreleased feature for a spin! That's brave of you. I think your theory is correct that the exclude patterns aren't matching because of how the LVM snapshot paths are stored. The good news is that the "fix" for LVM paths being stored that way is to upgrade your server to Borg 1.4.x+. With that version of Borg, borgmatic stores LVM snapshot paths without the `tmp/borgmatic-b7547a4w/borgmatic/lvm_snapshots/3751af5bd81011e6d21d` path prefix, so the archive file path looks just like any other file—which your exclude patterns will match. With older versions of Borg (like 1.2.8), the path stripping feature isn't available and so borgmatic falls back to storing the "full" snapshot path. (This is mentioned briefly in [the docs](https://torsion.org/borgmatic/docs/how-to/snapshot-your-filesystems/#subvolume-discovery).) The bad news is that this doesn't help you with any of your already-snapshotted file paths. But the `**/` exclude path work-around you discovered should address the problem. And because this is a problem solved "properly" by newer versions of Borg, I'm not really wild about modifying `recreate` or exclude patterns in general to compensate for it. Other questions you had: * Yes, the compact is needed to actually free up space. I just added this to the `--help` at your suggestion. * The "archive already exists" issue: When I get a chance, I'll look into this to see if anything can be done! * Exclusive lock: I think this is just how Borg 1 works. You might consider using `--bypass-lock`, which sadly is still not implemented in borgmatic (#427), but Borg supports it natively. I will say that I don't think this is an issue with Borg 2.
Author
Contributor

Thank you for this instant and elaborate response including answers to all questions.

It's nice to see your docs fix is not only used when calling with --help on the the command line but also on the website. That's DRY 😎

I like your priority: if it's fixed in borg 1.4, don't waste time on it. I guess I'll stick with the server-side borg version provided by Hetzner for now, but it's nice to know I could configure remote_path if I wanted to.

I'm afraid automatically just prefixing **/* (like with list --find) might even be dangerous if the exclude pattern is not very specific, so it's better up to the user to use this workaround manually, if desired.

Thank you for this instant and elaborate response including answers to all questions. It's nice to see your docs fix is not only used when calling with `--help` on the the command line but also on the website. That's DRY 😎 I like your priority: if it's fixed in borg 1.4, don't waste time on it. I guess I'll stick with the server-side borg version provided by Hetzner for now, but it's nice to know I _could_ configure `remote_path` if I wanted to. I'm afraid automatically just prefixing `**/*` (like with list --find) might even be dangerous if the exclude pattern is not very specific, so it's better up to the user to use this workaround manually, if desired.
bb closed this issue 2025-04-03 20:51:06 +00:00
Owner

I appreciate your understanding here! I'm actually going to reopen this ticket though so I remember to look into the "archive already exists" issue.

I appreciate your understanding here! I'm actually going to reopen this ticket though so I remember to look into the "archive already exists" issue.
witten 2025-04-03 22:16:12 +00:00
Owner

The solution I ended on for this one was to just display a nicer error message:

$ borgmatic -c test.yaml recreate --archive blah -v 2
...
Error running actions for repository
The archive "blah.recreate" is leftover from a prior recreate. Delete it first or select a different archive.

There are also a few other variants of this error message now for related Borg recreate errors.

I went this way because I didn't feel great about auto-deleting an archive that a user wasn't explicitly requesting to be deleted, even if it's "just" a temporary archive. And it's not always a temporary archive; borgmatic recreate --target foo can result in a Borg "archive already exists" error even though foo is not a temporary recreate archive.

Anyway, this is implemented in main and will be part of the next release.

The solution I ended on for this one was to just display a nicer error message: ``` $ borgmatic -c test.yaml recreate --archive blah -v 2 ... Error running actions for repository The archive "blah.recreate" is leftover from a prior recreate. Delete it first or select a different archive. ``` There are also a few other variants of this error message now for related Borg recreate errors. I went this way because I didn't feel great about auto-deleting an archive that a user wasn't explicitly requesting to be deleted, even if it's "just" a temporary archive. And it's not always a temporary archive; `borgmatic recreate --target foo` can result in a Borg "archive already exists" error even though `foo` is not a temporary recreate archive. Anyway, this is implemented in main and will be part of the next release.
Owner

Released in borgmatic 2.0.2!

Released in borgmatic 2.0.2!
Author
Contributor

I want to amend that Hetzner Storage Boxes actually allow choosing between Borg 1.1, 1.2 and 1.4, so we can actually use borg 1.4 by configuring remote_path: borg-1.4. The versions supported by Hetzner, the remote path argument and the current default version are documented here.

I want to amend that Hetzner Storage Boxes actually allow choosing between Borg 1.1, 1.2 and 1.4, so we can actually use borg 1.4 by configuring `remote_path: borg-1.4`. The versions supported by Hetzner, the remote path argument and the current default version are documented [here](https://docs.hetzner.com/storage/storage-box/access/access-ssh-rsync-borg/#borgbackup).
Owner

Awesome, glad to hear you can change that on the server side!

Awesome, glad to hear you can change that on the server side!
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#1053
No description provided.