#850 closed defect (fixed)
tahoe backup loops on recursive links
Reported by: | francois | Owned by: | |
---|---|---|---|
Priority: | major | Milestone: | 1.6.0 |
Component: | code-frontend-cli | Version: | 1.5.0 |
Keywords: | tahoe-backup recursive symlink reliability hang news-done | Cc: | |
Launchpad Bug: |
Description
francois@korn:~$ mkdir /tmp/test-backup/ francois@korn:~$ ln -s . /tmp/test-backup/test francois@korn:~$ tahoe backup -v /tmp/test-backup tahoe:tmp /usr/lib/pymodules/python2.6/foolscap/banana.py:2: DeprecationWarning: the sets module is deprecated import struct, sets, time processing /tmp/test-backup, olddircap None processing /tmp/test-backup/test, olddircap None processing /tmp/test-backup/test/test, olddircap None processing /tmp/test-backup/test/test/test, olddircap None processing /tmp/test-backup/test/test/test/test, olddircap None processing /tmp/test-backup/test/test/test/test/test, olddircap None processing /tmp/test-backup/test/test/test/test/test/test, olddircap None processing /tmp/test-backup/test/test/test/test/test/test/test, olddircap None processing /tmp/test-backup/test/test/test/test/test/test/test/test, olddircap None processing /tmp/test-backup/test/test/test/test/test/test/test/test/test, olddircap None processing /tmp/test-backup/test/test/test/test/test/test/test/test/test/test, olddircap None processing /tmp/test-backup/test/test/test/test/test/test/test/test/test/test/test, olddircap None processing /tmp/test-backup/test/test/test/test/test/test/test/test/test/test/test/test, olddircap None processing /tmp/test-backup/test/test/test/test/test/test/test/test/test/test/test/test/test, olddircap None processing /tmp/test-backup/test/test/test/test/test/test/test/test/test/test/test/test/test/test, olddircap None processing /tmp/test-backup/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test, olddircap None processing /tmp/test-backup/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test, olddircap None processing /tmp/test-backup/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test, olddircap None processing /tmp/test-backup/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test, olddircap None processing /tmp/test-backup/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test, olddircap None processing /tmp/test-backup/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test, olddircap None processing /tmp/test-backup/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test, olddircap None processing /tmp/test-backup/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test, olddircap None processing /tmp/test-backup/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test, olddircap None processing /tmp/test-backup/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test, olddircap None processing /tmp/test-backup/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test, olddircap None processing /tmp/test-backup/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test, olddircap None processing /tmp/test-backup/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test, olddircap None processing /tmp/test-backup/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test, olddircap None processing /tmp/test-backup/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test, olddircap None processing /tmp/test-backup/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test, olddircap None processing /tmp/test-backup/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test, olddircap None processing /tmp/test-backup/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test, olddircap None processing /tmp/test-backup/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test, olddircap None processing /tmp/test-backup/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test, olddircap None processing /tmp/test-backup/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test, olddircap None processing /tmp/test-backup/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test, olddircap None processing /tmp/test-backup/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test, olddircap None processing /tmp/test-backup/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test, olddircap None processing /tmp/test-backup/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test, olddircap None processing /tmp/test-backup/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test, olddircap None Traceback (most recent call last): File "/usr/bin/tahoe", line 8, in <module> load_entry_point('allmydata-tahoe==1.5.0', 'console_scripts', 'tahoe')() File "/usr/lib/pymodules/python2.6/allmydata/scripts/runner.py", line 91, in run rc = runner(sys.argv[1:]) File "/usr/lib/pymodules/python2.6/allmydata/scripts/runner.py", line 78, in runner rc = cli.dispatch[command](so) File "/usr/lib/pymodules/python2.6/allmydata/scripts/cli.py", line 456, in backup rc = tahoe_backup.backup(options) File "/usr/lib/pymodules/python2.6/allmydata/scripts/tahoe_backup.py", line 370, in backup return bu.run() File "/usr/lib/pymodules/python2.6/allmydata/scripts/tahoe_backup.py", line 212, in run new_backup_dircap = self.process(options.from_dir, latest_backup_dircap) File "/usr/lib/pymodules/python2.6/allmydata/scripts/tahoe_backup.py", line 262, in process newchilddircap = self.process(childpath, oldchildcap) File "/usr/lib/pymodules/python2.6/allmydata/scripts/tahoe_backup.py", line 262, in process newchilddircap = self.process(childpath, oldchildcap) File "/usr/lib/pymodules/python2.6/allmydata/scripts/tahoe_backup.py", line 262, in process newchilddircap = self.process(childpath, oldchildcap) File "/usr/lib/pymodules/python2.6/allmydata/scripts/tahoe_backup.py", line 262, in process newchilddircap = self.process(childpath, oldchildcap) File "/usr/lib/pymodules/python2.6/allmydata/scripts/tahoe_backup.py", line 262, in process newchilddircap = self.process(childpath, oldchildcap) File "/usr/lib/pymodules/python2.6/allmydata/scripts/tahoe_backup.py", line 262, in process newchilddircap = self.process(childpath, oldchildcap) File "/usr/lib/pymodules/python2.6/allmydata/scripts/tahoe_backup.py", line 262, in process newchilddircap = self.process(childpath, oldchildcap) File "/usr/lib/pymodules/python2.6/allmydata/scripts/tahoe_backup.py", line 262, in process newchilddircap = self.process(childpath, oldchildcap) File "/usr/lib/pymodules/python2.6/allmydata/scripts/tahoe_backup.py", line 262, in process newchilddircap = self.process(childpath, oldchildcap) File "/usr/lib/pymodules/python2.6/allmydata/scripts/tahoe_backup.py", line 262, in process newchilddircap = self.process(childpath, oldchildcap) File "/usr/lib/pymodules/python2.6/allmydata/scripts/tahoe_backup.py", line 262, in process newchilddircap = self.process(childpath, oldchildcap) File "/usr/lib/pymodules/python2.6/allmydata/scripts/tahoe_backup.py", line 262, in process newchilddircap = self.process(childpath, oldchildcap) File "/usr/lib/pymodules/python2.6/allmydata/scripts/tahoe_backup.py", line 262, in process newchilddircap = self.process(childpath, oldchildcap) File "/usr/lib/pymodules/python2.6/allmydata/scripts/tahoe_backup.py", line 262, in process newchilddircap = self.process(childpath, oldchildcap) File "/usr/lib/pymodules/python2.6/allmydata/scripts/tahoe_backup.py", line 262, in process newchilddircap = self.process(childpath, oldchildcap) File "/usr/lib/pymodules/python2.6/allmydata/scripts/tahoe_backup.py", line 262, in process newchilddircap = self.process(childpath, oldchildcap) File "/usr/lib/pymodules/python2.6/allmydata/scripts/tahoe_backup.py", line 262, in process newchilddircap = self.process(childpath, oldchildcap) File "/usr/lib/pymodules/python2.6/allmydata/scripts/tahoe_backup.py", line 262, in process newchilddircap = self.process(childpath, oldchildcap) File "/usr/lib/pymodules/python2.6/allmydata/scripts/tahoe_backup.py", line 262, in process newchilddircap = self.process(childpath, oldchildcap) File "/usr/lib/pymodules/python2.6/allmydata/scripts/tahoe_backup.py", line 262, in process newchilddircap = self.process(childpath, oldchildcap) File "/usr/lib/pymodules/python2.6/allmydata/scripts/tahoe_backup.py", line 262, in process newchilddircap = self.process(childpath, oldchildcap) File "/usr/lib/pymodules/python2.6/allmydata/scripts/tahoe_backup.py", line 262, in process newchilddircap = self.process(childpath, oldchildcap) File "/usr/lib/pymodules/python2.6/allmydata/scripts/tahoe_backup.py", line 262, in process newchilddircap = self.process(childpath, oldchildcap) File "/usr/lib/pymodules/python2.6/allmydata/scripts/tahoe_backup.py", line 262, in process newchilddircap = self.process(childpath, oldchildcap) File "/usr/lib/pymodules/python2.6/allmydata/scripts/tahoe_backup.py", line 262, in process newchilddircap = self.process(childpath, oldchildcap) File "/usr/lib/pymodules/python2.6/allmydata/scripts/tahoe_backup.py", line 262, in process newchilddircap = self.process(childpath, oldchildcap) File "/usr/lib/pymodules/python2.6/allmydata/scripts/tahoe_backup.py", line 262, in process newchilddircap = self.process(childpath, oldchildcap) File "/usr/lib/pymodules/python2.6/allmydata/scripts/tahoe_backup.py", line 262, in process newchilddircap = self.process(childpath, oldchildcap) File "/usr/lib/pymodules/python2.6/allmydata/scripts/tahoe_backup.py", line 262, in process newchilddircap = self.process(childpath, oldchildcap) File "/usr/lib/pymodules/python2.6/allmydata/scripts/tahoe_backup.py", line 262, in process newchilddircap = self.process(childpath, oldchildcap) File "/usr/lib/pymodules/python2.6/allmydata/scripts/tahoe_backup.py", line 262, in process newchilddircap = self.process(childpath, oldchildcap) File "/usr/lib/pymodules/python2.6/allmydata/scripts/tahoe_backup.py", line 262, in process newchilddircap = self.process(childpath, oldchildcap) File "/usr/lib/pymodules/python2.6/allmydata/scripts/tahoe_backup.py", line 262, in process newchilddircap = self.process(childpath, oldchildcap) File "/usr/lib/pymodules/python2.6/allmydata/scripts/tahoe_backup.py", line 262, in process newchilddircap = self.process(childpath, oldchildcap) File "/usr/lib/pymodules/python2.6/allmydata/scripts/tahoe_backup.py", line 262, in process newchilddircap = self.process(childpath, oldchildcap) File "/usr/lib/pymodules/python2.6/allmydata/scripts/tahoe_backup.py", line 262, in process newchilddircap = self.process(childpath, oldchildcap) File "/usr/lib/pymodules/python2.6/allmydata/scripts/tahoe_backup.py", line 262, in process newchilddircap = self.process(childpath, oldchildcap) File "/usr/lib/pymodules/python2.6/allmydata/scripts/tahoe_backup.py", line 262, in process newchilddircap = self.process(childpath, oldchildcap) File "/usr/lib/pymodules/python2.6/allmydata/scripts/tahoe_backup.py", line 262, in process newchilddircap = self.process(childpath, oldchildcap) File "/usr/lib/pymodules/python2.6/allmydata/scripts/tahoe_backup.py", line 262, in process newchilddircap = self.process(childpath, oldchildcap) File "/usr/lib/pymodules/python2.6/allmydata/scripts/tahoe_backup.py", line 268, in process raise BackupProcessingError("Cannot backup this file %r" % childpath) allmydata.scripts.tahoe_backup.BackupProcessingError: Cannot backup this file '/tmp/test-backup/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test' francois@korn:~$
Attachments (1)
Change History (12)
Changed at 2009-12-06T14:57:48Z by francois
comment:1 Changed at 2009-12-06T14:58:03Z by francois
- Keywords review added
comment:2 Changed at 2009-12-14T02:14:51Z by zooko
comment:3 follow-up: ↓ 7 Changed at 2009-12-20T20:59:13Z by warner
As #641 points out, if we could either skip symlinks or record them as symlinks (instead of following them), this would go away.
Francois: it looks like your patch only catches cycles of length one, right? I.e. if someone did ln -s .. foo or ln -s ../.. foo, then "tahoe backup" would still get stuck in a loop, yeah?
The more general solution (without fixing #641) would involve keeping a full list of every directory we'd ever started to process, and comparing the target of each symlinky child against that list, and bailing if it was found. That sounds like a lot of memory.
comment:4 Changed at 2009-12-20T21:03:15Z by davidsarah
Replying to zooko:
#104 (does cp -r work as expected?) was about this issue as well as a couple of others.
I don't think it's the same issue. This is only about recursive symlinks in the local filesystem. cp -r needs to handle loops both in the Tahoe and local filesystems. As Brian says, the only way to do that correctly in general is to keep track of the mutable directory storage indices (for the Tahoe fs) or the inode numbers (for the local fs) that you've already seen.
comment:5 Changed at 2009-12-20T21:04:31Z by davidsarah
- Keywords reliability added
comment:6 Changed at 2009-12-21T02:53:52Z by davidsarah
- Keywords review-needed added; review removed
comment:7 in reply to: ↑ 3 Changed at 2009-12-27T21:31:37Z by francois
- Keywords review-needed removed
Replying to warner:
Francois: it looks like your patch only catches cycles of length one, right? I.e. if someone did ln -s .. foo or ln -s ../.. foo, then "tahoe backup" would still get stuck in a loop, yeah?
Yes, Brian, you're right, this fix is wrong. Can someone with the necessary trac permissions delete this patch from the ticket ?
comment:8 Changed at 2009-12-27T21:59:46Z by warner
eh, I think it's fine to leave it there: no harm in having well-labeled experiments lying around :)
I don't know how to fix this in general. I suspect it will require having explicit support for symlinks in tahoe (#641), at least the ability to copy the symlink target name into a tahoe file-like object and then copy it back out again. A short-term fix (again #641, also #729) would be to let you skip over symlinks.. that's what I've been doing for my personal backups.
comment:9 Changed at 2009-12-29T19:17:16Z by davidsarah
- Keywords hang added
comment:10 Changed at 2010-01-27T22:54:30Z by warner
- Milestone changed from undecided to 1.6.0
- Resolution set to fixed
- Status changed from new to closed
e769bbb6dd41d40c fixes this, by skipping over all symlinks (with a warning).
comment:11 Changed at 2010-02-02T06:04:10Z by davidsarah
- Keywords news-done added
#104 (does cp -r work as expected?) was about this issue as well as a couple of others. Moving the loop issue from #104 to here.