create: archive recursion roots that are hard links of an earlier root, fixes #10388 - #10389
Open
ThomasWaldmann wants to merge 1 commit into
Open
ThomasWaldmann wants to merge 1 commit into
ThomasWaldmann wants to merge 1 commit into
Conversation
fixes borgbackup#10388 The duplicate root protection (borgbackup#5603) identified a finished root by (st_ino, st_dev) only. Hard links are different paths with the same inode, so they were taken for duplicates of the first root and silently not archived: - borg create arch input/file1 input/file2 (file2 being a hard link of file1) - borg create arch input/file1 input (hard links of file1 inside input) - borg create arch input/link input/target (followed symlink to a file) skip_key() now identifies directories by inode (as before) and all other fs objects by inode and path, so only the very same path is skipped. Co-Authored-By: Claude Fable 5.1 <[email protected]>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #10389 +/- ##
==========================================
- Coverage 88.19% 88.15% -0.04%
==========================================
Files 103 103
Lines 18822 18826 +4
Branches 2919 2920 +1
==========================================
- Hits 16600 16597 -3
- Misses 1548 1552 +4
- Partials 674 677 +3 ☔ View full report in Codecov by Harness. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #10388.
Problem
borg createsilently did not archive recursion roots that are hard links of an earlier root (rc 0, no warning):borg create arch input/file1 input/file2 input/file3(hard links of each other): onlyinput/file1was archived.borg create arch input/file1 input:input/file2andinput/file3were dropped while recursing intoinput.borg create arch input/link input/target(linkbeing a followed symlink to the filetarget, borg create should follow symlinks pointed to by roots #4737):input/targetwas dropped.Cause
The duplicate root protection of #5603 put the
(st_ino, st_dev)of each finished root intoskip_inodes, and_rec_walk()skips everything with a matching inode. That is right for directories, but hard links are different paths with the same inode.Fix
skip_key(path, st)builds the key used forskip_inodes:(st_ino, st_dev), as before. Same directory given twice, a symlink to a directory plus that directory, child directory first and parent after: all still archived once (Specifying the same path twice breaks hardlink during extraction #5603 protection unchanged,test_create_duplicate_rootandtest_extract_hardlinks_twicepass unchanged).(st_ino, st_dev, path). Only the very same (normalized) path is skipped, soinput/file1 input/file1 ./input/../input/file1is still archived once, andinput/file1 inputarchivesinput/file1once.The
borg createhelp text about roots given twice is adapted (usage docs / man page not regenerated).Tests
New in
create_cmd_test.py, all four fail without the fix:test_create_hardlinked_roots: three hard-linked roots, all in the archive with onehlid, extracting to one inode withst_nlink == 3.test_create_hardlinked_root_and_parent_dir:input/file1 input, every path exactly once.test_create_duplicate_file_root: same file given three times (two spellings) plus a hard link of it.test_create_symlink_root_and_target_file: symlink to a file and the file, both archived.Not changed by this PR
A directory root followed by a root inside it (
borg create arch input input/file1) archivesinput/file1twice. That is the same before and after this change: fs objects found while recursing never were inskip_inodes.🤖 Generated with Claude Code