diff options
author | Joey Hess <joey@kitenet.net> | 2012-02-24 16:30:47 -0400 |
---|---|---|
committer | Joey Hess <joey@kitenet.net> | 2012-02-24 16:30:47 -0400 |
commit | bd66f962d33e5480ed66fdafc9502926f60ed13b (patch) | |
tree | 09593779f8ed5a7aa2e5dab4aec9ab305e0bfb83 | |
parent | c9b48520ccf7c9dbda0ad08150178868cc69f660 (diff) |
Deal with NFS problem that caused a failure to remove a directory when removing content from the annex.
I was able to reproduce this on linux using the kernel's nfs server and
mounting localhost:/. Determined that removing the directory fails when
the just-deleted file in it was locked. Considered dropping the lock
before removing the directory, but this would complicate parts of the code
that should not need to worry about locking. So instead, ignore the failure
to remove the directory in this case.
While I was at it, made it attempt to remove both levels of hash
directories, in case they're empty.
-rw-r--r-- | Annex/Content.hs | 33 | ||||
-rw-r--r-- | debian/changelog | 2 | ||||
-rw-r--r-- | doc/bugs/nfs_mounted_repo_results_in_errors_on_drop_move.mdwn | 14 |
3 files changed, 39 insertions, 10 deletions
diff --git a/Annex/Content.hs b/Annex/Content.hs index d10370bc9..fc5f46af9 100644 --- a/Annex/Content.hs +++ b/Annex/Content.hs @@ -244,20 +244,33 @@ withObjectLoc key a = do let dir = parentDir file a (dir, file) +cleanObjectLoc :: Key -> Annex () +cleanObjectLoc key = do + file <- inRepo $ gitAnnexLocation key + liftIO $ removeparents file (3 :: Int) + where + removeparents _ 0 = return () + removeparents file n = do + let dir = parentDir file + maybe (return ()) (const $ removeparents dir (n-1)) + =<< catchMaybeIO (removeDirectory dir) + {- Removes a key's file from .git/annex/objects/ -} removeAnnex :: Key -> Annex () -removeAnnex key = withObjectLoc key $ \(dir, file) -> liftIO $ do - allowWrite dir - removeFile file - removeDirectory dir +removeAnnex key = withObjectLoc key $ \(dir, file) -> do + liftIO $ do + allowWrite dir + removeFile file + cleanObjectLoc key {- Moves a key's file out of .git/annex/objects/ -} fromAnnex :: Key -> FilePath -> Annex () -fromAnnex key dest = withObjectLoc key $ \(dir, file) -> liftIO $ do - allowWrite dir - allowWrite file - moveFile file dest - removeDirectory dir +fromAnnex key dest = withObjectLoc key $ \(dir, file) -> do + liftIO $ do + allowWrite dir + allowWrite file + moveFile file dest + cleanObjectLoc key {- Moves a key out of .git/annex/objects/ into .git/annex/bad, and - returns the file it was moved to. -} @@ -270,7 +283,7 @@ moveBad key = do createDirectoryIfMissing True (parentDir dest) allowWrite (parentDir src) moveFile src dest - removeDirectory (parentDir src) + cleanObjectLoc key logStatus key InfoMissing return dest diff --git a/debian/changelog b/debian/changelog index 46d65df38..8c30c2500 100644 --- a/debian/changelog +++ b/debian/changelog @@ -33,6 +33,8 @@ git-annex (3.20120124) UNRELEASED; urgency=low * rekey: New plumbing level command, can be used to change the keys used for files en masse. * Store web special remote url info in a more efficient location. + * Deal with NFS problem that caused a failure to remove a directory + when removing content from the annex. -- Joey Hess <joeyh@debian.org> Tue, 24 Jan 2012 16:21:55 -0400 diff --git a/doc/bugs/nfs_mounted_repo_results_in_errors_on_drop_move.mdwn b/doc/bugs/nfs_mounted_repo_results_in_errors_on_drop_move.mdwn index aa0c3cc29..761ee5b25 100644 --- a/doc/bugs/nfs_mounted_repo_results_in_errors_on_drop_move.mdwn +++ b/doc/bugs/nfs_mounted_repo_results_in_errors_on_drop_move.mdwn @@ -43,3 +43,17 @@ I'm on an nfs mounted filesystem (some netapp somewhere). This is repeatable, e I suspect git-annex is just too fast and optimistic for big slow nfs directories. +> git-annex locks files while it is operating on their content +> to avoid race conditions with other git-annex processes. +> Quite likely this problem (which I can reproduce) is due to +> NFS having bad (non-POSIX) locking semantics. +> +> Probably the +> lock is represented on the NFS server as some form of lock file +> next to the file being locked, and so when that file is deleted, with +> the lock still held, the directory, which should then be empty, still +> contains this lock file. +> +> So, this can be worked around by it not failing when the directory +> unexpectedly cannot be removed. I've made that change. [[done]] +> --[[Joey]] |