[
https://issues.apache.org/jira/browse/HDDS-17419?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Siyao Meng updated HDDS-17419:
------------------------------
Attachment: CR-8-reject-if-none-match-etag-before-om-finalization.patch
> OM accepts If-None-Match ETag on CreateKey and CompleteMultipartUpload before
> it is finalized for S3_IF_NONE_MATCH_ETAG
> -----------------------------------------------------------------------------------------------------------------------
>
> Key: HDDS-17419
> URL: https://issues.apache.org/jira/browse/HDDS-17419
> Project: Apache Ozone
> Issue Type: Bug
> Affects Versions: 2.3.0
> Reporter: Siyao Meng
> Priority: Minor
> Attachments:
> CR-8-reject-if-none-match-etag-before-om-finalization.patch,
> TestBugCR8PreFinalizedIfNoneMatch.java
>
>
> h3. Mechanism
> {{OzoneManagerVersion.S3_IF_NONE_MATCH_ETAG}} (104) is gated in the OM only
> by {{OzoneManager.checkFeatureEnabled}}, called from
> {{OMKeyCreateRequest.preExecute}} and
> {{S3MultipartUploadCompleteRequest.preExecute}} when {{KeyArgs.excludedETag}}
> is set. That method reads {{ozone.om.features.disabled}} and never the
> apparent version. No request in main code uses {{@DisallowedUntilOmVersion}},
> and no request validator checks the field. So an OM that is not finalized for
> 104 evaluates the condition in {{validateAndUpdateCache}} like a finalized
> one. The ZDU design requires new features to be unavailable until the upgrade
> is finalized, with an error for a client that tries one.
> h3. Trigger
> # The OMs run the current software and are pre-finalized (apparent version
> ZDU or a pre-ZDU layout version), as during an upgrade before finalization.
> # A client that does not check the OM version first sends CreateKey or
> CompleteMultiPartUpload with {{excludedETag}} over the OM protocol. This
> could be a non-Java client, or {{OzoneManagerProtocol}} used directly.
> {{RpcClient}}, and S3 Gateway through it, refuses on its cached OM version,
> so the stock clients do not send the field in this state.
> h3. Impact
> The OM applies If-None-Match before finalization: {{KEY_ALREADY_EXISTS}} for
> a matching ETag, or an open key guarded by {{expectedDataGeneration}}
> otherwise. At this commit every ZDU capable OM runs the same software, so all
> replicas apply the request the same way, and the guard field predates ZDU, so
> nothing is persisted in a new format. I found no replica divergence or data
> loss reachable today. The gap matters for the pattern: a later OM version
> gated the same way would, during a rolling upgrade or downgrade between ZDU
> releases, let a replica on the older software ignore the field and apply the
> request differently (argued, not run).
> h3. Reproduction
> PASS on unmodified source. [^TestBugCR8PreFinalizedIfNoneMatch.java]
> ({{hadoop-ozone/ozone-manager}}) starts one real OM with apparent version ZDU
> (test only {{OMStorage.TESTING_INIT_APPARENT_VERSION_KEY}}, software version
> 104) and sends requests through {{OzoneManagerProtocol}}. As a control,
> {{RpcClient.createKeyIfNoneMatch}} refuses. Results:
> * CreateKey with the current ETag as If-None-Match returns
> {{KEY_ALREADY_EXISTS}}.
> * CreateKey with another ETag succeeds, and the open key carries
> {{expectedDataGeneration}}.
> * CompleteMultiPartUpload with the current ETag returns
> {{KEY_ALREADY_EXISTS}}.
> A passing test means the defect is present. An earlier run of the same
> scenario on a three OM mini cluster during the analysis showed all three
> replicas applying it; I did not repeat that run. No mixed software ring was
> run, as none can be built at this commit.
> h3. Suggested fix
> The patch below closes the gap for the one post-ZDU write feature that exists
> today. Versions 101 to 103 need no gate for replica consistency. 101 and 103
> only add a rejection to read requests. 102 is used on writes only by
> AbortMultipartUpload, where the receiving OM resolves the S3 volume and
> clears {{assumeS3Context}} before the request enters the Ratis log.
> h3. Patch
> [^CR-8-reject-if-none-match-etag-before-om-finalization.patch], against
> 5f7111a27ea07ce6b7bf5284a4213ebacb65f2ae. It applies to master at e03ba37c41d
> with {{git apply -3}}: an import that HDDS-17299 added to
> {{TestOMKeyCreateRequest}} shifts one context line, and the three way merge
> is clean. The two touched test classes and their FSO subclasses passed on the
> merged tree at master 3f1a4331ec2.
> The patch adds two {{CLUSTER_NEEDS_FINALIZATION}} pre-process request
> validators, {{OMKeyCreateRequest.disallowCreateKeyWithExcludedETag}} and
> {{S3MultipartUploadCompleteRequest.disallowCompleteMultiPartUploadWithExcludedETag}}.
> They follow the EC validators in the same classes and reject
> {{excludedETag}} with {{NOT_SUPPORTED_OPERATION_PRIOR_FINALIZATION}} while
> the OM is not finalized for 104. The check runs before the request becomes a
> Ratis entry, and only the leader can accept, so replicas never disagree on
> it. Finalized clusters are unaffected, and the config check stays.
> {{@DisallowedUntilOmVersion}} was not used because it would block the whole
> request type.
> The gate is only as correct as the leader's apparent version. An OM that
> wrongly starts finalized in a pre-finalized ring skips all
> {{CLUSTER_NEEDS_FINALIZATION}} validators, this one included, while it leads.
> Covered by {{testDisallowExcludedETagBeforeFinalization}} in the existing
> {{TestOMKeyCreateRequest}} and {{TestS3MultipartUploadCompleteRequest}}. Each
> test loads the real validator registry with a pre-finalized version manager
> that allows every version except {{S3_IF_NONE_MATCH_ETAG}}, and checks both
> the rejection and that a request without the field passes. Without the
> change, all four runs fail (including both FSO subclasses). With it, the key
> create and commit, MPU complete and validator suites pass (698 tests),
> {{TestS3SDK}} on a mini cluster passes (249 tests, including the
> If-None-Match ETag PutObject and CompleteMultipartUpload cases), and
> checkstyle is clean. With the patch, the reproduction fails because all three
> requests return {{NOT_SUPPORTED_OPERATION_PRIOR_FINALIZATION}}.
> Related, not duplicates: HDDS-17258 (new OM request versioning framework for
> ZDU), HDDS-16734 (conditional delete and conditional MPU complete are ungated
> on client and OM), HDDS-17140 (S3 Gateway does not pick up the new OM version
> after ZDU finalization).
> Found by code review of the zero downtime upgrade version gating in SCM, OM
> and the datanode write path, as part of the TLA+ verification effort under
> HDDS-15926, on commit 5f7111a27ea07ce6b7bf5284a4213ebacb65f2ae. Checked
> against HDDS issues and apache/ozone pull requests for duplicates before
> filing. The attached patch is a proposal for review. Generated with Specula
> (Claude Opus 5.5).
--
This message was sent by Atlassian Jira
(v10.3.26#10030026)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]