Skip to content

HDDS-15791. EC reconstructed RECOVERING container while still idle can be deleted by SCM and recreated as new partial OPEN container#10702

Open
aswinshakil wants to merge 2 commits into
apache:masterfrom
aswinshakil:HDDS-15791
Open

HDDS-15791. EC reconstructed RECOVERING container while still idle can be deleted by SCM and recreated as new partial OPEN container#10702
aswinshakil wants to merge 2 commits into
apache:masterfrom
aswinshakil:HDDS-15791

Conversation

@aswinshakil

Copy link
Copy Markdown
Member

What changes were proposed in this pull request?

During EC offline reconstruction, the coordinator creates a RECOVERING replica on a spare DataNode and writes blocks over time. If reconstruction stalls (e.g. slow block-group processing) longer than ozone.recovering.container.timeout (~20m, measured from creation, not last write), the DN scrubber marks the replica UNHEALTHY and SCM force-deletes it.

The coordinator may still be running. The next WriteChunk finds no container; HddsDispatcher auto-creates a new OPEN container instead of failing. The coordinator continues and closes that replica shortly after, leaving a partial container (fewer blocks/chunks than the reference) that SCM can accept as CLOSED — silent data loss.

This PR fixes the issue my not allowing create container during WriteChunk for RECOVERING containers. Also update the recovering container timeout based on the last write to the container.

What is the link to the Apache JIRA

HDDS-15791

How was this patch tested?

Added Unit Tests

…n be deleted by SCM and recreated as new partial OPEN container
@aswinshakil aswinshakil requested a review from devmadhuu July 9, 2026 22:14

@devmadhuu devmadhuu left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @aswinshakil for your patch. Kindly have a look into some comments.

Comment thread hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/OzoneConsts.java Outdated
}

@Override
protected ChunkInfo.Builder decorateChunkInfo(ChunkInfo.Builder builder) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think, this might break the normal EC write as well because ECBlockOutputStream is used by both the reconstruction coordinator (ECReconstructionCoordinator) and the normal client write path (ECBlockOutputStreamEntry). So we might need to have this flag CONTAINER_CREATABLE_FALSE only for reconstruction path.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated to add overloaded API for reconstruction.

// current impl does not support caching both
ChunkInfo chunkInfo = ChunkInfo.newBuilder()
ChunkInfo chunkInfo = decorateChunkInfo(ChunkInfo.newBuilder()
.setChunkName(blockID.get().getLocalID() + "_chunk_" + ++chunkIndex)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

decorateChunkInfo method will fall into both normal EC write path and reconstruction path. Kindly check this part.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated this.

/**
* @return true if the DataNode may auto-create a missing container for this WriteChunk request
*/
public static boolean isContainerCreatable(ContainerCommandRequestProto request) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This flag is currently only restricted to check writeChunk metadata only, but missing PutBlock / PutSmallFilecheck. In a partial/padding stripe, non-writing nodes do create containers by an empty PutBlock, so in normal EC writepath, it is fine. But in case of reconstruction path, a slight edge case where PutBlock
might land up on a force-deleted RECOVERING container can still auto-create it as OPEN

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added for PutBlock as well.

*/
public void updateRecoveringContainerTimeout(long containerId) {
Preconditions.checkState(containerId >= 0, "Container Id cannot be negative.");
removeRecoveringContainer(containerId);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could be a performance issue, earlier removeRecoveringContainer was called when container should be marked as CLOSE, but now we are calling this a very hot path for every chunk write. Number of RECOVERING containers itself may be less, but number of chunks in lot of RECOVERING containers will add up this method call multiple times and this removeRecoveringContainer method is iterating all containers by value of hashmap entry. One possible solution: How about storing the recovering containers using containerId as key in hashmap and deadline time as value, then it will be O(1) operation

request);
}

maybeUpdateRecoveringContainerTimeout(kvContainer);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There could be a possibility of race condition still when getTasks check here if deadline crossed and then adds to backgroundTaskQueue, but by the time queue picks up and task call markContainerUnhealthy, a writeChunk call of this method may adds a fresh deadline entry but the already-queued task still marks the container UNHEALTHY — and leaves a stale entry for a now-UNHEALTHY container.

@aswinshakil aswinshakil marked this pull request as ready for review July 10, 2026 21:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants