Repository navigation
registry/storage: do not write hash state when closing a cancelled upload - #5021
Merged
milosgajdos merged 1 commit intoOct 18, 2026
Merged
Conversation
…load Cancel removes the upload directory, but the handler then closes the writer, and Close stores the hash state again. That recreates the upload directory without a startedat file, so the upload purger can never remove it, and Close reports "already closed". Skip storing the hash state once the upload has been cancelled. Signed-off-by: YoungjuKim <[email protected]>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Cancelling a blob upload (
DELETE /v2/<name>/blobs/uploads/<uuid>, or the cleanup after a failedPUT) leaves a directory behind that upload purging never removes.What happens in
main:blobWriter.Cancelcancels the file writer, then callsbw.Close(), thenremoveResourcesdeletes_uploads/<uuid>/.defer buh.Upload.Close()inCancelBlobUpload, andcloseResourcesinblobUploadDispatcher).blobWriter.ClosecallsstoreHashState, whichPutContents_uploads/<uuid>/hashstates/sha256/<offset>. That recreates the directoryremoveResourcesjust deleted, this time withoutdataorstartedat.getOutstandingUploadsgives an upload withoutstartedatthe default start timenow + 10000h, soPurgeUploadsnever treats it as old and the directory stays forever.The
Close()insideCancelalso always fails on the filesystem driver, becausefileWriter.Cancelhas already closed the file, so every cancelled upload logserror closing blobwriter: ...at error level.I found this on a registry that uses the filesystem driver (Harbor v2.15.2, whose registry is a v2.8.3 fork with the same
Cancel/Closecode and the same deferred close in the handler):DELETE .../blobs/uploads/<uuid>requests (all204) in the current log were followed byerror closing blobwriter: sync .../_uploads/<uuid>/data: file already closed, and each of those 12 directories still exists with onlyhashstates/sha256/0(108 bytes).hashstates-only (nodata, nostartedat); 1,228 are older than 30 days.age: 168h,interval: 24h); its latest run loggedPurge uploads finished. Num deleted=0, num errors=0.This is probably what #4524 described on S3.
The fix marks the writer as cancelled and makes
CloseskipstoreHashStatefor a cancelled upload.Closestill calls the driver'sFileWriter.Closeso drivers that release resources there (for example the S3 buffer pool) keep doing so; its error is ignored because the writer has already been cancelled. That also removes the spurious error log.The new test
TestBlobUploadCloseAfterCancelwrites a few bytes, cancels, closes the upload the way the handler does, and checks that the upload path no longer exists. With the in-memory driver it fails before the change and passes after it:Testing done:
main@ 042c3a9):--- PASS: TestBlobUploadCloseAfterCancelgo test ./registry/storage/ ./registry/handlers/→ok(8.6s, 64.7s);go vet ./registry/storage/cleangofmt -lis clean for the changed files.This change was drafted with AI assistance and reviewed by me.
🤖 Generated with Claude Code