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

Siyao Meng updated HDDS-16796:
------------------------------
    Attachment: CR-3-set-committed-deleted-flag-authoritatively.patch

> deletedTable entries inherit the committed flag from their key info, so the 
> purge can release pending deletion usage that was never added
> -----------------------------------------------------------------------------------------------------------------------------------------
>
>                 Key: HDDS-16796
>                 URL: https://issues.apache.org/jira/browse/HDDS-16796
>             Project: Apache Ozone
>          Issue Type: Bug
>            Reporter: Siyao Meng
>            Priority: Major
>         Attachments: CR-3-set-committed-deleted-flag-authoritatively.patch
>
>
> h3. Mechanism
> A {{deletedTable}} entry carries a flag that records whether the replicated 
> size of that key info and one namespace unit were added to the bucket's 
> {{snapshotUsedBytes}} and {{snapshotUsedNamespace}} when the key left the key 
> table ({{OmKeyInfo.isDeletedKeyCommitted}}, set with 
> {{OmKeyInfo.withCommittedKeyDeletedFlag}}). When the entry is purged, 
> {{KeyManagerImpl.getPendingDeletionKeys}}, {{KeyDeletingService}} and 
> {{OMKeyPurgeRequest.updateBucketSize}} subtract the size and the namespace 
> unit only for key infos that carry the flag (HDDS-13756).
> The flag is part of the {{OmKeyInfo}} that each producer moves into 
> {{deletedTable}}, and the producers do not all set it from their own intent. 
> The shared mover {{OmUtils.prepareKeyForDelete}} keeps whatever the key info 
> it is handed carries, and two sites that build the entry without that mover, 
> {{S3MultipartUploadCompleteResponse}} for the key and the unused parts of a 
> completed upload and {{OMKeyRequest.wrapUncommittedBlocksAsPseudoKey}} for 
> the pseudo key of uncommitted blocks, do not clear it either. Only 
> {{AbstractOMKeyDeleteResponse}} decides the flag for the entry it writes.
> A producer that does not add a key's size to the pending deletion counters 
> can therefore write an entry that the purge treats as charged, and the purge 
> then subtracts a size and a namespace unit that were never added. The 
> counters have no lower bound, so they go negative and 
> {{OmBucketInfo.getTotalBucketSpace}} and {{getTotalBucketNamespace}}, which 
> the quota checks in {{OMKeyRequest}} compare against, fall below the bucket's 
> real usage. Nothing recomputes them automatically.
> h3. Trigger
> # A key info that already carries the committed flag value is moved into 
> {{deletedTable}} by a producer that does not add its size to the bucket's 
> pending deletion counters. Run through the shared mover and through 
> {{S3MultipartUploadCompleteResponse}} (an unused part of a completed upload).
> # {{KeyDeletingService}} purges the entry.
> The other producers that route through the shared mover (multipart abort, an 
> overwritten or aborted part, {{FSORepairTool}}) and the uncommitted blocks 
> pseudo key reach the same state, from code reading, not run.
> By history, not run on older code: the flag and the pending deletion counters 
> arrived together with HDDS-13756, so the inheritance is present from the 
> 2.1.0 release tag onwards. 2.0.0 has neither.
> h3. Impact
> * After the purge the bucket's {{snapshotUsedBytes}} and 
> {{snapshotUsedNamespace}} are lower by the size and the namespace unit of an 
> entry that never added them, and go negative for a bucket with nothing else 
> pending. In the regression run of the shared mover the entry comes back with 
> the flag cleared, and the purge therefore leaves the counters alone.
> * The charged usage the quota checks read is then below the bucket's real 
> usage, so the bucket admits more than its space and namespace quota allow.
> * No key and no data is affected, and the counters stay wrong until an 
> operator starts a quota repair ({{ozone repair om quota start}}), which 
> recomputes them (code reading, not run).
> h3. Reproduction
> The two regression tests in the attached patch cover it and fail on 
> unmodified source:
> * {{TestOmUtils.prepareKeyForDeleteSetsCommittedFlagAuthoritatively}} 
> ({{hadoop-ozone/common}}): the shared mover must decide the flag of the entry 
> it builds, for the three argument form and for both values of the new 
> argument. Without the change the three argument form and the {{false}} form 
> both return a flagged entry.
> * 
> {{TestS3MultipartUploadCompleteResponse.testCompleteDoesNotInheritClientCommittedFlag}}
>  ({{hadoop-ozone/ozone-manager}}, also in the inherited {{...WithFSO}}): an 
> unused part of a completed upload must not produce a flagged entry. Without 
> the change it fails with {{expected: <false> but was: <true>}}.
> h3. Patch
> [^CR-3-set-committed-deleted-flag-authoritatively.patch], against 
> a6332fb59879b80615b9233e953d6813d03ae7a8. It also applies to master at 
> fa7b58e3901.
> {{OmUtils.prepareKeyForDelete}} takes the flag as a new argument and sets it 
> on the entry it builds instead of keeping the value of the key info it is 
> handed. The three argument form stays and passes {{false}}, so a producer 
> that does not charge the counters needs no change. The producers that do 
> charge them pass their intent: {{AbstractOMKeyDeleteResponse}} passes the 
> value it already computed (both of its overloads), 
> {{OMDirectoriesPurgeResponseWithFSO}} passes {{true}} for the sub files of a 
> purged directory instead of flagging the key info beforehand. The two sites 
> that build the entry without the mover clear the flag explicitly: 
> {{S3MultipartUploadCompleteResponse}} for the key and the unused parts it 
> moves, and {{OMKeyRequest.wrapUncommittedBlocksAsPseudoKey}} for the pseudo 
> key. {{OMKeyCommitRequest}}, which flags the version it overwrites after the 
> move, is unchanged.
> So every {{deletedTable}} entry is flagged by the code that writes it, and an 
> entry whose source key info carried a value is written with the flag the 
> producer intends. Nothing changes for an entry the OM itself flagged, there 
> is no wire or protocol change, and entries already in {{deletedTable}} are 
> read as before.
> With the patch the key delete and purge response suites, the directories 
> purge and key purge request suites, the quota repair task suite, the key and 
> part commit response suites, the multipart abort, commit part and complete 
> response suites and {{TestKeyDeletingService}} pass, and checkstyle on 
> {{hadoop-ozone/common}} and {{hadoop-ozone/ozone-manager}} is clean.
> One coordination note with HDDS-16793, which is a different defect in the 
> same accounting and whose patch is also open for review: that patch pre-sets 
> the flag on the shared test fixture {{OMRequestTestUtils.deleteKey}}, which 
> this change then overrides, so {{TestQuotaRepairTask}} has two failures with 
> both applied. Whichever lands second carries the fixture line over to the 
> four argument form of the mover. Verified by running both.
> 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. Related but not 
> duplicates: HDDS-13756 (introduced the flag and the pending deletion 
> counters), HDDS-16793 (quota repair counts entries the purge never releases), 
> HDDS-16176 (the size formula in the same release path). 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