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

Siyao Meng updated HDDS-16793:
------------------------------
    Attachment: TestBugCR2QuotaRepairCountsUncommittedDeletedKeys.java

> Quota repair adds deletedTable entries without the committed flag to the 
> pending deletion usage of the bucket, and the purge never releases them
> ------------------------------------------------------------------------------------------------------------------------------------------------
>
>                 Key: HDDS-16793
>                 URL: https://issues.apache.org/jira/browse/HDDS-16793
>             Project: Apache Ozone
>          Issue Type: Bug
>            Reporter: Siyao Meng
>            Priority: Major
>         Attachments: 
> CR-2-count-only-committed-deleted-keys-in-quota-repair.patch, 
> TestBugCR2QuotaRepairCountsUncommittedDeletedKeys.java
>
>
> h3. Mechanism
> {{QuotaRepairTask.countDeletedKey}} (HDDS-15204) adds the replicated size of 
> every key info in the {{deletedTable}} entries of a bucket to 
> {{snapshotUsedBytes}}, and one unit per key info to 
> {{snapshotUsedNamespace}}. The requests that maintain these counters follow a 
> narrower rule (HDDS-13756). Only a key that leaves the key table after commit 
> is added to them, and it is marked with 
> {{OmKeyInfo.withCommittedKeyDeletedFlag(true)}}: by 
> {{AbstractOMKeyDeleteResponse}} for DeleteKey and DeleteKeys, by 
> {{OMKeyCommitRequest}} for the key it overwrites, and by 
> {{OMDirectoriesPurgeResponseWithFSO}} for sub files. When the entry is 
> purged, {{KeyDeletingService}} and {{OMKeyPurgeRequest}} release only key 
> infos that have the flag.
> Every other key info in {{deletedTable}} has no flag and was never added to 
> the counters: the key that {{S3MultipartUploadCompleteRequest}} overwrites, 
> the parts of an aborted multipart upload, an overwritten part and the unused 
> parts of a completed upload, expired open keys ({{OMOpenKeysDeleteRequest}}), 
> the uncommitted blocks of a key commit, and entries written before 
> HDDS-13756. A repair that runs while such an entry is waiting adds an amount 
> to the counters that no purge removes.
> By history, not run on older code: the recount of {{deletedTable}} was added 
> by HDDS-15204 and is in no release tag up to 2.2.1, so only unreleased master 
> is affected.
> h3. Trigger
> # A bucket has a {{deletedTable}} entry without the committed flag. Run with 
> a key that is overwritten by a completed multipart upload. The other sources 
> listed above are from code reading, not run.
> # Quota repair runs for the bucket before {{KeyDeletingService}} purges the 
> entry. An admin starts it with {{ozone repair om quota start}} 
> ({{OzoneManager.startQuotaRepair}}). The service interval is 60s by default. 
> The entry of the overwritten key stays for as long as a snapshot references 
> that key (run separately on the same harness, not part of the attached test: 
> still present after 30 service runs with a snapshot taken before the 
> overwrite).
> # The entry is purged.
> h3. Impact
> * With {{deletedTable}} empty again, {{snapshotUsedBytes}} and 
> {{snapshotUsedNamespace}} of the bucket keep the size and one unit for each 
> key info that had no flag when the repair ran. Both are part of the usage 
> that the quota checks compare. Run: a bucket with a namespace quota of 2 that 
> holds one key rejects a second key with {{QUOTA_EXCEEDED}}. The space quota 
> check reads {{snapshotUsedBytes}} the same way (argued, not run).
> * No data is affected. The counters stay wrong until quota repair runs again 
> at a time when no such entry is waiting (argued, not run).
> h3. Reproduction
> PASS, deterministic, unmodified source. 
> [^TestBugCR2QuotaRepairCountsUncommittedDeletedKeys.java] 
> ({{hadoop-ozone/ozone-manager}}) drives one real OM with its 
> {{KeyDeletingService}} through {{OzoneManagerProtocol}}, with the testing SCM 
> block client of the OM tests and no datanodes. Repair is started with {{new 
> QuotaRepairTask(om).repair(buckets)}}, the body of 
> {{OzoneManager.startQuotaRepair}}. The service interval is 100 ms and the 
> service is held with its own suspend and resume hook so that the repair runs 
> while the entry is waiting. 
> {{multipartOverwriteThenRepairLeavesPendingCountersStuck}} shows 
> {{snapshotUsedBytes=805306368}} and {{snapshotUsedNamespace=1}} after the 
> repair and unchanged after the purge, with an empty {{deletedTable}}, and the 
> rejected second key. {{keyOverwriteThenRepairReturnsToZero}} is the control 
> with a plain key overwrite, where the counters return to zero and the second 
> key is accepted. A passing first test means the defect is present.
> h3. Patch
> [^CR-2-count-only-committed-deleted-keys-in-quota-repair.patch], against 
> a6332fb59879b80615b9233e953d6813d03ae7a8. It also applies to master at 
> 3a22acfaa21.
> {{countDeletedKey}} counts a key info only if {{isDeletedKeyCommitted()}} is 
> set, which is the rule the purge uses to release it. The size formula is 
> unchanged (replicated size per key info, HDDS-16176 covers that formula). The 
> function is shared by the scan of the active {{deletedTable}} and the scans 
> of the snapshot {{deletedTable}}s, so both follow the rule. The patch does 
> not change which entries carry the flag.
> Covered by {{testQuotaRepairCountsOnlyCommittedDeletedKeys}} in the existing 
> {{TestQuotaRepairTask}}: an entry with the flag, an entry without it and an 
> entry that holds one key info of each kind (as a key commit writes when it 
> overwrites a key and drops uncommitted blocks) must count as two keys. 
> Without the change it fails with "expected: 2000L but was: 5000L". The 
> existing fixtures ({{putDeletedKey}} in the test and 
> {{OMRequestTestUtils.deleteKey}}) now write the flag, as a real delete of a 
> committed key does. With the change {{TestQuotaRepairTask}}, 
> {{TestOMQuotaRepairRequest}}, {{TestOMKeyPurgeRequestAndResponse}}, 
> {{TestOMDirectoriesPurgeRequestAndResponse}} and {{TestKeyDeletingService}} 
> (55 tests) and {{TestOzoneRepairShell}} on a mini cluster (3 tests) pass, 
> checkstyle is clean. With the patch the first test of the reproduction fails 
> at the counters after the repair (0 instead of 805306368), the control still 
> passes.
> Found by code review of the OM key deletion service and key purge paths, as 
> part of the TLA+ verification effort under HDDS-15926, on commit 
> a6332fb59879b80615b9233e953d6813d03ae7a8. 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