fixed the race breaking moving files from archive in direct mode

assistant: Fix bug in direct mode that could occur when a symlink is moved
out of an archive directory, and resulted in the file not being set to
direct mode when it was transferred.

The bug was that the direct mode mapping was not up-to-date when the
transferrer finished. So, finding no direct mode place to store the object,
it was put into .git/annex in indirect mode.

To fix this, just make the watcher update the direct mode mapping to
include the new file before it starts the transfer. (Seems we don't need to
update it to remove the old file if the link was moved, because the direct
mode code will notice it's not present and the mapping gets updated for its
removal later.)

The reason this was a race, and was probably not seen often is because
the committer came along and updated the direct mode mapping as part of
adding the moved symlink. But when the file was sufficiently small or
the remote sufficiently fast, this could happen after the transfer
finished.
This commit is contained in:
Joey Hess 2013-03-04 14:25:18 -04:00
parent 051622c6da
commit 1d388d5579
3 changed files with 11 additions and 4 deletions

View file

@ -19,6 +19,7 @@ import qualified Git.Config
import Utility.ThreadScheduler import Utility.ThreadScheduler
import qualified Assistant.Threads.Watcher as Watcher import qualified Assistant.Threads.Watcher as Watcher
import Utility.LogFile import Utility.LogFile
import Config
import Data.Time.Clock.POSIX import Data.Time.Clock.POSIX
@ -105,7 +106,8 @@ dailyCheck = do
liftAnnex $ warning msg liftAnnex $ warning msg
void $ addAlert $ sanityCheckFixAlert msg void $ addAlert $ sanityCheckFixAlert msg
addsymlink file s = do addsymlink file s = do
Watcher.runHandler Watcher.onAddSymlink file s isdirect <- liftAnnex isDirect
Watcher.runHandler (Watcher.onAddSymlink isdirect) file s
insanity $ "found unstaged symlink: " ++ file insanity $ "found unstaged symlink: " ++ file
hourlyCheck :: Assistant () hourlyCheck :: Assistant ()

View file

@ -82,7 +82,7 @@ runWatcher = do
direct <- liftAnnex isDirect direct <- liftAnnex isDirect
addhook <- hook $ if direct then onAddDirect else onAdd addhook <- hook $ if direct then onAddDirect else onAdd
delhook <- hook onDel delhook <- hook onDel
addsymlinkhook <- hook onAddSymlink addsymlinkhook <- hook $ onAddSymlink direct
deldirhook <- hook onDelDir deldirhook <- hook onDelDir
errhook <- hook onErr errhook <- hook onErr
let hooks = mkWatchHooks let hooks = mkWatchHooks
@ -193,10 +193,12 @@ onAddDirect file fs = do
- Or, if it is a git-annex symlink, ensure it points to the content - Or, if it is a git-annex symlink, ensure it points to the content
- before adding it. - before adding it.
-} -}
onAddSymlink :: Handler onAddSymlink :: Bool -> Handler
onAddSymlink file filestatus = go =<< liftAnnex (Backend.lookupFile file) onAddSymlink isdirect file filestatus = go =<< liftAnnex (Backend.lookupFile file)
where where
go (Just (key, _)) = do go (Just (key, _)) = do
when isdirect $
liftAnnex $ void $ addAssociatedFile key file
link <- liftAnnex $ calcGitLink file key link <- liftAnnex $ calcGitLink file key
ifM ((==) (Just link) <$> liftIO (catchMaybeIO $ readSymbolicLink file)) ifM ((==) (Just link) <$> liftIO (catchMaybeIO $ readSymbolicLink file))
( do ( do

3
debian/changelog vendored
View file

@ -15,6 +15,9 @@ git-annex (4.20130228) UNRELEASED; urgency=low
very non-aggressively. very non-aggressively.
* webapp: New preferences page allows enabling/disabling debug logging * webapp: New preferences page allows enabling/disabling debug logging
at runtime, as well as configuring numcopies and diskreserve. at runtime, as well as configuring numcopies and diskreserve.
* assistant: Fix bug in direct mode that could occur when a symlink is
moved out of an archive directory, and resulted in the file not being
set to direct mode when it was transferred.
-- Joey Hess <joeyh@debian.org> Wed, 27 Feb 2013 23:20:40 -0400 -- Joey Hess <joeyh@debian.org> Wed, 27 Feb 2013 23:20:40 -0400