fix potential race in updating inode cache
In Annex.Content, the object file was statted after pointer files were populated. But if annex.thin is set, once the pointer files are populated, the object file can potentially be modified via the hard link. So, it was possible, though seemingly very unlikely, for the inode of the modified object file to be cached. Command.Fix and Command.Fsck had similar problems, statting the work tree files after they were in place. Changed them to stat the temp file that gets moved into place. This does rely on .git/annex being on the same filesystem. If it's not, the cached inode will not be the same as the one that the temp file gets moved to. Result will be that git-annex will later need to do an expensive verification of the content of the worktree files. Note that the cross-filesystem move of the temp file already is a larger amount of extra work, so this seems acceptable. Sponsored-by: Luke Shumaker on Patreon
This commit is contained in:
parent
3b5a3e168d
commit
e4b2a067e0
4 changed files with 8 additions and 9 deletions
|
@ -346,8 +346,11 @@ moveAnnex key af src = ifM (checkSecureHashes' key)
|
|||
fs <- map (`fromTopFilePath` g)
|
||||
<$> Database.Keys.getAssociatedFiles key
|
||||
unless (null fs) $ do
|
||||
destic <- withTSDelta $
|
||||
liftIO . genInodeCache dest
|
||||
ics <- mapM (populatePointerFile (Restage True) key dest) fs
|
||||
Database.Keys.storeInodeCaches' key [dest] (catMaybes ics)
|
||||
Database.Keys.addInodeCaches key
|
||||
(catMaybes (destic:ics))
|
||||
)
|
||||
alreadyhave = liftIO $ R.removeLink src
|
||||
|
||||
|
|
|
@ -77,8 +77,8 @@ breakHardLink file key obj = do
|
|||
unlessM (checkedCopyFile key obj tmp' mode) $
|
||||
error "unable to break hard link"
|
||||
thawContent tmp'
|
||||
Database.Keys.storeInodeCaches key [tmp']
|
||||
modifyContent obj $ freezeContent obj
|
||||
Database.Keys.storeInodeCaches key [file]
|
||||
next $ return True
|
||||
|
||||
makeHardLink :: RawFilePath -> Key -> CommandPerform
|
||||
|
|
|
@ -363,7 +363,7 @@ verifyWorkTree key file = do
|
|||
void $ checkedCopyFile key obj tmp' mode
|
||||
thawContent tmp'
|
||||
)
|
||||
Database.Keys.storeInodeCaches key [file]
|
||||
Database.Keys.storeInodeCaches key [tmp']
|
||||
_ -> return ()
|
||||
return True
|
||||
|
||||
|
|
|
@ -18,7 +18,6 @@ module Database.Keys (
|
|||
getAssociatedKey,
|
||||
removeAssociatedFile,
|
||||
storeInodeCaches,
|
||||
storeInodeCaches',
|
||||
addInodeCaches,
|
||||
getInodeCaches,
|
||||
removeInodeCaches,
|
||||
|
@ -175,11 +174,8 @@ removeAssociatedFile k = runWriterIO . SQL.removeAssociatedFile k
|
|||
|
||||
{- Stats the files, and stores their InodeCaches. -}
|
||||
storeInodeCaches :: Key -> [RawFilePath] -> Annex ()
|
||||
storeInodeCaches k fs = storeInodeCaches' k fs []
|
||||
|
||||
storeInodeCaches' :: Key -> [RawFilePath] -> [InodeCache] -> Annex ()
|
||||
storeInodeCaches' k fs ics = withTSDelta $ \d ->
|
||||
addInodeCaches k . (++ ics) . catMaybes
|
||||
storeInodeCaches k fs = withTSDelta $ \d ->
|
||||
addInodeCaches k . catMaybes
|
||||
=<< liftIO (mapM (\f -> genInodeCache f d) fs)
|
||||
|
||||
addInodeCaches :: Key -> [InodeCache] -> Annex ()
|
||||
|
|
Loading…
Add table
Reference in a new issue