Commit graph

90 commits

Author SHA1 Message Date
Thomas Waldmann
f2b96e3d15
fastcdc: add FastCDC chunker with a keyed Gear hash
Add a new "fastcdc" content-defined chunker selectable via --chunker-params.
It uses the FastCDC Gear rolling hash (fp = (fp << 1) + Gear[byte]), which is
window-less and cheaper per byte than buzhash's cyclic-polynomial update, so it
chunks noticeably faster (see "borg benchmark cpu" output), while producing
the same chunk-size distribution and deduplication.

The Gear table is keyed: it is derived from the repo id key via CSPRNG (own
"fastcdc" domain), exactly like the buzhash64 table, so chunk cut points stay
unpredictable without the key (anti-fingerprinting). It implements the same
FastCDC techniques as buzhash64 (sub-minimum skipping, normalized chunking with
a required nc_level, min/max clamping); the mask uses the high bits of the hash
(Gear accumulates entropy there).

chunker-params: "fastcdc,chunk_min,chunk_max,chunk_mask,nc_level" - there is no
window field, because Gear is window-less. e.g. fastcdc,19,23,21,2

Also: borg benchmark cpu now measures the fastcdc chunker; tests in
borg.testsuite.chunkers (golden vector, size distribution, keyed gear table,
param parsing, slow fuzz); docs and changelog.

Benchmarks (scripts/chunker_bench.py, buzhash64 vs fastcdc, both nc_level=2,
incompressible data unless noted):

  5 GiB, 2 MiB target (default params):
    buzhash64: CV 0.294, 1011 MB/s
    fastcdc:   CV 0.295, 1313 MB/s   (+30%)

  64 MiB, 64 KiB target:
    buzhash64: CV 0.374, shift-resilience 0.9928,  963 MB/s
    fastcdc:   CV 0.359, shift-resilience 0.9929, 1331 MB/s   (+38%)

  Re-backup of a 2.5 GiB file after scattered single-byte edits (dedup ratio,
  0.5 = v2 fully deduplicated, lower is better):
     64 edits:  buzhash64 0.5237, fastcdc 0.5236
    320 edits:  buzhash64 0.6133, fastcdc 0.6161

  borg benchmark cpu, 1 GB: fastcdc 3.80s, buzhash 4.36s, buzhash64 8.13s,
  fixed 0.56s.

Chunk-size distribution, deduplication and shift-resilience match buzhash64
within noise; fastcdc is consistently faster.

Also: fix bug when computing the mask, one needs to use 1ULL instead of
1, so the shifting computation is done in a uint64, not in a 32bit int.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 23:24:25 +02:00
Thomas Waldmann
66d010c2ac
docs: update / fix "internals" section 2026-06-23 11:19:38 +02:00
Mrityunjay Raj
27d693c222 repository: read-only check by hashing pack/index objects, refs #8476 #8572
Implement the read-only repository check by hashing pack and index
objects and comparing against the stored hashes, without writing to the
repository.

