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

Siyao Meng reassigned HDDS-15826:
---------------------------------

       Assignee: Siyao Meng
    Description: 
h2. Problem

Recon serves the disk-usage ({{/du}}), file-size-distribution, and 
directory-count views by walking the NSSummary directory tree. Three code paths 
do this walk recursively:

* {{EntityHandler.getTotalFileSizeDist}}
* {{EntityHandler.getTotalDirCount}}
* {{ReconUtils.gatherSubPaths}}

Each recurses over {{NSSummary.getChildDir()}} with no protection against a 
malformed tree. If the persisted NSSummary data is corrupted so that a 
directory lists itself, or one of its ancestors, as a child, the child set 
forms a cycle. The recursion then never terminates and Recon dies with a 
{{StackOverflowError}}. On the read path this surfaces as an HTTP 500 from 
{{/du}} and can take the Recon process down. Because the corruption lives in 
persisted state, the failure repeats on every request until the data is 
rebuilt. The recursion also had no bound for a non-cyclic but pathologically 
deep tree.

h2. Fix

Convert all three walks from recursion to iterative traversal backed by an 
explicit stack and a {{visited}} set, so each object is visited (and counted) 
at most once. For a well-formed tree the results are unchanged.

Two smaller improvements ride along:

* {{gatherSubPaths}} previously fetched each node's NSSummary twice; it now 
fetches once (on pop), halving the {{getNSSummary}} lookups on large trees.
* De-duplicating silently would hide a real data problem, so each walk logs a 
single WARN per request (with path/object context) the first time it detects a 
repeated reference.

h2. Scope

Read-side hardening only. This does not prevent the corruption at write time, 
and does not add response paging or a size limit to {{/du}} (a separate 
follow-up for very large but well-formed buckets).

  was:Recon disk-usage tree walks recurse over NSSummary child directories with 
no cycle guard; a corrupted tree where a directory references itself or an 
ancestor causes infinite recursion and a StackOverflowError (HTTP 500 on /du).


> Recon /du endpoint crashes with StackOverflowError on a corrupted NSSummary 
> tree
> --------------------------------------------------------------------------------
>
>                 Key: HDDS-15826
>                 URL: https://issues.apache.org/jira/browse/HDDS-15826
>             Project: Apache Ozone
>          Issue Type: Bug
>          Components: Ozone Recon
>            Reporter: Siyao Meng
>            Assignee: Siyao Meng
>            Priority: Major
>
> h2. Problem
> Recon serves the disk-usage ({{/du}}), file-size-distribution, and 
> directory-count views by walking the NSSummary directory tree. Three code 
> paths do this walk recursively:
> * {{EntityHandler.getTotalFileSizeDist}}
> * {{EntityHandler.getTotalDirCount}}
> * {{ReconUtils.gatherSubPaths}}
> Each recurses over {{NSSummary.getChildDir()}} with no protection against a 
> malformed tree. If the persisted NSSummary data is corrupted so that a 
> directory lists itself, or one of its ancestors, as a child, the child set 
> forms a cycle. The recursion then never terminates and Recon dies with a 
> {{StackOverflowError}}. On the read path this surfaces as an HTTP 500 from 
> {{/du}} and can take the Recon process down. Because the corruption lives in 
> persisted state, the failure repeats on every request until the data is 
> rebuilt. The recursion also had no bound for a non-cyclic but pathologically 
> deep tree.
> h2. Fix
> Convert all three walks from recursion to iterative traversal backed by an 
> explicit stack and a {{visited}} set, so each object is visited (and counted) 
> at most once. For a well-formed tree the results are unchanged.
> Two smaller improvements ride along:
> * {{gatherSubPaths}} previously fetched each node's NSSummary twice; it now 
> fetches once (on pop), halving the {{getNSSummary}} lookups on large trees.
> * De-duplicating silently would hide a real data problem, so each walk logs a 
> single WARN per request (with path/object context) the first time it detects 
> a repeated reference.
> h2. Scope
> Read-side hardening only. This does not prevent the corruption at write time, 
> and does not add response paging or a size limit to {{/du}} (a separate 
> follow-up for very large but well-formed buckets).



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