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

Krishna Kumar Asawa reassigned HDDS-15688:
------------------------------------------

    Assignee: Gargi Jaiswal

> DiskBalancer reverts to RUNNING when diskBalancer.info persist fails in 
> nodeStateUpdated() during decommission/maintenance
> --------------------------------------------------------------------------------------------------------------------------
>
>                 Key: HDDS-15688
>                 URL: https://issues.apache.org/jira/browse/HDDS-15688
>             Project: Apache Ozone
>          Issue Type: Bug
>          Components: Ozone Datanode
>    Affects Versions: 2.3.0
>            Reporter: Arun Sarin
>            Assignee: Gargi Jaiswal
>            Priority: Major
>         Attachments: repro-diskbalancer-decommission-persist-failure.sh, 
> repro_diskbalancer_decommission_persist_20260626_131028.txt, 
> repro_diskbalancer_decommission_persist_20260626_131028_datanode_filtered.log,
>  repro_diskbalancer_decommission_persist_20260626_131028_datanode_full.log, 
> repro_diskbalancer_decommission_persist_20260626_131028_scm_filtered.log, 
> repro_diskbalancer_decommission_persist_20260626_131028_scm_full.log
>
>
> Hi [~gargijaiswal] / [~sammichen] ,
> Flagging a safety issue in the persist-failure path added around 
> {{nodeStateUpdated()}} in {{DiskBalancerService}} 
> When a DN enters {{DECOMMISSIONING}} or {{{}ENTERING_MAINTENANCE{}}}, the 
> service correctly sets {{operationalState = PAUSED}} and calls 
> {{{}writeDiskBalancerInfoTo(){}}}. If that throws {{{}IOException{}}}, the 
> catch block reverts to {{originalServiceState}} — which is {{RUNNING}} when 
> we were trying to pause for decommission. {{getTasks()}} then keeps 
> scheduling moves on a node that is already leaving service.
> The revert-to-last-persisted-state logic makes sense for {{PAUSED → RUNNING}} 
> (resume fails → stay paused). It is unsafe for {{RUNNING → PAUSED}} (pause 
> fails → must stay paused in memory).
> [https://github.com/apache/ozone/blob/29b2ad5fcd40642c77f771128e7f0f7c4fe88e42/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/diskbalancer/DiskBalancerService.java#L853-L864]
> In production , same can happen in any of the below cases: 
> 1. Decommission during metadata volume pressure
> User decommissions a DN while the metadata disk is nearly full (RocksDB 
> container DBs, SCM heartbeat state, {{{}diskBalancer.info{}}}, etc. on the 
> same volume). The atomic write creates {{diskBalancer.info.tmp}} but the 
> rename to {{diskBalancer.info}} fails with no space. DN is already 
> {{{}DECOMMISSIONING{}}}; DiskBalancer reverts to {{RUNNING}} and may still be 
> moving containers off that node while SCM is draining it.
> 2. Datanode in Maintenance window 
> Node put into {{ENTERING_MAINTENANCE}} during a disk/hardware incident on the 
> metadata mount. Same path as decommission - pause is attempted, persist 
> fails, revert to {{{}RUNNING{}}}. Maintenance is meant to stop user I/O and 
> background work; DiskBalancer keeps running.
> 3. Race with concurrent admin action
> {{ozone admin datanode diskbalancer start}} (or stop) and decommission 
> overlap. Both paths persist via {{applyDiskBalancerInfo()}} / 
> {{{}nodeStateUpdated(){}}}. A failed write on the decommission pause path 
> still reverts to {{RUNNING}} regardless of what the admin command intended.
> h3. Repro (confirmed on master)
> Compose cluster, 5 DNs, RF=3, {{{}ozone-2.3.0-SNAPSHOT{}}}.
>  # Start DiskBalancer on IN_SERVICE DN → RPC {{RUNNING}}
>  # Break persist: {{rm -rf /data/metadata/diskBalancer.info && mkdir 
> /data/metadata/diskBalancer.info}}
>  # {{ozone admin datanode decommission <dn-ip>:19864}}
>  # DN reaches {{{}DECOMMISSIONING{}}}; DiskBalancer RPC still {{RUNNING}}
> *Automated script[To repro]:*
> *[^repro-diskbalancer-decommission-persist-failure.sh]*
> h3. Expected vs actual
> || ||Expected||Actual||
> |DN op state after decommission|{{DECOMMISSIONING}}|{{DECOMMISSIONING}} ✓|
> |DiskBalancer in-memory / RPC|{{PAUSED}}|{{RUNNING}} ✗|
> h3. Suggested fix
> On persist failure in {{{}nodeStateUpdated(){}}}:
>  * If we were pausing ({{{}operationalState == PAUSED{}}} after transition): 
> keep PAUSED in memory; log retain despite failure
>  * If we were resuming ({{{}operationalState == RUNNING{}}} after 
> transition): revert to PAUSED (current revert behavior is already safe here)



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