Siyao Meng created HDDS-16142:
---------------------------------

             Summary: SCM deleted block transaction summary can be double 
counted after a Ratis submit timeout
                 Key: HDDS-16142
                 URL: https://issues.apache.org/jira/browse/HDDS-16142
             Project: Apache Ozone
          Issue Type: Bug
            Reporter: Siyao Meng


The volatile deleted-block transaction summary in 
{{SCMDeletedBlockTransactionStatusManager}} (the {{totalTxCount}}, 
{{totalBlockCount}}, {{totalBlockSize}}, {{totalReplicatedBlockSize}} counters 
surfaced by {{getDeletedBlockSummary}}) can be decremented twice for a single 
transaction, driving the summary below the set of transactions it actually 
accounts for. The undercount is persisted durably and reloaded on leader 
transfer, so it is permanent.

h3. Steps to reproduce

# Add a delete transaction so the summary is incremented and the transaction is 
queued for the durable deleted-block log.
# The Ratis submit for the add times out. {{SCMRatisServerImpl.submitRequest}} 
does {{submitClientRequestAsync(req).get(timeout)}}, which abandons the future 
without cancelling the request, so {{addTransactions}} takes the 
{{IOException}} path and rolls the summary back down, assuming the durable add 
never landed.
# The abandoned request still commits and applies afterwards, so the 
transaction is durably present in the deleted-block log even though the summary 
was reverted.
# The container later becomes terminal. {{getTransactions}} re-caches the 
transaction size and {{removeTransactions}} decrements the summary a second 
time.

After this sequence the volatile summary is at least 1 below the number of 
transactions accounted for. {{removeTransactionsFromDB(txIDs, getSummary())}} 
then persists the undercount durably, so it survives leader transfer and 
restart.

h3. Root cause

{{SCMDeletedBlockTransactionStatusManager.addTransactions}} increments the 
summary, calls {{deletedBlockLogStateManager.addTransactionsToDB(txList, 
getSummary())}}, and on {{IOException}} reverts the increment in its catch 
block on the assumption that the durable add did not happen. A Ratis submit 
timeout breaks that assumption: {{submitRequest}} abandons the client request 
future after the timeout without cancelling it, so the request can still be 
committed and applied, persisting the transaction. The now durable transaction 
is later removed normally and {{removeTransactions}} decrements the summary 
again for the same transaction, a double decrement for a single transaction.

h3. Impact

The deleted-block transaction summary is observability only. It is surfaced by 
the SCM client protocol {{getDeletedBlockSummary}}, {{ozone admin scm}}, Recon, 
and JMX metrics, and does not affect deletion correctness or 
{{getNumOfValidTransactions()}}. The consequence is a persistent, operator 
visible undercount of pending deleted-block work that survives leader transfer 
and restart. There is no data loss and no premature deletion.

h3. Relation to HDDS-13184, HDDS-15726, HDDS-14572

HDDS-13184 introduced the deleted-block summary accounting. HDDS-15726 (the 
most recent change to this file) added the {{addTransactions}} and 
{{removeTransactions}} rollback-on-DB-failure catch blocks that this bug 
exploits; it does not account for the submit-timeout-but-still-applied case. 
HDDS-14572 added the leader-transfer summary reconstruction that makes the 
undercount survive failover. None of these reports or fixes the double 
decrement.

h3. Suggested fix

Do not treat an {{IOException}} from {{addTransactionsToDB}} as proof that the 
durable mutation did not land. Prefer reconciling the summary from the 
authoritative durable state (the deleted-block log and the persisted summary) 
on the failure path and on leader transfer, rather than maintaining it purely 
through incremental increment and rollback. Alternatively, make the submit path 
settle or cancel the request so a timed-out submit cannot later commit.



--
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