This is an automated email from the ASF dual-hosted git repository.
adoroszlai pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ozone.git
The following commit(s) were added to refs/heads/master by this push:
new 45aa103c2a9 HDDS-15301. Malformed PutBlock request can mark container
UNHEALTHY (#10295)
45aa103c2a9 is described below
commit 45aa103c2a9bf26e9406e2fe9d5acddf557fd2ac
Author: Peter Lee <[email protected]>
AuthorDate: Tue May 19 15:31:03 2026 +0800
HDDS-15301. Malformed PutBlock request can mark container UNHEALTHY (#10295)
---
.../container/common/impl/HddsDispatcher.java | 1 +
.../ozone/container/keyvalue/KeyValueHandler.java | 6 ++++
.../container/common/impl/TestHddsDispatcher.java | 42 ++++++++++++++++++++++
.../TestOnDemandContainerScannerIntegration.java | 11 ++++--
4 files changed, 58 insertions(+), 2 deletions(-)
diff --git
a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/impl/HddsDispatcher.java
b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/impl/HddsDispatcher.java
index a109c02e5a1..249e58df94d 100644
---
a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/impl/HddsDispatcher.java
+++
b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/impl/HddsDispatcher.java
@@ -174,6 +174,7 @@ private boolean canIgnoreException(Result result) {
case CLOSED_CONTAINER_IO:
case DELETE_ON_OPEN_CONTAINER:
case UNSUPPORTED_REQUEST:// Blame client for sending unsupported request.
+ case MALFORMED_REQUEST:// Blame client for sending malformed request.
case CONTAINER_MISSING:
case CONTAINER_ALREADY_EXISTS:
return true;
diff --git
a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/KeyValueHandler.java
b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/KeyValueHandler.java
index 474b7458644..af7242541ab 100644
---
a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/KeyValueHandler.java
+++
b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/KeyValueHandler.java
@@ -33,6 +33,7 @@
import static
org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.Result.INVALID_ARGUMENT;
import static
org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.Result.INVALID_CONTAINER_STATE;
import static
org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.Result.IO_EXCEPTION;
+import static
org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.Result.MALFORMED_REQUEST;
import static
org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.Result.PUT_SMALL_FILE_ERROR;
import static
org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.Result.UNCLOSED_CONTAINER_IO;
import static
org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.Result.UNSUPPORTED_REQUEST;
@@ -123,6 +124,7 @@
import org.apache.hadoop.hdds.upgrade.HDDSLayoutFeature;
import org.apache.hadoop.hdds.utils.FaultInjector;
import org.apache.hadoop.hdds.utils.HddsServerUtil;
+import org.apache.hadoop.hdds.utils.db.CodecException;
import org.apache.hadoop.hdds.utils.io.RandomAccessFileChannel;
import org.apache.hadoop.ozone.OzoneConfigKeys;
import org.apache.hadoop.ozone.OzoneConsts;
@@ -685,6 +687,10 @@ ContainerCommandResponseProto handlePutBlock(
metrics.incContainerBytesStats(Type.PutBlock, numBytes);
} catch (StorageContainerException ex) {
return ContainerUtils.logAndReturnError(LOG, ex, request);
+ } catch (CodecException ex) {
+ return ContainerUtils.logAndReturnError(LOG,
+ new StorageContainerException("Malformed PutBlock request", ex,
+ MALFORMED_REQUEST), request);
} catch (IOException ex) {
return ContainerUtils.logAndReturnError(LOG,
new StorageContainerException("Put Key failed", ex, IO_EXCEPTION),
diff --git
a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/impl/TestHddsDispatcher.java
b/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/impl/TestHddsDispatcher.java
index b5d4ea10647..0f10eaf1327 100644
---
a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/impl/TestHddsDispatcher.java
+++
b/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/impl/TestHddsDispatcher.java
@@ -538,6 +538,48 @@ public void
testCreateContainerWhenAlreadyExistsDoesNotMarkUnhealthy() throws IO
}
}
+ @Test
+ public void testMalformedPutBlockDoesNotMarkContainerUnhealthy() throws
IOException {
+ String testDirPath = testDir.getPath();
+ try {
+ UUID scmId = UUID.randomUUID();
+ OzoneConfiguration conf = new OzoneConfiguration();
+ conf.set(HDDS_DATANODE_DIR_KEY, testDirPath);
+ conf.set(OzoneConfigKeys.OZONE_METADATA_DIRS, testDirPath);
+ DatanodeDetails dd = randomDatanodeDetails();
+ HddsDispatcher hddsDispatcher = createDispatcher(dd, scmId, conf);
+
+ ContainerCommandRequestProto writeChunkRequest =
+ getWriteChunkRequest(dd.getUuidString(), 1L, 1L);
+ ContainerCommandResponseProto writeChunkResponse =
+ hddsDispatcher.dispatch(writeChunkRequest, null);
+ assertEquals(ContainerProtos.Result.SUCCESS,
writeChunkResponse.getResult());
+
+ ContainerCommandRequestProto putBlockRequest =
+ ContainerTestHelper.getPutBlockRequest(writeChunkRequest);
+ ContainerProtos.BlockData malformedBlockData =
+ putBlockRequest.getPutBlock().getBlockData().toBuilder()
+ .setSize(putBlockRequest.getPutBlock().getBlockData().getSize()
+ 1)
+ .build();
+ ContainerCommandRequestProto malformedPutBlockRequest =
+ putBlockRequest.toBuilder()
+ .setPutBlock(putBlockRequest.getPutBlock().toBuilder()
+ .setBlockData(malformedBlockData))
+ .build();
+
+ ContainerCommandResponseProto response =
+ hddsDispatcher.dispatch(malformedPutBlockRequest, null);
+ assertEquals(ContainerProtos.Result.MALFORMED_REQUEST,
response.getResult());
+
+ Container container = hddsDispatcher.getContainer(1L);
+ assertNotNull(container);
+ assertTrue(container.getContainerData().isOpen());
+ assertFalse(container.getContainerData().isUnhealthy());
+ } finally {
+ ContainerMetrics.remove();
+ }
+ }
+
@Test
public void testDuplicateWriteChunkAndPutBlockRequest() throws IOException {
String testDirPath = testDir.getPath();
diff --git
a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/dn/scanner/TestOnDemandContainerScannerIntegration.java
b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/dn/scanner/TestOnDemandContainerScannerIntegration.java
index e81b3244a96..5f1b049c028 100644
---
a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/dn/scanner/TestOnDemandContainerScannerIntegration.java
+++
b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/dn/scanner/TestOnDemandContainerScannerIntegration.java
@@ -35,6 +35,7 @@
import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos;
import
org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.ContainerDataProto.State;
import org.apache.hadoop.ozone.HddsDatanodeService;
+import org.apache.hadoop.ozone.common.Checksum;
import org.apache.hadoop.ozone.container.common.interfaces.Container;
import org.apache.hadoop.ozone.container.common.interfaces.ContainerDispatcher;
import org.apache.hadoop.ozone.container.common.utils.ContainerLogger;
@@ -205,7 +206,7 @@ void testOnDemandScanTriggeredByUnhealthyContainer() throws
Exception {
.getOnDemandScanner().getMetrics();
int initialScannedCount = scannerMetrics.getNumContainersScanned();
- // Create a PutBlock request with malformed block data to trigger internal
error
+ // Create a PutBlock request for a chunk that was never written to trigger
internal error
ContainerProtos.ContainerCommandRequestProto writeFailureRequest =
ContainerProtos.ContainerCommandRequestProto.newBuilder()
.setCmdType(ContainerProtos.Type.PutBlock)
@@ -218,7 +219,13 @@ void testOnDemandScanTriggeredByUnhealthyContainer()
throws Exception {
.setLocalID(999L)
.setBlockCommitSequenceId(1)
.build())
- .setSize(1024) // Size mismatch with chunks
+ .addChunks(ContainerProtos.ChunkInfo.newBuilder()
+ .setChunkName("missing-chunk")
+ .setOffset(0)
+ .setLen(1024)
+ .setChecksumData(Checksum.getNoChecksumDataProto())
+ .build())
+ .setSize(1024)
.build())
.build())
.build();
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]