Report check progress separately for the index and for the packs, each
ending at 100%.
2026-06-19 23:30:33 +05:30
Thomas Waldmann
31202ea4f1
remove xxhash / xxh64 requirement, mentions 2026-06-10 00:38:18 +02:00
Thomas Waldmann
f13dd4ddc9
repokey: use same format as with external keyfile
- always have a starting line with FILE_ID repoid
- store repkeys content-addressed, name is sha256(content)
- search by repo id on load
- add keyfile_format / keyfile_parse / is_keyfile helpers
2026-05-31 22:50:25 +02:00
Thomas Waldmann
d0167d8cdf docs: forward port DoS warning for none mode (fixes #6715) 2026-05-13 10:14:36 +02:00
Mrityunjay Raj
02f447536c docs: document platformdirs change and platform-specific directory paths, fixes #7332 2026-02-27 11:50:35 +05:30
Mrityunjay Raj
fc89a66dc7 upgrade http:// URLs to https:// and remove dead librelist.com link, fixes #9342 2026-02-16 01:42:09 +05:30
Thomas Waldmann
3120f9cd1c
fixed typos and grammar (AI)
this was done by Junie AI.
2025-09-23 14:56:23 +02:00
Thomas Waldmann
d23704e112
buzhash64: docs 2025-06-10 23:42:22 +02:00
Thomas Waldmann
7072f6263d
ChunkerParams: reject even window size for buzhash, fixes #8868 2025-05-23 06:49:52 +02:00
Thomas Waldmann
0b4ec9df1a
work around sudden failure of sphinx ini lexer
/Users/tw/w/borg/docs/internals/data-structures.rst:971:
WARNING: Lexing literal_block
'
[cache]
version = 1
repository = 3c4...e59
manifest = 10e...21c
timestamp = 2017-06-01T21:31:39.699514
key_type = 2
previous_location = /path/to/repo

[integrity]
manifest = 10e...21c
files = {"algorithm": "XXH64", "digests": {"HashHeader": "eab...39e3", "final": "e2a...b24"}}
'
as "ini" resulted in an error at token: '}'.
Retrying in relaxed mode. [misc.highlighting_failure]

Note: this part of the docs didn't change for a long time, so I guess
the sudden warning comes from a change in sphinx' lexers.

Main problem is that rc != 0 will abort our CI pipeline.
2025-01-05 19:47:40 +01:00
Thomas Waldmann
a891559578
files cache improvements, fixes #8385, fixes #5658
- changes to locally stored files cache:

  - store as files.<H(archive_name)>
  - user can manually control suffix via env var
  - if local files cache is not found, build from previous archive.
- enable rebuilding the files cache via loading the previous
  archive's metadata from the repo (better than starting with
  empty files cache and needing to read/chunk/hash all files).
  previous archive == same archive name, latest timestamp in repo.
- remove AdHocCache (not needed any more, slow)
- remove BORG_CACHE_IMPL, we only have one
- remove cache lock (this was blocking parallel backups to same
  repo from same machine/user).

Cache entries now have ctime AND mtime.

Note: TTL and age still needed for discarding removed files.
      But due to the separate files caches per series, the TTL
      was lowered to 2 (from 20).
2024-09-20 00:40:49 +02:00
Thomas Waldmann
78c7aabbb6
docs: fix usage docs and references for repo-* commands 2024-09-08 18:06:26 +02:00
Thomas Waldmann
ace97fadec
docs: updates / removing outdated stuff 2024-09-08 12:00:50 +02:00
Thomas Waldmann
d6a70f48f2
remove LocalCache
Note: this is the default cache implementation in borg 1.x,
it worked well, but there were some issues:

- if the local chunks cache got out of sync with the repository,
  it needed an expensive rebuild from the infos in all archives.
- to optimize that, a local chunks.archive.d cache was used to
  speed that up, but at the price of quite significant space needs.

AdhocCacheWithFiles replaced this with a non-persistent chunks cache,
requesting all chunkids from the repository to initialize a simplified
non-persistent chunks index, that does not do real refcounting and also
initially does not have size information for pre-existing chunks.

We want to move away from precise refcounting, LocalCache needs to die.
2024-09-07 22:00:31 +02:00
Thomas Waldmann
bd1d734591
docs: removed TAMs, introduce typed repo objects 2023-09-24 20:11:00 +02:00
Thomas Waldmann
96c3c90230
docs: remove hint about item_keys in manifest 2023-07-04 23:46:53 +02:00
Thomas Waldmann
ddd93c5828
docs: remove --chunker-params hint to borg < 1.0 2023-07-04 23:41:17 +02:00
Thomas Waldmann
bf667170a7
ArchiveItem.cmdline list-of-str -> .command_line str, fixes #7246
Same change for .recreate_cmdline -> .recreate_command_line .

