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]

Reply via email to