Siyao Meng created HDDS-16894:
---------------------------------

             Summary: OneReplicaPipelineSafeModeRule still counts reports of 
pipelines closed during safe mode after its refresh lowers the threshold
                 Key: HDDS-16894
                 URL: https://issues.apache.org/jira/browse/HDDS-16894
             Project: Apache Ozone
          Issue Type: Bug
            Reporter: Siyao Meng
         Attachments: 
MC-3-drop-closed-pipeline-reports-on-one-replica-rule-refresh.patch, 
TestBugMC3OneReplicaRuleCountsClosedPipeline.java

h3. Mechanism
While the rule is not met, {{OneReplicaPipelineSafeModeRule.refresh(false)}} 
calls {{initializeRule(true)}}, which rebuilds {{oldPipelineIDSet}} and 
{{thresholdCount}} from the RATIS/THREE pipelines that are open now. 
{{currentReportedPipelineCount}} and {{reportedPipelineIDSet}} are kept as they 
are, so reports of pipelines that have closed since still count towards a 
threshold that only covers open pipelines. With R reported pipelines of which C 
have closed, the rule passes once R reaches ceil(0.9 x open), so it covers C 
fewer open pipelines than configured. Once {{SCMSafeModeManager}} records the 
rule as validated it is never checked again.

The class Javadoc says the rule ensures at least one reported datanode per open 
pipeline, so that open containers have a replica to read when SCM leaves safe 
mode. The container rules only count CLOSED and QUASI_CLOSED containers.

h3. Trigger
# SCM starts in safe mode with open RATIS/THREE pipelines, and the datanodes of 
some of them report.
# One of the reported pipelines is closed while SCM is in safe mode: by 
{{StaleNodeHandler}} or {{DeadNodeHandler}} after a registered datanode goes 
silent, by a Ratis pipeline action from a datanode, or by {{ozone admin 
pipeline close}}.
# The periodic refresh ({{hdds.scm.safemode.rule.refresh.interval}}, default 
5s) runs. In releases before the periodic refresh thread, the refresh runs on 
{{SCMStateMachine.applyTransaction}} in safe mode, so the transaction that 
closes the pipeline triggers it (code reading, not run on a release).

h3. Impact
* Smallest case, run: two open pipelines p1 and p2 (threshold 2). Only p1's 
three datanodes register and report, and p1 is reported healthy. p1 is closed. 
The refresh sets the threshold to 1 with the count still 1, the rule validates 
with 0 of 1 open pipelines reported, and in the same refresh cycle SCM leaves 
safe mode, because every other rule already passes (3 datanodes registered, one 
healthy pipeline, no closed containers).
* SCM leaves safe mode only if the other rules pass. If the unreported 
datanodes hold closed containers with keys, the container rule still holds SCM 
in safe mode unless those containers are under 1% of the total. The rule's own 
bound already allows 10% of open pipelines to stay unreported. The bug loosens 
that by one pipeline per reported pipeline closed during safe mode.
* After an early exit, {{getContainerWithPipeline}} no longer refuses open 
containers without reported replicas, so reads of those containers go to 
datanodes that have not reported until they come back, and block allocation can 
pick the unreported open pipeline (code reading, not run). No data loss is 
expected.
* The refresh path dates from HDDS-5263 (1.2.0). Related: HDDS-11844 proposes 
changing what this rule requires before SCM leaves safe mode. This report and 
patch keep the current requirement.

h3. Reproduction
[^TestBugMC3OneReplicaRuleCountsClosedPipeline.java] 
({{hadoop-hdds/server-scm}}) runs the smallest case above with the real 
{{PipelineManagerImpl}}, the real {{SCMSafeModeManager}} with all its rules and 
its refresh thread (interval lowered to 100ms), real registration, pipeline 
report and open pipeline events, and {{PipelineManagerImpl.closePipeline}}. On 
the unmodified commit it fails every time with {{SCM left safe mode with 0 of 1 
open pipelines reported}}, and the log shows {{OneReplicaPipelineSafeModeRule 
rule is successfully validated}} followed by {{SCM exiting safe mode.}} With 
the patch it passes. Not run on a real cluster.

h3. Patch
[^MC-3-drop-closed-pipeline-reports-on-one-replica-rule-refresh.patch], against 
b0aa6475b7856d2c7f467dd3db12b9a1dd116f63. It also applies to master at 
6818707698c.

On refresh, {{initializeRule(true)}} keeps only the reported pipelines that are 
still open ({{reportedPipelineIDSet.retainAll(oldPipelineIDSet)}}) and lowers 
{{currentReportedPipelineCount}} by the number removed. Reports of pipelines 
that are still open are kept. The count is lowered rather than set to the set 
size because {{cleanup()}} empties the set after the rule has passed. From the 
code, this also covers the report free validation path 
({{updateReportedPipelineSet}}), which uses the same set and count. That path 
is not tested. Nothing changes when no reported pipeline closes during safe 
mode. The metric {{currentPipelinesWithAtleastOneReplicaReportedCount}} is a 
counter and still includes the closed pipelines.

Covered by {{testRefreshDropsReportsOfPipelinesNoLongerOpen}} in the existing 
{{TestOneReplicaPipelineSafeModeRule}}: three open pipelines, two report, one 
of those closes, and after the refresh the rule expects threshold 2 and count 1 
and is not met. A report from the third pipeline then satisfies it. Without the 
change it fails ({{expected: <1> but was: <2>}}). With it, the 
{{org.apache.hadoop.hdds.scm.safemode}} unit tests (75) and 
{{TestSCMSafeModeWithPipelineRules}} on a mini cluster (2) pass, and checkstyle 
is clean.

Found by TLA+ model checking and code review of the SCM safe mode rules under 
HDDS-15926, on commit b0aa6475b7856d2c7f467dd3db12b9a1dd116f63. 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