re-add lock journal before reading journal files

This reverts commit 2e6e9876e3.

This is gonna be needed after all.. The append will only be atomic if
the journal is locked, because the file being appended will have to be
moved out of the way to avoid an old version of git-annex seeing an
incomplete write to it. When git-annex finds that the file is not in the
journal, and checks the append location, locking will be needed to avoid
a race causing it to miss it in the append location too due to it being
moved back to the journal.
This commit is contained in:
Joey Hess 2022-07-18 16:40:25 -04:00
parent 36f0bdcd57
commit 28b0aaea54
No known key found for this signature in database
GPG key ID: DB12DB0FF05F8F38

View file

@ -236,7 +236,7 @@ updateTo' pairs = do
else return $ "merging " ++ else return $ "merging " ++
unwords (map Git.Ref.describe branches) ++ unwords (map Git.Ref.describe branches) ++
" into " ++ fromRef name " into " ++ fromRef name
localtransitions <- getLocalTransitions localtransitions <- getLocalTransitions jl
unless (null tomerge) $ do unless (null tomerge) $ do
showSideAction merge_desc showSideAction merge_desc
mapM_ checkBranchDifferences refs mapM_ checkBranchDifferences refs
@ -265,7 +265,7 @@ updateTo' pairs = do
-- Gather any transitions that are new to either the -- Gather any transitions that are new to either the
-- local branch or a remote ref, which will need to be -- local branch or a remote ref, which will need to be
-- applied on the fly. -- applied on the fly.
localts <- getLocalTransitions localts <- lockJournal getLocalTransitions
remotets <- mapM getRefTransitions refs remotets <- mapM getRefTransitions refs
ts <- if all (localts ==) remotets ts <- if all (localts ==) remotets
then return [] then return []
@ -307,13 +307,14 @@ get file = do
content <- if journalIgnorable st content <- if journalIgnorable st
then getRef fullname file then getRef fullname file
else if null (unmergedRefs st) else if null (unmergedRefs st)
then getLocal file then lockJournal $
\jl -> getLocal jl file
else unmergedbranchfallback st else unmergedbranchfallback st
setCache file content setCache file content
return content return content
where where
unmergedbranchfallback st = do unmergedbranchfallback st = do
l <- getLocal file l <- lockJournal $ \jl -> getLocal jl file
bs <- forM (unmergedRefs st) $ \ref -> getRef ref file bs <- forM (unmergedRefs st) $ \ref -> getRef ref file
let content = l <> mconcat bs let content = l <> mconcat bs
return $ applytransitions (unhandledTransitions st) content return $ applytransitions (unhandledTransitions st) content
@ -343,7 +344,7 @@ precache file branchcontent = do
st <- getState st <- getState
content <- if journalIgnorable st content <- if journalIgnorable st
then pure branchcontent then pure branchcontent
else getJournalFileStale (GetPrivate True) file >>= return . \case else lockJournal $ \jl -> getJournalFile jl (GetPrivate True) file >>= return . \case
NoJournalledContent -> branchcontent NoJournalledContent -> branchcontent
JournalledContent journalcontent -> journalcontent JournalledContent journalcontent -> journalcontent
PossiblyStaleJournalledContent journalcontent -> PossiblyStaleJournalledContent journalcontent ->
@ -354,13 +355,13 @@ precache file branchcontent = do
- reflect changes in remotes. - reflect changes in remotes.
- (Changing the value this returns, and then merging is always the - (Changing the value this returns, and then merging is always the
- same as using get, and then changing its value.) -} - same as using get, and then changing its value.) -}
getLocal :: RawFilePath -> Annex L.ByteString getLocal :: JournalLocked -> RawFilePath -> Annex L.ByteString
getLocal = getLocal' (GetPrivate True) getLocal jl = getLocal' jl (GetPrivate True)
getLocal' :: GetPrivate -> RawFilePath -> Annex L.ByteString getLocal' :: JournalLocked -> GetPrivate -> RawFilePath -> Annex L.ByteString
getLocal' getprivate file = do getLocal' jl getprivate file = do
fastDebug "Annex.Branch" ("read " ++ fromRawFilePath file) fastDebug "Annex.Branch" ("read " ++ fromRawFilePath file)
go =<< getJournalFileStale getprivate file go =<< getJournalFile jl getprivate file
where where
go NoJournalledContent = getRef fullname file go NoJournalledContent = getRef fullname file
go (JournalledContent journalcontent) = return journalcontent go (JournalledContent journalcontent) = return journalcontent
@ -394,12 +395,12 @@ getRef ref file = withIndex $ catFile ref file
- modifes the current content of the file on the branch. - modifes the current content of the file on the branch.
-} -}
change :: Journalable content => RegardingUUID -> RawFilePath -> (L.ByteString -> content) -> Annex () change :: Journalable content => RegardingUUID -> RawFilePath -> (L.ByteString -> content) -> Annex ()
change ru file f = lockJournal $ \jl -> f <$> getToChange ru file >>= set jl ru file change ru file f = lockJournal $ \jl -> f <$> getToChange jl ru file >>= set jl ru file
{- Applies a function which can modify the content of a file, or not. -} {- Applies a function which can modify the content of a file, or not. -}
maybeChange :: Journalable content => RegardingUUID -> RawFilePath -> (L.ByteString -> Maybe content) -> Annex () maybeChange :: Journalable content => RegardingUUID -> RawFilePath -> (L.ByteString -> Maybe content) -> Annex ()
maybeChange ru file f = lockJournal $ \jl -> do maybeChange ru file f = lockJournal $ \jl -> do
v <- getToChange ru file v <- getToChange jl ru file
case f v of case f v of
Just jv -> Just jv ->
let b = journalableByteString jv let b = journalableByteString jv
@ -446,8 +447,8 @@ changeOrAppend ru file f = lockJournal $ \jl ->
oldc <> journalableByteString toappend oldc <> journalableByteString toappend
{- Only get private information when the RegardingUUID is itself private. -} {- Only get private information when the RegardingUUID is itself private. -}
getToChange :: RegardingUUID -> RawFilePath -> Annex L.ByteString getToChange :: JournalLocked -> RegardingUUID -> RawFilePath -> Annex L.ByteString
getToChange ru f = flip getLocal' f . GetPrivate =<< regardingPrivateUUID ru getToChange jl ru f = flip (getLocal' jl) f . GetPrivate =<< regardingPrivateUUID ru
{- Records new content of a file into the journal. {- Records new content of a file into the journal.
- -
@ -727,10 +728,10 @@ stageJournal jl commitindex = withIndex $ withOtherTmp $ \tmpdir -> do
removeWhenExistsWith (R.removeLink) (toRawFilePath jlogf) removeWhenExistsWith (R.removeLink) (toRawFilePath jlogf)
openjlog tmpdir = liftIO $ openTmpFileIn tmpdir "jlog" openjlog tmpdir = liftIO $ openTmpFileIn tmpdir "jlog"
getLocalTransitions :: Annex Transitions getLocalTransitions :: JournalLocked -> Annex Transitions
getLocalTransitions = getLocalTransitions jl =
parseTransitionsStrictly "local" parseTransitionsStrictly "local"
<$> getLocal transitionsLog <$> getLocal jl transitionsLog
{- This is run after the refs have been merged into the index, {- This is run after the refs have been merged into the index,
- but before the result is committed to the branch. - but before the result is committed to the branch.
@ -979,7 +980,7 @@ overBranchFileContents' select go st = do
-- Check the journal, in case it did not get committed to the branch -- Check the journal, in case it did not get committed to the branch
checkjournal f branchcontent checkjournal f branchcontent
| journalIgnorable st = return branchcontent | journalIgnorable st = return branchcontent
| otherwise = getJournalFileStale (GetPrivate True) f >>= return . \case | otherwise = lockJournal $ \jl -> getJournalFile jl (GetPrivate True) f >>= return . \case
NoJournalledContent -> branchcontent NoJournalledContent -> branchcontent
JournalledContent journalledcontent -> JournalledContent journalledcontent ->
Just journalledcontent Just journalledcontent
@ -989,7 +990,7 @@ overBranchFileContents' select go st = do
drain buf fs = case getnext fs of drain buf fs = case getnext fs of
Just (v, f, fs') -> do Just (v, f, fs') -> do
liftIO $ putMVar buf fs' liftIO $ putMVar buf fs'
content <- getJournalFileStale (GetPrivate True) f >>= \case content <- lockJournal $ \jl -> getJournalFile jl (GetPrivate True) f >>= \case
NoJournalledContent -> return Nothing NoJournalledContent -> return Nothing
JournalledContent journalledcontent -> JournalledContent journalledcontent ->
return (Just journalledcontent) return (Just journalledcontent)