diff options
author | Ludovic Courtès <ludo@gnu.org> | 2018-12-14 11:10:25 +0100 |
---|---|---|
committer | Ludovic Courtès <ludo@gnu.org> | 2018-12-14 12:07:24 +0100 |
commit | adb158b7396cbdcda347fa298978408e531a03fd (patch) | |
tree | fd6877e72a20840cd3962f80a89618bd08fcf04b /guix | |
parent | ea49fbdea3bbb9b55951b7bff9d9cf768fd23161 (diff) |
deduplication: Gracefully handle ENOSPC raised by 'link' calls.
Reported by Andreas Enge <andreas@enge.fr>
in <https://bugs.gnu.org/33676>.
* guix/store/deduplication.scm (replace-with-link): Catch ENOSPC around
'get-temp-link'. Do nothing when 'get-temp-link' throws ENOSPC. Move
code to restore PARENT's permissions outside of 'catch'.
* tests/store-deduplication.scm ("deduplicate, ENOSPC"): New test.
Diffstat (limited to 'guix')
-rw-r--r-- | guix/store/deduplication.scm | 40 |
1 files changed, 27 insertions, 13 deletions
diff --git a/guix/store/deduplication.scm b/guix/store/deduplication.scm index 21b0c81f3d..a777940f86 100644 --- a/guix/store/deduplication.scm +++ b/guix/store/deduplication.scm @@ -99,24 +99,38 @@ LINK-PREFIX." (define* (replace-with-link target to-replace #:key (swap-directory (dirname target))) "Atomically replace the file TO-REPLACE with a link to TARGET. Use -SWAP-DIRECTORY as the directory to store temporary hard links. +SWAP-DIRECTORY as the directory to store temporary hard links. Upon ENOSPC +and EMLINK, TO-REPLACE is left unchanged. Note: TARGET, TO-REPLACE, and SWAP-DIRECTORY must be on the same file system." - (let* ((temp-link (get-temp-link target swap-directory)) - (parent (dirname to-replace)) - (stat (stat parent))) - (make-file-writable parent) + (define temp-link (catch 'system-error (lambda () - (rename-file temp-link to-replace) - - ;; Restore PARENT's mtime and permissions. - (set-file-time parent stat) - (chmod parent (stat:mode stat))) + (get-temp-link target swap-directory)) (lambda args - (delete-file temp-link) - (unless (= EMLINK (system-error-errno args)) - (apply throw args)))))) + ;; We get ENOSPC when we can't fit an additional entry in + ;; SWAP-DIRECTORY. + (if (= ENOSPC (system-error-errno args)) + #f + (apply throw args))))) + + ;; If we couldn't create TEMP-LINK, that's OK: just don't do the + ;; replacement, which means TO-REPLACE won't be deduplicated. + (when temp-link + (let* ((parent (dirname to-replace)) + (stat (stat parent))) + (make-file-writable parent) + (catch 'system-error + (lambda () + (rename-file temp-link to-replace)) + (lambda args + (delete-file temp-link) + (unless (= EMLINK (system-error-errno args)) + (apply throw args)))) + + ;; Restore PARENT's mtime and permissions. + (set-file-time parent stat) + (chmod parent (stat:mode stat))))) (define* (deduplicate path hash #:key (store %store-directory)) "Check if a store item with sha256 hash HASH already exists. If so, |