Commit a1bfbc8
authored
restore: preserve hardlinks on restore (#492)
This is the simplest (and probably least efficient) way to address
#16
This issue **has been open since 2022**, and it seems potentially like a
way to have very confusing BUGS if you backup this folder:
```sh
wstein@lite:/tmp$ mkdir link
wstein@lite:/tmp$ cd link/
wstein@lite:/tmp/link$ ls
wstein@lite:/tmp/link$ echo "foo" > A.txt
wstein@lite:/tmp/link$ ln A.txt B.txt
wstein@lite:/tmp/link$ echo "bar" >> B.txt
wstein@lite:/tmp/link$ more A.txt
foo
bar
wstein@lite:/tmp/link$ more B.txt
foo
bar
```
then restore it, and suddenly it behave very differently after the
restore.
I'm building software where rustic backup/restore has to actually work
well -- it's not just for emergency recovery, but part of the normal
lifecycle of user data. I ran some big tests of backup/restore, and only
after fixing this hard link issue was the filesystem restored properly.
Fortunately, restore already records inode, device id, and link count
metadata for files. But the restore path recreated every file as an
independent plain file, so **hardlinks were silently de-linked on
restore**.
This PR adds a post-restore hardlink pass keyed by the stored
`(device_id, inode)` identity. After file contents and metadata are
restored, sibling paths in each hardlink group are replaced with
hardlinks to a canonical restored path.
Also add a test using the existing backup fixture that contains a
hardlink pair.
Obviously, it could make good sense to close this if:
- you don't like that it isn't the globally optimal way to solve this
problem (since it restores each linked file, then combines them, rather
than restoring only one). It was just the minimal way to do this that at
the end preserves the links.
- I didn't worry at all about non-POSIX
If you close this, it would probably be good though to mention clearly
on the main rustic README page that hardlinks silently break on backup
--> restore, as it can lead to major bugs for users, and it's only
something they might find via careful testing / debugging of errors
popping up later (that was the case for me). "hard link" isn't mentioned
anywhere on main rustic README or issue tracker (it's in this
rustic_core issue).
For anybody who does need this, I put a release here for linux:
https://github.com/sagemathinc/rustic/releases
Thanks!1 parent 910b42e commit a1bfbc8
3 files changed
Lines changed: 159 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
102 | 102 | | |
103 | 103 | | |
104 | 104 | | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
105 | 111 | | |
106 | 112 | | |
107 | 113 | | |
| |||
791 | 797 | | |
792 | 798 | | |
793 | 799 | | |
| 800 | + | |
| 801 | + | |
| 802 | + | |
| 803 | + | |
| 804 | + | |
| 805 | + | |
| 806 | + | |
| 807 | + | |
| 808 | + | |
| 809 | + | |
| 810 | + | |
| 811 | + | |
| 812 | + | |
| 813 | + | |
| 814 | + | |
| 815 | + | |
| 816 | + | |
| 817 | + | |
| 818 | + | |
| 819 | + | |
| 820 | + | |
| 821 | + | |
| 822 | + | |
| 823 | + | |
| 824 | + | |
| 825 | + | |
| 826 | + | |
| 827 | + | |
| 828 | + | |
| 829 | + | |
| 830 | + | |
| 831 | + | |
| 832 | + | |
794 | 833 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
90 | 90 | | |
91 | 91 | | |
92 | 92 | | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
93 | 99 | | |
94 | 100 | | |
95 | 101 | | |
| |||
350 | 356 | | |
351 | 357 | | |
352 | 358 | | |
| 359 | + | |
353 | 360 | | |
| 361 | + | |
| 362 | + | |
| 363 | + | |
354 | 364 | | |
355 | 365 | | |
356 | 366 | | |
| |||
373 | 383 | | |
374 | 384 | | |
375 | 385 | | |
| 386 | + | |
| 387 | + | |
| 388 | + | |
| 389 | + | |
| 390 | + | |
| 391 | + | |
| 392 | + | |
| 393 | + | |
| 394 | + | |
| 395 | + | |
| 396 | + | |
| 397 | + | |
| 398 | + | |
| 399 | + | |
| 400 | + | |
| 401 | + | |
| 402 | + | |
| 403 | + | |
| 404 | + | |
| 405 | + | |
| 406 | + | |
| 407 | + | |
| 408 | + | |
| 409 | + | |
| 410 | + | |
| 411 | + | |
| 412 | + | |
| 413 | + | |
| 414 | + | |
| 415 | + | |
| 416 | + | |
| 417 | + | |
| 418 | + | |
| 419 | + | |
| 420 | + | |
| 421 | + | |
| 422 | + | |
| 423 | + | |
| 424 | + | |
| 425 | + | |
| 426 | + | |
| 427 | + | |
| 428 | + | |
| 429 | + | |
| 430 | + | |
| 431 | + | |
| 432 | + | |
| 433 | + | |
| 434 | + | |
| 435 | + | |
| 436 | + | |
376 | 437 | | |
377 | 438 | | |
378 | 439 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
1 | 2 | | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
0 commit comments