Siyao Meng created HDDS-17419:
---------------------------------
Summary: 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
Reporter: Siyao Meng
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]