Repository navigation
HDDS-17360. Datanode asks SCM to close an open EC container when it loses the container's replica - #11727
HDDS-17360. Datanode asks SCM to close an open EC container when it loses the container's replica#11727yandrey321 wants to merge 4 commits into
Conversation
…oses the container's replica Generated-by: Claude Code (Claude Opus 5.5)
smengcl
left a comment
There was a problem hiding this comment.
+1. Thanks @yandrey321 for the patch.
jojochuang
left a comment
There was a problem hiding this comment.
The Ratis and EC paths address the same allocation problem at different levels:
| Step | Ratis | EC with this PR |
|---|---|---|
| Volume fails | Replica is removed locally, marked missing, and omitted from the full container report | Same, plus a CLOSE action for each affected OPEN EC container, followed by a heartbeat |
| Subsequent write | Goes through the Ratis state machine and fails on the missing replica | Goes through gRPC and returns CONTAINER_MISSING |
| Failure handling | State machine becomes unhealthy; DataNode requests pipeline close | Dispatcher re-adds a container-close action; the first such failure per container triggers an immediate heartbeat |
| SCM response | Closes the pipeline and finalizes its open containers | Finalizes the affected container, stopping further allocation; the EC pipeline is closed later during allocation |
| Replica closing | Normal Ratis close handling, potentially involving QUASI_CLOSED |
Force-close, avoiding QUASI_CLOSED |
| Repair | Ratis replica recovery/replication handling | Missing EC index becomes eligible for reconstruction after closure |
One timing distinction worth preserving in the description: the Ratis missing-container path depends on a subsequent write encountering the failure. Volume failure alone does not immediately close an idle Ratis pipeline. This patch's EC volume-failure hook acts even without further writes.
Could we also extend the integration test through the remaining recovery steps? Currently, waiting for the container to leave OPEN proves that allocation stops, and reading the existing key verifies availability with surviving fragments. It does not establish that closure completes or reconstruction occurs.
Waiting for SCM's container state to reach CLOSED, then verifying restoration of all required EC replica indexes, would cover those claims. The test may need a spare DataNode to satisfy reconstruction placement constraints.
Done. The integration test now waits for SCM to report the container CLOSED, and then until every RS(3,2) index (1–5) has a CLOSED replica again, before reading the key a second time. The cluster has 6 datanodes, so the reconstruction target doesn't have to be the datanode that lost the replica. The close-container wait and the replication manager and report intervals are shortened to keep the test at about 20 s. In the test log the replication manager sends a reconstructECContainersCommand and the datanode completes it about 5 s after the volume failure. |
|
I have a question here: When volume failed, why it is not triggering FCR? According to https://issues.apache.org/jira/browse/HDDS-8448, it should trigger FCR right. Upon processing FCR, aren't we closing the open containers for replication? |
It does trigger the FCR:
For Ratis the close doesn't come from the FCR either. The next write to the lost container fails in the Ratis state machine, and the datanode asks SCM to close the pipeline. EC writes go over gRPC and have no such path, so SCM kept allocating the container, and every write to the missing index failed with The integration test shows this. With the volume-failure hook removed, An alternative would be for SCM to close an OPEN EC container whose replica count falls below the required nodes. But SCM can't tell a lost replica from a newly allocated container whose replicas haven't been reported yet, so it could close new containers by mistake. Only the datanode knows that it lost the replica, so it reports it, the same way the Ratis path does. |
|
I screened all 324 unresolved issues returned by the Jira filter for
These are existing adjacent defects, not regressions introduced by this PR. HDDS-17267 is the most important companion fix for making closure without subsequent writes dependable: the volume-failure hook queues the CLOSE action once and removes the replica locally; a failed heartbeat or SCM re-registration response can discard the action. A later failed EC write re-adds it, but an idle container can remain OPEN. Failure/re-registration coverage would help establish the retry behavior. The earlier recovery-test concern has been addressed: the integration test now waits for CLOSED state and restoration of all five EC indexes. On head Generated-by: Codex (GPT-6) |
|
@jojochuang I'll pick up these Specula JIRAs and fix them as follow ups. |
Co-authored-by: Codex (GPT-6) Change-Id: Iedb9578a1589a9b25b855df381a148ab9913fc38
Co-authored-by: Codex (GPT-6) Change-Id: If7d406e019f499fb2e1f6873be957d70d52129c1
jojochuang
left a comment
There was a problem hiding this comment.
The EC write detection now has an explanatory comment, and master has been merged. Local validation on JDK 21 passed: TestHddsDispatcher (18 tests), TestVolumeSetDiskChecks (6 tests), TestECContainerCloseOnVolumeFailure (1 integration test), and repository checkstyle. No blocking findings from the source review. CI on this updated head is not yet confirmed green.
Generated-by: Codex (GPT-6)
What changes were proposed in this pull request?
Problem. When a datanode loses the replica of an open EC container, for example because its volume failed, nothing closes the container, and SCM keeps allocating it:
CONTAINER_MISSING("has been lost and cannot be recreated");OpenContainerHandleronly checks that each remaining replica is OPEN, so an open EC container with a missing index counts as healthy;Ratis containers on the same volume are closed within seconds: the failed write makes the Ratis state machine unhealthy, and the datanode asks SCM to close the pipeline. EC writes go through the gRPC path, which has no such handling.
Implementation idea. The datanode asks SCM to close the container, through the existing
ContainerActionCLOSEin the heartbeat, in two places:
ContainerSet.handleVolumeFailures), for each OPEN EC container on it (replica index > 0).The existing code already triggers a heartbeat after the full container report, so SCM closes the container
within seconds, whether or not anyone writes to it.
CONTAINER_MISSING(HddsDispatcher), if it is an ECwrite (replica index > 0 on WriteChunk or PutBlock). Only the first such write per container triggers an immediate
heartbeat; later ones re-add the action, deduplicated while pending.
SCM's existing path does the rest:
ContainerActionsHandlerfiresCLOSE_CONTAINER;is closed at the next allocation;
Key decisions.
whose replicas haven't been created yet is never closed by mistake. That risk would come with an SCM-side check on
replica counts.
handles every CLOSE
action the same way, and the datanode log says why.
lost with a failed heartbeat, SCM failover, and containers that went missing in other ways.
Side effects.
for containers that are no longer OPEN, so repeats and reports from several datanodes are harmless.
missing index gets reconstructed sooner.
Generated-by: Claude Code (Claude Opus 5.5)
What is the link to the Apache JIRA
https://issues.apache.org/jira/browse/HDDS-17360
How was this patch tested?
Integration and unit tests.