resume properly when copying a file to/from a local git remote is interrupted (take 2)

This method avoids breaking test_readonly. Just check if the dest file
exists, and avoid CoW probing when it does, so when CoW probing fails,
it can resume where the previous non-CoW copy left off.

If CoW has been probed already to work, delete the dest file
since a CoW copy will presumably work. It seems like it would be almost
as good to just skip CoW copying in this case too, but consider that the
dest file might have started to be copied from some other remote, not
using CoW, but CoW has been probed to work to copy from the current
place.

Sponsored-by: Dartmouth College's Datalad project
This commit is contained in:
Joey Hess 2021-09-27 16:03:01 -04:00
parent 7ccf642863
commit b9aa2ce8d1
No known key found for this signature in database
GPG key ID: DB12DB0FF05F8F38
3 changed files with 26 additions and 8 deletions

View file

@ -27,18 +27,32 @@ newtype CopyCoWTried = CopyCoWTried (MVar Bool)
newCopyCoWTried :: IO CopyCoWTried
newCopyCoWTried = CopyCoWTried <$> newEmptyMVar
{- Copies a file is copy-on-write is supported. Otherwise, returns False. -}
{- Copies a file is copy-on-write is supported. Otherwise, returns False.
-
- The destination file must not exist yet, or it will fail to make a CoW copy,
- and will return false.
-}
tryCopyCoW :: CopyCoWTried -> FilePath -> FilePath -> MeterUpdate -> IO Bool
tryCopyCoW (CopyCoWTried copycowtried) src dest meterupdate =
-- If multiple threads reach this at the same time, they
-- will both try CoW, which is acceptable.
ifM (isEmptyMVar copycowtried)
( do
ok <- docopycow
void $ tryPutMVar copycowtried ok
return ok
-- If dest exists, don't try CoW, since it would
-- have to be deleted first.
( ifM (doesFileExist dest)
( return False
, do
ok <- docopycow
void $ tryPutMVar copycowtried ok
return ok
)
, ifM (readMVar copycowtried)
( docopycow
( do
-- CoW is known to work, so delete
-- dest if it exists in order to do a fast
-- CoW copy.
void $ tryIO $ removeFile dest
docopycow
, return False
)
)

View file

@ -9,6 +9,8 @@ git-annex (8.20210904) UNRELEASED; urgency=medium
* borg: Avoid trying to extract xattrs, ACLS, and bsdflags when
retrieving from a borg repository.
* Sped up git-annex smudge --clean by 25%.
* Resume where it left off when copying a file to/from a local git remote
was interrupted.
-- Joey Hess <id@joeyh.name> Fri, 03 Sep 2021 12:02:55 -0400

View file

@ -56,11 +56,13 @@ copyFileExternal meta src dest = do
| otherwise = copyMetaDataParams meta
{- When a filesystem supports CoW (and cp does), uses it to make
- an efficient copy of a file. Otherwise, returns False. -}
- an efficient copy of a file. Otherwise, returns False.
-
- The dest file must not exist yet, or it will fail to make a CoW copy,
- and will return False. -}
copyCoW :: CopyMetaData -> FilePath -> FilePath -> IO Bool
copyCoW meta src dest
| BuildInfo.cp_reflink_supported = do
void $ tryIO $ removeFile dest
-- When CoW is not supported, cp will complain to stderr,
-- so have to discard its stderr.
ok <- catchBoolIO $ withNullHandle $ \nullh ->