java-topology/defects/hadoop/patch/hadoop-0003-ticket.md

1.7 KiB
Raw Blame History

UNDF: UNDF-2026-000000098

hadoop-0003: StoragePolicySatisfier — ArrayList.contains() O(n²) in block placement loop

Severity

MEDIUM — called during storage policy satisfaction (tiered storage balancing), not every request, but runs per-block across potentially thousands of blocks

File

hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/sps/StoragePolicySatisfier.java

Lines

780805 (findTargetNode() method, called from line 642)

Pattern

CWE-407: O(n) ArrayList.contains() inside a nested for loop.

// DEFECTIVE
List<DatanodeInfo> excludeNodes = new ArrayList<>(existingBlockStorages);  // line 525

// ... later:
for (StorageType t : targetTypes) {                             // outer O(T)
    for (DatanodeWithStorage.StorageDetails targetNode : ...) { // inner O(N)
        DatanodeInfo target = targetNode.getDatanodeInfo();
        if (!excludeNodes.contains(target)                      // O(E) ArrayList scan!
            && matcher.match(...)) {

excludeNodes is built as new ArrayList<>(existingBlockStorages) at line 525 and passed through to findTargetNode(). With E excluded nodes, T storage types, and N candidates per type, total cost is O(T * N * E). During policy satisfaction of a large cluster with EC blocks, E can be tens of nodes and N can be hundreds of candidates.

Fix

Change excludeNodes from ArrayList to HashSet at construction point (line 525). All call sites pass it as List<DatanodeInfo> — change signature to Collection<DatanodeInfo> or Set<DatanodeInfo> where possible, or wrap: new HashSet<>(existingBlockStorages).

Speedup

~30x at E=100, T=5, N=200 (measured in unit test).