Repository navigation
fix(replication): forward FULL_OBJECT checksum type for multipart replicas - #255
Merged
Vonng merged 1 commit intoOct 24, 2026
Merged
Conversation
…licas Signed-off-by: Denis Babchuk <babchukdenis@icloud.com>
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.
Contribution Licensing (no CLA, inbound=outbound, DCO required)
This pull request contributes to PGSTY SILO (
pgsty/silo). Code contributionsare accepted under AGPL-3.0-or-later, the same license as the server.
This project does not use a CLA or require a separate Apache-2.0 license grant.
By submitting this pull request I represent that I have the right to contribute
the code changes under this repository's
GNU Affero General Public License v3.0 or later
and retain copyright in my original work. Existing copyright and license
notices remain intact; separately licensed material keeps its applicable terms.
Every commit must carry a DCO
Signed-off-bytrailer(
git commit -s) certifying theDeveloper Certificate of Origin — see
CONTRIBUTING.md.
Description
Fixes #254
getCRCMetabuilds the checksum headers for replication requests and dropsx-amz-checksum-type(cmd/bucket-replication.go:4246):putReplicationOptspasses these headers to the target'sNewMultipartUpload. A multipart object with a FULL_OBJECT CRC32 or CRC32C checksum is therefore replicated into a COMPOSITE upload.replicateObjectWithMultipartcompletes it with the whole-object CRC, and the target's composite check (cmd/erasure-multipart.go:1586) rejects that withBadDigest: The CRC32 you specified did not match the calculated checksum.. The version stays FAILED and never reaches the target. CRC64NVME is not affected because the target defaults it to FULL_OBJECT.The skip comes from upstream minio#21535 (
4ea6f3b06); before it, the type was forwarded with every checksum. c859041 and 7e079ff do not cover this case: they act on completions of uploads the target already treats as FULL_OBJECT, and replication never sends the type.With this change
getCRCMetaaddsx-amz-checksum-type: FULL_OBJECTwhen the checksum is multipart, a mergeable CRC (CanMerge) and of type FULL_OBJECT. The target then creates a FULL_OBJECT upload. The completion carries the type too, which passes the explicit type check from 7e079ff. Part requests, single-part objects, COMPOSITE checksums and SHA1/SHA256 keep the headers they get today.Motivation and Context
Since c859041 (#31), SILO accepts FULL_OBJECT CRC32/CRC32C multipart uploads from SDK clients. With replication configured, these objects stay FAILED on the source and never reach the target. Every retry, including the one a
HeadObjecton a FAILED version queues, sends the whole object again.Why only multipart FULL_OBJECT CRCs. Forwarding the type for every checksum, as before minio#21535, would send
FULL_OBJECTwith single-part SHA1/SHA256 checksums, and the target rejects that combination (getContentChecksum,internal/hash/checksum.go:766). Single-part objects and COMPOSITE uploads replicate correctly without the type.CanMergelimits the change to CRC32, CRC32C and CRC64NVME; for CRC64NVME the header only repeats the target's default.Server-side copies.
putReplicationOptsalready replicates an object with a singlePutObjectwhen the object is not multipart but has a FULL_OBJECT checksum (cmd/bucket-replication.go:883). With the type dropped, that check never matched. ACopyObjectof a multipart FULL_OBJECT object is such an object: it keeps the multipart checksum but has a plain ETag. On main it is replicated as a one-part multipart upload and fails with the sameBadDigest. With this change the check works as written, and the copy is replicated with a single PUT.How to test this PR?
The tests are in the new file
cmd/bucket-replication-checksum_test.go.TestGetCRCMetaChecksumTypechecks the headersgetCRCMetabuilds for single-part objects (SHA256, CRC32, CRC64NVME), multipart COMPOSITE objects (CRC32C, SHA256) and multipart FULL_OBJECT objects (CRC32, CRC32C, CRC64NVME), and for a part request.TestReplicateObjectChecksumTypesuploads objects through the S3 API of a test server and replicates them into a second bucket the wayreplicateObjectdoes:putReplicationOpts, thenreplicateObjectWithMultipartorPutObject. It checks the replication mode and compares the replica's checksum with the source. The cases are single PUTs (SHA256, CRC32), multipart COMPOSITE (CRC32C, SHA256), multipart FULL_OBJECT (CRC32, CRC32C, CRC64NVME) and aCopyObjectof the FULL_OBJECT CRC32 object.Without the change:
TestGetCRCMetaChecksumTypefails on the three multipart FULL_OBJECT cases becausex-amz-checksum-typeis missing.TestReplicateObjectChecksumTypesfails onmp-FULL_OBJECT-CRC32andmp-FULL_OBJECT-CRC32Cwithreplication failed: The CRC32 you specified did not match the calculated checksum., and oncopy-FULL_OBJECT-CRC32withmultipart replication: got true, want false.With the change both tests pass.
Run locally on Go 1.27.3 (darwin/arm64), on main
b91e1c6f2:make verifiers(golangci-lint v2.15.0: 0 issues, check-gen, rebrand-guard),go vet ./cmd,make buildgo test ./cmd -count=1 -run 'Replicat|Checksum|CRC|Multipart'go test ./cmd -count=1 -timeout 60m:ok, 274 sManual check with two single-drive servers and
mc admin replicate add, as in the issue. Objects are uploaded to the first site with aws CLI v2 (2 × 5 MiB parts for multipart). Each cell shows the source replication status; COMPLETED also means that the replica has the same checksum and checksum type as the source.CopyObjectof the FULL_OBJECT CRC32 objectThe columns are source → target builds. In the failing cells the target's
mc admin trace --errorsshows400 s3.CompleteMultipartUploadfor each attempt.Compatibility impact
No API, configuration, storage metadata, metric, route or dependency changes.
NewMultipartUploadandCompleteMultipartUploadto the target now carryx-amz-checksum-type: FULL_OBJECT. A copy of such an object, which is not multipart, is replicated with onePutObjectcarrying the same headers instead of a one-part multipart upload. Part requests and all other objects are unchanged.X-Minio-Replication-Ssec-Crc, andgetCRCMetacannot decrypt it without the client key.putReplicationOptsas well (batchReplicationOpts), so it sends the same headers. I did not test it separately.Types of changes
Checklist:
git commit -s) per the DCOcommit-idorPR #here): upstream4ea6f3b06(fix: invalid checksum on site replication with conforming checksum types minio/minio#21535)make verifierspassesmake buildpasspgsty/silo.pgsty.com, if needed (not needed)