JSON output key "command_line":
borg 1.x: sys.argv [list of str]
borg 2: shlex.join(sys.argv) [str]
2023-01-20 00:19:00 +01:00
Paul D
253d8e8d4e Docs grammar fixes
joined split infinitives, and relocated adverbs appropriately.
2022-12-29 22:26:54 +00:00
Paul D
a85b643866 Docs grammar fixes.
One cannot "to not x", but one can "not to x".
Avoiding split infinitives gives the added bonus that machine
translation yields better results.

setup (n/adj) vs set(v) up. We don't "I setup it" but "I set it up".

Likewise for login(n/adj) and log(v) in, backup(n/adj) and back(v) up.
2022-12-29 00:01:48 +00:00
Thomas Waldmann
c8830cde44 update docs 2022-09-08 22:26:23 +02:00
Thomas Waldmann
fb74fdb710 massively increase per archive metadata stream size limit, fixes #1473
implemented by introducing one level of indirection, the limit is now
very high, so it is not practically relevant any more.

we always use the indirection (storing the metadata stream chunk ids list not
directly into the archive item, but into some repo objects referenced by the new
ArchiveItem.item_ptrs list).

thus, the code behaves the same for all archive sizes.
2022-08-06 19:01:41 +02:00
Thomas Waldmann
d5df53732d increase Key.version to 2
Old borg (< 2.0) can not read/process the new keys that have crypt_key instead of enc_key and enc_hmac_key.
2022-08-03 12:25:58 +02:00
Thomas Waldmann
89e4a52c56 docs: misc. updates
- remove outdated stuff
- fix infos for borg 2.0
2022-08-03 11:35:25 +02:00
Jonas Schäfer
c8ab490017 docs: provide more details on object layout
While writing my own out-of-band decoder, I had a hard time figuring out
how to unpack the manifest. From the description, I was only able to
read that the manifest is msgpack'd, but I had not been able to figure
out that it's also going through the same encryption+compression logic
as all other things do.

This should make it a little clearer and provide the necessary
information to understand how the compression works.
2022-07-30 19:24:26 +02:00
Thomas Waldmann
5e0c4a8fd4 document hlid, fixes #2388 2022-07-05 22:27:08 +02:00
Thomas Waldmann
51cf85e627 build_usage / build_man / doc updates 2022-06-25 21:58:19 +02:00
Thomas Waldmann
421d4bdfb0 docs: fix bytes -> str in data-structures docs 2022-06-09 17:57:28 +02:00
Thomas Waldmann
6bfdb3f630 refactor hardlink_master processing globally
borg now has the chunks list in every item with content.
due to the symmetric way how borg now deals with hardlinks using
item.hlid, processing gets much simpler.

but some places where borg deals with other "sources" of hardlinks
still need to do some hardlink management:
borg uses the HardLinkManager there now (which is not much more
than a dict, but keeps documentation at one place and avoids some
code duplication we had before).

item.hlid is computed via hardlink_id function.

support hardlinked symlinks, fixes #2379
as we use item.hlid now to group hardlinks together,
there is no conflict with the item.source usage for
symlink targets any more.

2nd+ hardlinks now add to the files count as did the 1st one.
for borg, now all hardlinks are created equal.
so any hardlink item with chunks now adds to the "file" count.

