Siyao Meng created HDDS-16763:
---------------------------------
Summary: A failed FSO CompleteMultipartUpload leaves missing
parent directories in the cache, so later acknowledged creates become orphans
Key: HDDS-16763
URL: https://issues.apache.org/jira/browse/HDDS-16763
Project: Apache Ozone
Issue Type: Bug
Reporter: Siyao Meng
Attachments:
MC-2-withdraw-cache-entries-of-failed-fso-multipart-complete.patch,
TestBugMC2FailedMpuOrphanDir.java
h3. Mechanism
{{S3MultipartUploadCompleteRequest.validateAndUpdateCache}} adds the missing
FSO parent directories
({{S3MultipartUploadCompleteRequestWithFSO.addMissingParentsToCache}}) and a
synthesized open file entry to the table cache before checks that can still
fail ({{NOT_A_FILE}}, {{NO_SUCH_MULTIPART_UPLOAD_ERROR}}, the part list checks,
{{QUOTA_EXCEEDED}} for the key). The error response writes nothing to RocksDB,
and nothing removes those cache entries until the epoch is evicted after flush.
{{OzoneManagerStateMachine.applyTransaction}} does not wait for the double
buffer flush, so a later request can be applied while the failed request's
directories are still visible in the cache.
h3. Trigger
On an FSO bucket, a {{CompleteMultipartUpload}} that fails (for example an
unknown upload ID) for a key whose parent directories do not exist, followed by
a mkdir or key create and commit under those parents, applied before the failed
request's epoch is flushed and evicted.
h3. Impact
The later request is acknowledged OK and persists a directory or file row whose
parent directory never reaches RocksDB. After eviction the acknowledged
directory or key is unreachable ({{FILE_NOT_FOUND}} / {{KEY_NOT_FOUND}}), stays
unreachable after OM restart, and its row and namespace charge remain as an
orphan. The outcome also depends on each OM's flush timing: an OM that applies
the later create after its own eviction creates the parents itself, so
{{directoryTable}} and {{usedNamespace}} can differ between OMs (argued, not
run).
h3. Reproduction
PASS. [^TestBugMC2FailedMpuOrphanDir.java] ({{hadoop-ozone/integration-test}}),
uninstrumented jars, single OM mini cluster. With two racing client threads and
no hooks, 4 of 300 acknowledged mkdirs were lost. Holding the flush with
{{OzoneManagerDoubleBuffer.pause/unpause}} makes it deterministic. The cross OM
consequence is argued, not run.
h3. Suggested fix
Withdraw the directory and open file cache entries when the complete fails,
under the bucket lock, or restructure the method so that it publishes them only
on success. A plain move of {{addMissingParentsToCache}} and
{{addMultiPartToCache}} below the validation does not work, because the method
resolves the key through those cache entries in between (the complete after
parent deletion case of HDDS-11784 would start failing). HDDS-16117 fixed the
bucket quota side of this site only.
h3. Patch
[^MC-2-withdraw-cache-entries-of-failed-fso-multipart-complete.patch], against
20e6a1c0f6039248373efd3eb1d7f2afcf7f1535. It also applies to master at
9c6bee807c8.
{{addMissingParentsToCache}} returns the directory table keys it added, and the
existing {{catch}} block calls a new hook, {{removeMissingEntriesFromCache}},
which the FSO request implements by replacing those entries and the synthesized
open key entry with entries without a value at the same transaction index,
while the bucket lock is still held. The keys were verified absent under that
lock before they were added, so this restores the state before the request, and
a later request creates the parents itself on every OM. The success path is
untouched. Publishing only on success would be the cleaner rule but needs the
key resolution on the success path reworked; that is a reviewer's call.
Covered by {{testFailedCompleteDoesNotLeaveMissingParentsInCache}} in the
existing {{TestS3MultipartUploadCompleteRequestWithFSO}} and
{{testDirectoryCreatedAfterFailedCompleteIsPersistedWithItsParent}} in the
existing {{TestOzoneClientMultipartUploadWithFSO}} (double buffer pause and
unpause on the shared cluster). Both fail without the change. The multipart
request and response unit suites (127 tests) and all of
{{TestOzoneClientMultipartUploadWithFSO}} (33 tests, including the HDDS-16117
and HDDS-11784 cases) pass, checkstyle is clean.
Found by TLA+ model checking and code review of the OM FSO namespace mutation
paths under HDDS-15926, on commit 20e6a1c0f6039248373efd3eb1d7f2afcf7f1535.
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]