[ 
https://issues.apache.org/jira/browse/HDDS-16788?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Siyao Meng updated HDDS-16788:
------------------------------
    Attachment: TestBugCR4CompleteMissingOpenKey.java

> CompleteMultipartUpload terminates the OM when the open key of an 
> OBJECT_STORE or LEGACY upload is missing
> ----------------------------------------------------------------------------------------------------------
>
>                 Key: HDDS-16788
>                 URL: https://issues.apache.org/jira/browse/HDDS-16788
>             Project: Apache Ozone
>          Issue Type: Bug
>            Reporter: Siyao Meng
>            Priority: Major
>         Attachments: 
> CR-4-fail-multipart-complete-when-open-key-is-missing.patch, 
> TestBugCR4CompleteMissingOpenKey.java
>
>
> h3. Mechanism
> {{S3MultipartUploadCompleteRequest.getOmKeyInfo}} reads the open key of the 
> upload and uses the result without a null check in both of its branches: 
> {{dbOpenKeyInfo.toBuilder()}} when the key does not exist yet, 
> {{dbOpenKeyInfo.getFileEncryptionInfo()}} when an existing key is 
> overwritten. If the upload still has its {{multipartInfoTable}} entry but no 
> open key, the {{NullPointerException}} passes the {{IOException | 
> InvalidPathException}} handler in {{validateAndUpdateCache}}, reaches 
> {{OzoneManagerStateMachine.runCommand}}, and the OM calls 
> {{ExitUtils.terminate}}.
> Other requests already accept this state: {{S3MultipartUploadAbortRequest}} 
> (since HDDS-14601) and {{S3ExpiredMultipartUploadsAbortRequest}} both 
> continue when the open key is missing. FSO buckets are not affected, because 
> the FSO complete request adds a missing open key back before it is read 
> (checked by unit test).
> h3. Trigger
> # An upload on an OBJECT_STORE or LEGACY bucket has its 
> {{multipartInfoTable}} entry but no open key. {{OpenKeyCleanupService}} in 
> 1.3.x deleted the open key of uploads older than 
> {{ozone.om.open.key.expire.threshold}} (default 7d) and left the 
> {{multipartInfoTable}} entry. HDDS-9098 stopped that in 1.4.0, but entries 
> created before survive the upgrade. The HDDS-9095 comments of 2026-02-09 
> report such entries from a running cluster, which led to HDDS-14601.
> # A client sends CompleteMultipartUpload for that upload.
> I found no way to create the state with the current code through the client 
> API or the background services. Since 1.4.0 {{MultipartUploadCleanupService}} 
> aborts such uploads once they are older than 
> {{ozone.om.open.mpu.expire.threshold}} (default 30d), so with default 
> settings the entries disappear about a month after the upgrade. The report 
> above shows that they can outlive that in practice (cause not investigated).
> h3. Impact
> The OM terminates while applying the request. The request is a committed 
> Ratis log entry, so a restarted OM applies it again and terminates again (run 
> on a single node OM). In an HA ring every OM applies the same entry (argued 
> from the state machine code, not run). Nothing skips a failing log entry, so 
> the OMs stay down until an operator intervenes (argued, not run).
> h3. Reproduction
> PASS, deterministic, unmodified source. 
> [^TestBugCR4CompleteMissingOpenKey.java] ({{hadoop-ozone/ozone-manager}}) 
> drives one real OM with single node Ratis through {{OzoneManagerProtocol}}. 
> The only step that is not a client call is the {{DeleteOpenKeys}} request 
> that removes the open key, which is the request {{OpenKeyCleanupService}} 
> submitted for such keys before HDDS-9098. The test shows the terminate for 
> OBJECT_STORE and for LEGACY with a {{NullPointerException}} in 
> {{S3MultipartUploadCompleteRequest.getOmKeyInfo}}, the second terminate on 
> log replay after a restart, and the client abort succeeding on the same 
> state. {{System.exit}} is disabled in the test JVM, so the terminate is 
> observed as the recorded {{ExitUtils.terminate(1, ...)}} call. A passing test 
> means the defect is present.
> h3. Patch
> [^CR-4-fail-multipart-complete-when-open-key-is-missing.patch], against 
> d067ba38e7aea917db7efd290b4af53987ec985a. It also applies to master at 
> a6332fb5987.
> {{getOmKeyInfo}} reads the open key once, before the two branches, and fails 
> with {{NO_SUCH_MULTIPART_UPLOAD_ERROR}} when it is missing. The existing 
> handler returns that as an error response, the OM keeps running, and the 
> {{multipartInfoTable}} entry stays so the upload can still be aborted. The 
> key is not rebuilt from the parts as it is for FSO, because for these layouts 
> the ACLs, metadata, tags and encryption info of the upload are stored only in 
> the open key. A patched OM that replays an already logged complete for such 
> an upload returns the error instead of terminating (argued, not run).
> Covered by {{testValidateAndUpdateCacheWithOrphanMultipartInfo}} in the 
> existing {{TestS3MultipartUploadCompleteRequest}}, without and with an 
> already committed key, inherited by the FSO subclass. Without the change both 
> OBJECT_STORE cases fail with the {{NullPointerException}}. The multipart 
> request and response unit suites and the open key and multipart cleanup 
> service suites (149 tests) pass, checkstyle is clean. No mini cluster suite 
> was run. With the patch the three complete tests of the reproduction fail, 
> because the client receives the error and the OM does not terminate.
> Found by TLA+ model checking and code review of the OM expired multipart 
> upload cleanup paths under HDDS-15926, on commit 
> d067ba38e7aea917db7efd290b4af53987ec985a. 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
(v8.20.10#820010)

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to