Commit Graph

2672 Commits

Author SHA1 Message Date
Michael Eischer f000da3b35 Return helpful error if subfolder syntax fails on Windows (#21813) 2026-05-20 22:55:01 +02:00
Michael Eischer ccfb31b5fa filter: correctly stop pattern validation on first invalid part (#21812) 2026-05-20 22:42:26 +02:00
Michael Eischer a639b8d711 Merge pull request #21811 from MichaelEischer/misc-fixes
Address various code smells, outdated comments and nits
2026-05-20 22:38:36 +02:00
Winfried Plappert 990329013e prune more aggresively (#21803)
Co-authored-by: Michael Eischer <michael.eischer@fau.de>
2026-05-16 15:49:08 +00:00
Michael Eischer 10645ccd2a fix comment and variable name typos 2026-05-16 17:05:33 +02:00
Michael Eischer fa1a318780 fs: drop outdated comment regarding UNC paths on Windows 2026-05-16 17:05:33 +02:00
Michael Eischer 8b6eff5a47 filter: fix comment for validatePatterns 2026-05-16 17:05:33 +02:00
Michael Eischer 3cc592463f Don't lower case case-insensitive patterns in place 2026-05-16 15:35:42 +02:00
Michael Eischer c04a1d857d backend/retry: debug log correct error on failed file removal 2026-05-16 15:35:42 +02:00
Michael Eischer bd945df2ea archiver: note that fileSaver.Save expects non-blocking callbacks 2026-05-16 15:35:42 +02:00
Michael Eischer 5105015f5d check: filter packs while holding blobRefs lock
Not an actual problem with the current usage. But for consistency always
take the lock when interacting with blobRefs.
2026-05-16 15:35:42 +02:00
Michael Eischer d4397926cc restorer: drop redundant nil check 2026-05-16 15:35:42 +02:00
Michael Eischer 5caa33e7b9 repository/pack: prevent packer usage after error
In-depth hardening to prevent packer reuse after an error.
2026-05-16 15:35:42 +02:00
Michael Eischer ef750c4c5d archiver: reuse buffer if reading from file failed 2026-05-16 15:35:42 +02:00
Michael Eischer 3148494a92 archiver: check chunker error before updating the node
This is actually just a cosmetic issue as chunk.Length is 0 if the
chunker returned an error.
2026-05-16 12:03:43 +02:00
Michael Eischer 265d070255 ui: Fix data race and minor API cleanup (#21801) 2026-05-15 21:23:24 +02:00
Michael Eischer bf14a94600 Merge pull request #21784 from jtru/fuse-mount-hardlink-count
mount: Ensure a hard link count > 0 for all files
2026-05-14 11:25:20 +02:00
Michael Eischer 4547fd7b18 fuse: tweak comment 2026-05-14 11:18:16 +02:00
Michael Eischer d494e37dc1 ui/termstatus: reorder findUnchangedLines function 2026-05-14 10:42:13 +02:00
Michael Eischer 59697213f9 ui/termstatus: cleanup test code 2026-05-14 10:42:13 +02:00
Michael Eischer df2d65bb88 ui/termstatus: test skipping of unchanged lines 2026-05-14 10:42:13 +02:00
Michael Eischer bd8aad3b9b ui/termstatus: deduplicate error handling 2026-05-14 10:42:13 +02:00
Michael Eischer cf34130a05 ui/termstatus: simplify status tracking 2026-05-14 10:42:13 +02:00
Donggyu Kim e33bcede2f terminal: Do not write unchanged status lines
Check if each line of status is changed, and write
the line to the terminal only if it has changed
2026-05-14 10:42:13 +02:00
Michael Eischer 4f781b69f9 add hardlink test 2026-05-13 22:29:34 +02:00
Michael Eischer f3854cf299 Merge pull request #21796 from restic/go-1.25
Bump minimum go version to 1.25 & update dependencies
2026-05-12 18:56:09 +02:00
Michael Eischer a213daef29 windows: improve randomness of temp file name
Creating two temporary files at nearly the same time could result in a
filename collision.
2026-05-11 22:50:48 +02:00
Michael Eischer e3f065ad54 windows: ignore temporary access denied error on temp file creation 2026-05-11 22:42:51 +02:00
Michael Eischer 4c94678d7d fix linter and compilation issues 2026-05-10 17:53:29 +02:00
Michael Eischer a241652787 windows: fix hang while reading from directory 2026-05-10 17:53:29 +02:00
Michael Eischer 5c935e71fa index: also preallocate hashed array tree 2026-05-10 00:35:17 +02:00
Michael Eischer 934c615e51 index: support index preallocation 2026-05-10 00:35:17 +02:00
Michael Eischer ba638b6602 indexmap: use bloom filter to drastically speed up check for unknown blobs
Only in use on 64-bit systems. Use the upper 28bits of the id of an
index entry as bloom filter. This allows skipping the index entry
traversal most of the time if an id is not stored in the hashmap.

The bloom filter embedded in the index entry id is check each time
before following a reference to an index entry. This further reduces
the risk of false positives. The bloom filter itself is basically for
free on modern CPUs.

The main performance cost of checking for unknown blobs in the index are
the essentially random RAM accesses for the initial bucket lookup as
well as following the next pointer in the index entries. With the bloom
filter most of the time only the initial bucket lookup is necessary.

This speeds up checking for unknown blobs by a factor 5 (!), while
having no effect on the lookup of known blobs:

$ benchstat no-bloom with-bloom
name                old time/op  new time/op  delta
IndexHasUnknown-16  49.0ms ± 2%   9.9ms ± 7%  -79.70%  (p=0.000 n=10+10)
IndexHasKnown-16    48.0ms ± 3%  47.9ms ± 3%     ~     (p=0.968 n=10+9)

This bloom filter parameters m=28 k=1 were derived empirically, while
also leaving sufficient room for very large repositories. Before this
commit, the final merge index step took roughly 1 second per million
index entries. With the chosen bloom filter parameters, it would
currently take 19 hours to just merge such an index. It is safe to
assume that such large repositories don't exist.

Comparison with other parameter sets:

$ m=28 k=1 versus m=32 k=1
name                old time/op  new time/op  delta
IndexHasUnknown-16  49.0ms ± 2%   9.7ms ±16%  -80.17%  (p=0.000 n=10+10)
IndexHasKnown-16    48.0ms ± 3%  48.4ms ± 3%     ~     (p=0.436 n=10+10)

$ m=28 k=1 versus m=24 k=1
name                old time/op  new time/op  delta
IndexHasUnknown-16  49.0ms ± 2%  10.8ms ±13%  -77.90%  (p=0.000 n=10+10)
IndexHasKnown-16    48.0ms ± 3%  47.9ms ± 3%     ~     (p=0.684 n=10+10)

$ m=28 k=1 versus m=28 k=2
name                old time/op  new time/op  delta
IndexHasUnknown-16  49.0ms ± 2%  24.9ms ± 5%  -49.27%  (p=0.000 n=10+10)
IndexHasKnown-16    48.0ms ± 3%  48.0ms ± 4%     ~     (p=1.000 n=10+10)

`k=2` outright wrecks the performance. This is most likely the case as
it performs worse on longer index entry chains, which also happen to be
the expensive ones to process.

`m=32` yields diminishing returns, while getting within an order of
magnitude of the largest known restic repositories.

Design alternatives:

In principle it would be possible to add a single large bloom filter
instead of embedding them in the index entry ids. However, this bloom
filter would necessarily incur additional random memory accesses and
thus slow things down overall.
2026-05-10 00:35:17 +02:00
Michael Eischer 320f709fbc index: modernize masterindex tests
`b.Loop()` drastically shortens benchmark execution times for tests with
an expensive initialization phase as it only has to happen once now.
2026-05-10 00:35:17 +02:00
Michael Eischer e33ed5d0c1 index: make tests more representative 2026-05-10 00:35:17 +02:00
Michael Eischer 39084a912e Merge pull request #5700 from MichaelEischer/err-invalid-env 2026-05-10 00:18:40 +02:00
Michael Eischer 4c0dc9e202 index: support incremental index loading
Do not require a full index reload if only a few additional index files
have been added. This can drastically speed up loading the index in the
mount command.
2026-05-07 22:52:03 +02:00
Johannes Truschnigg 461bddb0e8 mount: Ensure a hard link count > 0 for all files
When using `restic mount` to serve a repository via a POSIX host's file
system, all files backed up from Windows systems will show up on the
mounting host with a (hard)link count of 0.

While this is not a problem in general and most programs do not even
register this strange value, some others (such as Samba's smbd(8)) will
go the extra mile and check a file's stat() results for various
properties (such as a positive non-zero link count), and refuse to
operate if any of the reported values appear off.

Since other inode properties absent from non-POSIX backup sources are
also "faked up" (e.g., the inode number) during mount and work fine in
general, the chances of this change to be in any way harmful are
probably rather slim.
2026-04-19 13:44:18 +02:00
Michael Eischer 7077500a3b Have backup -vv mention compressed size of added files (#5669)
ui: mention compressed size of added files in `backup -vv`

This is already shown for modified files, but the added files message
wasn't updated when compression was implemented in restic.

Co-authored-by: Ilya Grigoriev <ilyagr@users.noreply.github.com>
2026-02-18 21:24:29 +01:00
Michael Eischer d1937a530b clarify pack ID in decryption error (#5710)
pack ID is included in full. In addition, the error message now says
that it is a pack file.
2026-02-18 20:43:10 +01:00
Michael Eischer 5be6d9c73f fail of RESTIC_READ_CONCURRENCY or RESTIC_COMPRESSION are invalid 2026-02-01 15:57:07 +01:00
gunar 7101f11133 Fail fast for invalid RESTIC_PACK_SIZE env values (#5592)
Co-authored-by: Michael Eischer <michael.eischer@fau.de>
2026-02-01 15:45:31 +01:00
Michael Eischer 67c13c643d Merge pull request #5691 from MichaelEischer/fix-rewriter-error 2026-02-01 12:09:52 +01:00
Michael Eischer ef1d525f22 rewriter: return correct error if tree iteration fails 2026-01-31 22:07:07 +01:00
Michael Eischer 74d60ad223 rewriter: test KeepEmptyDirectory option 2026-01-31 22:01:23 +01:00
Michael Eischer 0d71f70a22 minor cleanups and typos 2026-01-31 22:01:23 +01:00
Winfried Plappert ee154ce0ab restic rewrite --include
added function Count() to the *TreeWriter methods
2026-01-31 19:58:29 +00:00
Winfried Plappert 5148608c39 restic rewrite include - based on restic 0.18.1
cmd/restic/cmd_rewrite.go:
introduction of include filters for this command:
- add include filters, add error checking code
- add new parameter 'keepEmptyDirectoryFunc' to 'walker.NewSnapshotSizeRewriter()',
  so empty directories have to be kept to keep the directory structure intact
- add parameter 'keepEmptySnapshot' to 'filterAndReplaceSnapshot()' to keep snapshots
  intact when nothing is to be included
- introduce helper function 'gatherIncludeFilters()' and 'gatherExcludeFilters()' to
  keep code flow clean

cmd/restic/cmd_rewrite_integration_test.go:
add several new tests around the 'include' functionality

internal/filter/include.go:
this is where is include filter is defined

internal/walker/rewriter.go:
- struct RewriteOpts gains field 'KeepEmtpyDirectory', which is a 'NodeKeepEmptyDirectoryFunc()'
  which defaults to nil, so that al subdirectories are kept
- function 'NewSnapshotSizeRewriter()' gains the parameter 'keepEmptyDirecoryFilter' which
  controls the management of empty subdirectories in case of include filters active

internal/data/tree.go:
gains a function Count() for checking the number if node elements in a newly built tree

internal/walker/rewriter_test.go:
function 'NewSnapshotSizeRewriter()' gets an additional parameter nil to keeps things happy

cmd/restic/cmd_repair_snapshots.go:
function 'filterAndReplaceSnapshot()' gets an additional parameter 'keepEmptySnapshot=nil'

doc/045_working_with_repos.rst:
gets to mention include filters

changelog/unreleased/issue-4278:
the usual announcement file

git rebase master -i produced this

restic rewrite include - keep linter happy

cmd/restic/cmd_rewrite_integration_test.go:
linter likes strings.Contain() better than my strings.Index() >= 0
2026-01-31 19:42:56 +00:00
Michael Eischer ce7c144aac data: add support for unknown keys to treeIterator
While not planned, it's also not completely impossible that a tree node
might get additional top-level fields. As the tree iterator is built
with a strict expectation of the top-level fields, this would result in
a parsing error. Future-proof the code by simply skipping unknown
fields.
2026-01-31 20:03:38 +01:00
Michael Eischer 81948937ca data: test DualTreeIterator 2026-01-31 20:03:38 +01:00