add stat check

I have a strace taken on a lustre filesystem on which link() returned 0,
but didn't actually succeed, since the file already existed.

One of the linux man pages recommended using link followed by checking like
this. I was reading it yesterday, but cannot find it now.
This commit is contained in:
Joey Hess 2015-11-13 13:22:45 -04:00
parent 88d94e674c
commit c2cbe5619b
Failed to extract signature

View file

@ -92,7 +92,7 @@ tryLock lockfile = trySideLock lockfile $ \sidelock -> do
nukeFile tmp
return Nothing
let tooklock = return $ Just $ LockHandle lockfile fd sidelock
ifM (isJust <$> catchMaybeIO (createLink tmp lockfile))
ifM (linkToLock tmp lockfile)
( do
nukeFile tmp
tooklock
@ -111,6 +111,33 @@ tryLock lockfile = trySideLock lockfile $ \sidelock -> do
_ -> failedlock
)
-- Linux man pages recommend linking a pid lock into place,
-- as the most portable atomic operation that will fail if
-- it already exists. However, on some network filesystems,
-- link will return success sometimes despite having failed,
-- so we have to stat both files to check if it actually worked.
linkToLock :: FilePath -> FilePath -> IO Bool
linkToLock src dest = ifM (isJust <$> catchMaybeIO (createLink src dest))
( catchDefaultIO False checklink
, return False
)
where
checklink = do
x <- getSymbolicLinkStatus src
y <- getSymbolicLinkStatus dest
return $ and
[ deviceID x == deviceID y
, fileID x == fileID y
, fileMode x == fileMode y
, linkCount x == linkCount y
, fileOwner x == fileOwner y
, fileGroup x == fileGroup y
, specialDeviceID x == specialDeviceID y
, fileSize x == fileSize y
, modificationTime x == modificationTime y
, isRegularFile x == isRegularFile y
]
-- | Waits as necessary to take a lock.
--
-- Uses a 1 second wait-loop.