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

Siyao Meng updated HDDS-17060:
------------------------------
    Attachment: TestBugMC8ResurrectionNotMirrored.java

> Recon keeps a container CLOSED after SCM moves it from DELETING or DELETED 
> back to QUASI_CLOSED
> -----------------------------------------------------------------------------------------------
>
>                 Key: HDDS-17060
>                 URL: https://issues.apache.org/jira/browse/HDDS-17060
>             Project: Apache Ozone
>          Issue Type: Bug
>            Reporter: Siyao Meng
>            Priority: Minor
>         Attachments: MC-8-follow-scm-from-closed-back-to-quasi-closed.patch, 
> TestBugMC8ResurrectionNotMirrored.java
>
>
> h3. Mechanism
> SCM's replication manager moves an empty CLOSED container to DELETING and, 
> once no replica is left, to DELETED. If a datanode then reports a non-empty 
> Ratis replica that is OPEN, CLOSING, UNHEALTHY, or QUASI_CLOSED with a bcsId 
> above the container's, 
> {{AbstractContainerReportHandler.updateContainerState}} moves the container 
> back to QUASI_CLOSED (HDDS-14684, which extended HDDS-12421). Recon does not 
> follow when it still has the container CLOSED at that point:
> * {{ReconStorageContainerSyncHelper}} never copies DELETING, and copies 
> DELETED only from SCM's current DELETED list, which no longer contains the 
> container.
> * Recon's report handler runs the same {{updateContainerState}}, which does 
> nothing for a CLOSED container.
> * {{ReconStorageContainerSyncHelper.reconcileToQuasiClosed}} handles a 
> container that SCM lists as QUASI_CLOSED only when Recon has it DELETED, OPEN 
> or CLOSING. For CLOSED it logs at debug level and skips it, on every cycle.
> The skip is deliberate 
> ({{TestReconSCMContainerSyncIntegration.doesNotOverwriteContainerAlreadyClosedInRecon}}):
>  Recon can be ahead of SCM when it processed a CLOSED replica that SCM has 
> not processed yet. But SCM never moves a CLOSED container to QUASI_CLOSED 
> directly, only through DELETING or DELETED, so in this case SCM is ahead.
> h3. Trigger
> # An empty CLOSED container; a datanode that holds a stale non-empty copy is 
> away.
> # SCM's replication manager deletes the empty replicas and moves the 
> container to DELETING (then DELETED once the deletes are confirmed).
> # The datanode comes back and reports its replica (UNHEALTHY in the 
> reproduction) before Recon's next sync has run its DELETED pass. SCM moves 
> the container back to QUASI_CLOSED.
> The window runs from SCM's DELETE transition until Recon's next sync cycle 
> has run its DELETED pass 
> ({{ozone.recon.scm.container.sync.task.interval.delay}}, default 6h); whether 
> SCM is in DELETING or already in DELETED does not matter. If Recon has 
> already synced DELETED, its own report handler moves the container back to 
> QUASI_CLOSED together with SCM. If SCM later closes the container (a CLOSED 
> replica appears) or deletes it again, the CLOSED or DELETED pass catches up. 
> With only an UNHEALTHY replica left, SCM keeps it QUASI_CLOSED.
> h3. Impact
> Recon shows the container as CLOSED and leaves it out of its QUASI_CLOSED 
> list and count ({{ContainerEndpoint.getQuasiClosedContainers}}) for as long 
> as SCM keeps it QUASI_CLOSED. Recon's QUASI_CLOSED specific health states 
> cannot apply to it (argued from the code, not run). SCM and datanode state 
> are not affected. The same code is in 2.2.0 and 2.2.1. Recon replaces its SCM 
> DB from a snapshot only at startup with a large count difference or on an 
> admin request.
> h3. Reproduction
> PASS, deterministic, unmodified source. 
> [^TestBugMC8ResurrectionNotMirrored.java] ({{hadoop-ozone/recon}}) runs a 
> real SCM {{ContainerManagerImpl}} and SCM 
> {{IncrementalContainerReportHandler}} next to the real 
> {{ReconContainerManager}}, {{ReconIncrementalContainerReportHandler}} and 
> {{ReconStorageContainerSyncHelper}}. The SCM client that Recon calls answers 
> from the SCM container manager. Every datanode report goes to both sides; the 
> only step applied directly is the {{DELETE}} (and {{CLEANUP}}) transition the 
> replication manager makes. Two tests end, after six sync cycles and a 
> repeated report, with SCM QUASI_CLOSED and Recon CLOSED: one with the report 
> arriving while SCM is DELETING, one while SCM is already DELETED but before 
> Recon's next sync. A control test where Recon synced DELETED first shows 
> Recon following SCM. A passing test means the defect is present.
> h3. Suggested fix
> A rule that waits for two consecutive sync cycles is not needed. When Recon 
> is ahead, it got there by closing the container on a CLOSED replica, which it 
> records. So Recon can follow SCM back to QUASI_CLOSED whenever SCM lists the 
> container QUASI_CLOSED and Recon knows no CLOSED replica of it. This is a 
> heuristic with bounded, self healing errors: if Recon was ahead and has lost 
> its CLOSED replica record (for example the node died), it follows SCM to 
> QUASI_CLOSED and closes again through the CLOSED pass or the next CLOSED 
> replica report once SCM closes the container; a stale CLOSED replica record 
> delays the move until a report removes it.
> h3. Patch
> [^MC-8-follow-scm-from-closed-back-to-quasi-closed.patch], against 
> 916aa1d9949cbb10f2750a40c8704340893131a2. It also applies to master at 
> 62d982ff2d9.
> In {{reconcileToQuasiClosed}}, a container that Recon has CLOSED and SCM 
> lists as QUASI_CLOSED is moved to QUASI_CLOSED when none of its replicas in 
> Recon is CLOSED. It uses the same transitions SCM went through ({{DELETE}}, 
> then {{transitionDeletingOrDeletedToTargetState}}), so the record and its 
> replicas are kept. A container with a CLOSED replica is still skipped as 
> before.
> Covered by the new {{followsScmBackToQuasiClosedWhenReconHasNoClosedReplica}} 
> in {{TestReconSCMContainerSyncIntegration}}; 
> {{doesNotOverwriteContainerAlreadyClosedInRecon}} now gives Recon the CLOSED 
> replica that makes it ahead of SCM, and still expects CLOSED. Without the 
> change the new test fails with Recon CLOSED; with it the Recon {{scm}} 
> package tests pass and checkstyle is clean. With the patch the two defect 
> tests of the reproduction fail because Recon ends QUASI_CLOSED, and the 
> control still passes.
> Found by TLA+ model checking and code review of the datanode container report 
> and Recon container tracking paths under HDDS-15926, on commit 
> 916aa1d9949cbb10f2750a40c8704340893131a2. 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