ItemFormatter: support {hlid} instead of {source} for hardlinks
2022-05-18 14:20:01 +02:00
Thomas Waldmann
85d4b98a16 docs: updated for repository version 2, PUT2 tag 2022-04-09 18:58:47 +02:00
Thomas Waldmann
f4a6ad080b docs: add new AEAD modes to security docs 2022-03-26 17:05:57 +01:00
Julian Picht
091c48bc37
docs: Clarify on-disk order and size of log entry fields (#6357)
docs: clarify on-disk order and size of log entry fields

The order of the fields of a log entry on disk is CRC32 first, the docs had the size first.

I tried to make this list similar to the HashIndex struct description.
2022-02-25 12:53:58 +01:00
Thomas Waldmann
94e93ba7e6 formula is only approximately correct
the movement of the start of the hashing window stops at (file_size - window_size), thus THAT would be the factor in that formula, not just file_size.

for medium and big files, window_size is much smaller than file_size, so guess we can just say "approximately" for the general case.
2022-01-16 20:39:29 +01:00
enkore
79cb4e43e5
docs/data-structures: tie CDC back into dedup rationale 2021-11-27 18:45:19 +00:00
enkore
5b297849d3
docs/data-structures: add content-defined chunking explainer 2021-11-27 14:41:24 +00:00
Andrea Gelmini
72e7c46fa7 Fix typos 2021-01-07 17:54:33 +01:00
Thomas Waldmann
b8bb0494f6 create --sparse, file map support for the "fixed" chunker, see #14
a file map can be:

- created internally inside chunkify by calling sparsemap, which uses
  SEEK_DATA / SEEK_HOLE to determine data and hole ranges inside a
  seekable sparse file.
  Usage: borg create --sparse --chunker-params=fixed,BLOCKSIZE ...
  BLOCKSIZE is the chunker blocksize here, not the filesystem blocksize!

- made by some other means and given to the chunkify function.
  this is not used yet, but in future this could be used to only read
  the changed parts and seek over the (known) unchanged parts of a file.

sparsemap: the generate range sizes are multiples of the fs block size.
           the tests assume 4kiB fs block size.
2020-12-27 22:06:08 +01:00
Guinness
61c92110e6 Change documentation inaccuracy on chunk size.
We know use only "target chunk size" when speaking of the chunk size
that is expected to happen most of the time. This removes statistical
and mathematical inacurracies that could be troublesome for mathematical
people.

Fixes #5336
2020-10-23 13:03:12 +02:00
Thomas Portmann
dfc5e915cc
Fixed locking, issue #4923 (#4928)
locking: fix ExclusiveLock race condition bug, fixes #4923

- ExclusiveLock is now based on os.rename instead of os.mkdir.
- catch FileNotFoundError observed under race condition in ExclusiveLock.release()
  and .kill_stale_lock()
- added TestExclusiveLock.test_race_condition() which reveals issue #4923
- updated docs
- locking: use "raise LockTimeout from None" for prettier traceback

Co-authored-by: Thomas Portmann <thomas@portmann.org>
Co-authored-by: Thomas Waldmann <tw@waldmann-edv.de>
2020-07-03 10:09:32 +02:00
Thalian
08a7661e67 [FEATURE] #4489 – Deprecate --nobsdflags option
Replaced by --noflags. In internal data structure the key 'bsdflags' is kept for backwards compatibility.
2020-03-25 06:35:15 +01:00
Thomas Waldmann
7f46eb99aa update docs about fixed chunker and chunker algo spec needed 2019-02-13 06:30:13 +01:00
Thomas Waldmann
e6fcf4ea42 update docs about separated compaction 2018-07-14 14:53:23 +02:00
TW
4b98393542
Merge pull request #3520 from pngwjpgh/doc/chunk-seed
Chunk seed is generated per /repository/
2018-01-10 07:26:26 +01:00
Gregor Kleen
1820e22c02 Chunk seed is generated per /repository/ 2018-01-09 18:17:46 +01:00
Gianfranco Costamagna
0980d6ac43 fixup allows one to, with suggestions from Dan Christensen 2018-01-03 15:54:52 +01:00
Gianfranco Costamagna
111a19f7fa fix typo: allows to -> allows one to 2018-01-03 11:42:38 +01:00
Thomas Waldmann
2588e50f0b readme / docs: mention zstd 2017-12-18 22:55:00 +01:00
Tom Denley
c6591a7c06 Correct usage of "fewer" in place of "less" 2017-11-11 11:21:45 +00:00