Bug #68183
openrgw: conditional write doesn't work in certain scenarios
0%
Description
Ceph supports conditional writing since 2014: https://tracker.ceph.com/issues/8562
However it doesn't work with the following cases:
- a bucket has versioning enabled
- it's a multipart upload
Current behavior¶
S3 API returns 201 even though the If-None-Match: * header was submitted to a bucket with the versioning enabled or during the multipart upload.
Simple bucket¶
This example works fine
$ curl -XPUT https://my-ceph.local/condition_write/only_once --aws-sigv4 aws:amz:default:s3 -u XX:XX -H "If-None-Match: *" -v -d"This is the first write" 2>&1 | egrep -i 'HTTP|etag|Modified' * ALPN: curl offers h2,http/1.1 * using HTTP/1.x > PUT /condition_write/only_once HTTP/1.1 < HTTP/1.1 200 OK < ETag: "dcc31a80288e0758b0c522eaaa0b5bec" $ curl -XPUT https://my-ceph.local/condition_write/only_once --aws-sigv4 aws:amz:default:s3 -u XX:XX -H "If-None-Match: *" -v -d"This is the first write" 2>&1 | egrep -i 'HTTP|etag|Modified' * ALPN: curl offers h2,http/1.1 * using HTTP/1.x > PUT /condition_write/only_once HTTP/1.1 < HTTP/1.1 412 Precondition Failed
Bucket with versioning enabled¶
$ aws --region default --endpoint-url https://my-ceph.local s3api put-bucket-versioning --bucket condition_write --versioning-configuration Status=Enabled $ curl -XPUT https://my-ceph.local/condition_write/only_once --aws-sigv4 aws:amz:default:s3 -u XX:XX -H "If-None-Match: *" -v -d"This is the first write" 2>&1 | egrep -i 'HTTP|etag|Modified' * ALPN: curl offers h2,http/1.1 * using HTTP/1.x > PUT /condition_write/only_once HTTP/1.1 < HTTP/1.1 200 OK < ETag: "dcc31a80288e0758b0c522eaaa0b5bec" $ curl -XPUT https://my-ceph.local/condition_write/only_once --aws-sigv4 aws:amz:default:s3 -u XX:XX -H "If-None-Match: *" -v -d"This is the first write" 2>&1 | egrep -i 'HTTP|etag|Modified' * ALPN: curl offers h2,http/1.1 * using HTTP/1.x > PUT /condition_write/only_once HTTP/1.1 < HTTP/1.1 200 OK < ETag: "dcc31a80288e0758b0c522eaaa0b5bec"
Multipart upload¶
Create an initial key and test the second conditional write with the If-None-Match: *
$ curl -XPUT https://my-ceph.local/condition_write/only_once --aws-sigv4 aws:amz:default:s3 -u XX:XX -H "If-None-Match: *" -v -d"This is the first write" 2>&1 | egrep -i 'HTTP|etag|Modified' * ALPN: curl offers h2,http/1.1 * using HTTP/1.x > PUT /condition_write/only_once HTTP/1.1 < HTTP/1.1 200 OK < ETag: "dcc31a80288e0758b0c522eaaa0b5bec" $ curl -XPUT https://my-ceph.local/condition_write/only_once --aws-sigv4 aws:amz:default:s3 -u XX:XX -H "If-None-Match: *" -v -d"This is the first write" 2>&1 | egrep -i 'HTTP|etag|Modified' * ALPN: curl offers h2,http/1.1 * using HTTP/1.x > PUT /condition_write/only_once HTTP/1.1 < HTTP/1.1 412 Precondition Failed
Run multipart upload against this key:
$ curl -s -XPOST https://my-ceph.local/condition_write/only_once?uploads -H "If-None-Match: *" --aws-sigv4 aws:amz:default:s3 -u XX:XX <?xml version="1.0" encoding="UTF-8"?><InitiateMultipartUploadResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/"><Tenant>481c6f7874024488a2ab2197e5bb1931</Tenant><Bucket>condition_write</Bucket><Key>only_once</Key><UploadId>2~QcmAkzqsyVF1un_uiLA-Ste89T_ExaN</UploadId></InitiateMultipartUploadResult> $ curl -XPUT "https://my-ceph.local/condition_write/only_once?partNumber=1&uploadId=2~QcmAkzqsyVF1un_uiLA-Ste89T_ExaN" -H "If-None-Match: *" --aws-sigv4 aws:amz:default:s3 -u XX:XX -d"This is the multipart write" -v ... < HTTP/1.1 200 OK < Content-Length: 0 < ETag: "e4683000ff181d33580b4039304880da" ... $ curl -XPOST "https://my-ceph.local/condition_write/only_once?uploadId=2~QcmAkzqsyVF1un_uiLA-Ste89T_ExaN" -H "If-None-Match: *" -H "Content-Type: application/xml" --aws-sigv4 aws:amz:default:s3 -u XX:XX -d"<CompleteMultipartUpload><Part><PartNumber>1</PartNumber><ETag>e4683000ff181d33580b4039304880da</ETag></Part></CompleteMultipartUpload>" <?xml version="1.0" encoding="UTF-8"?><CompleteMultipartUploadResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/"><Location>my-ceph.local/481c6f7874024488a2ab2197e5bb1931:condition_write/only_once</Location><Tenant>481c6f7874024488a2ab2197e5bb1931</Tenant><Bucket>condition_write</Bucket><Key>only_once</Key><ETag></ETag></CompleteMultipartUploadResult> $ curl "https://my-ceph.local/condition_write/only_once" --aws-sigv4 aws:amz:default:s3 -u XX:XX This is the multipart write
As you see, the object was rewritten with the multipart upload content: This is the multipart write
Expected behavior¶
All update requests with the If-None-Match: * header must fail with the 412 response code.
Updated by kay diam over 1 year ago
- Subject changed from rgw: conditioning writing doesn't work in certain scenarios to rgw: conditional write doesn't work in certain scenarios
Updated by Casey Bodley over 1 year ago
- Related to Feature #67925: AWS S3 Conditional Writes added
Updated by J. Eric Ivancich over 1 year ago
- Related to Bug #68185: rgw: conditional write doesn't work with Swift API added
Updated by kay diam over 1 year ago
In addition, the conditional write feature should be reflected in documentation. Currently there is no info: https://docs.ceph.com/en/latest/radosgw/s3/objectops/
Updated by Ali Masarwa 6 months ago
- Copied to Bug #73076: rgw: conditional write doesn't work with multipart upload added
Updated by Casey Bodley 6 months ago
- Status changed from New to Pending Backport
- Assignee set to Ali Masarwa
- Backport set to squid tentacle
- Pull request ID set to 63348
Updated by Casey Bodley 6 months ago
backports need to include followup fix for https://tracker.ceph.com/issues/72517 https://github.com/ceph/ceph/pull/64997
Updated by Upkeep Bot 6 months ago
- Copied to Backport #73089: squid: rgw: conditional write doesn't work in certain scenarios added
Updated by Upkeep Bot 6 months ago
- Copied to Backport #73090: tentacle: rgw: conditional write doesn't work in certain scenarios added
Updated by Upkeep Bot 6 months ago
- Merge Commit set to 78502297afd074e51e0d2f99fac1b45fc3eaa0c2
- Fixed In set to v20.3.0-1937-g78502297af
- Upkeep Timestamp set to 2025-09-17T18:54:59+00:00