From a72517bacef6160a03f1f773ef9b79eb41509337 Mon Sep 17 00:00:00 2001 From: CapMoon Date: Fri, 20 Mar 2026 11:00:50 +0800 Subject: [PATCH] HADOOP-19847. Move logAllocatedBlock out of lock in FSNamesystem.getAdditionalBlock to reduce latency --- .../hdfs/server/namenode/FSDirWriteFileOp.java | 14 ++++++++------ .../hadoop/hdfs/server/namenode/FSNamesystem.java | 7 ++++++- .../hdfs/server/namenode/TestAddBlockRetry.java | 3 ++- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSDirWriteFileOp.java b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSDirWriteFileOp.java index fa1fba631c8383..a96dfdc7d25108 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSDirWriteFileOp.java +++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSDirWriteFileOp.java @@ -67,6 +67,7 @@ import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.concurrent.atomic.AtomicReference; import static org.apache.hadoop.hdfs.server.namenode.snapshot.Snapshot.CURRENT_STATE_ID; import static org.apache.hadoop.util.Time.now; @@ -223,7 +224,7 @@ static LocatedBlock makeLocatedBlock(FSNamesystem fsn, BlockInfo blk, */ static LocatedBlock storeAllocatedBlock(FSNamesystem fsn, String src, long fileId, String clientName, ExtendedBlock previous, - DatanodeStorageInfo[] targets) throws IOException { + DatanodeStorageInfo[] targets, AtomicReference newBlockRef) throws IOException { long offset; // Run the full analysis again, since things could have changed // while chooseTarget() was executing. @@ -256,7 +257,8 @@ static LocatedBlock storeAllocatedBlock(FSNamesystem fsn, String src, // allocate new block, record block locations in INode. Block newBlock = fsn.createNewBlock(blockType); INodesInPath inodesInPath = INodesInPath.fromINode(pendingFile); - saveAllocatedBlock(fsn, src, inodesInPath, newBlock, targets, blockType); + BlockInfo newBlockInfo = saveAllocatedBlock(fsn, src, inodesInPath, newBlock, targets, blockType); + newBlockRef.set(newBlockInfo); persistNewBlock(fsn, src, pendingFile); offset = pendingFile.computeFileSize(); @@ -781,17 +783,17 @@ private static void persistNewBlock( * @param targets target datanodes where replicas of the new block is placed * @throws QuotaExceededException If addition of block exceeds space quota */ - static void saveAllocatedBlock(FSNamesystem fsn, String src, + static BlockInfo saveAllocatedBlock(FSNamesystem fsn, String src, INodesInPath inodesInPath, Block newBlock, DatanodeStorageInfo[] targets, BlockType blockType) throws IOException { assert fsn.hasWriteLock(RwLockMode.GLOBAL); BlockInfo b = addBlock(fsn.dir, src, inodesInPath, newBlock, targets, blockType); - logAllocatedBlock(src, b); DatanodeStorageInfo.incrementBlocksScheduled(targets); + return b; } - private static void logAllocatedBlock(String src, BlockInfo b) { + static void logAllocatedBlock(String src, BlockInfo b) { if (!NameNode.stateChangeLog.isInfoEnabled()) { return; } @@ -803,7 +805,7 @@ private static void logAllocatedBlock(String src, BlockInfo b) { if (uc != null) { uc.appendUCPartsConcise(sb); } - sb.append(" for " + src); + sb.append(" for ").append(src); NameNode.stateChangeLog.info(sb.toString()); } diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSNamesystem.java b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSNamesystem.java index 5938cd466846d0..a1e9f71c53bbce 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSNamesystem.java +++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSNamesystem.java @@ -182,6 +182,7 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.function.Supplier; @@ -3111,14 +3112,18 @@ LocatedBlock getAdditionalBlock( checkOperation(OperationCategory.WRITE); writeLock(RwLockMode.GLOBAL); LocatedBlock lb; + AtomicReference newBlockRef = new AtomicReference<>(); try { checkOperation(OperationCategory.WRITE); lb = FSDirWriteFileOp.storeAllocatedBlock( - this, src, fileId, clientName, previous, targets); + this, src, fileId, clientName, previous, targets, newBlockRef); } finally { writeUnlock(RwLockMode.GLOBAL, operationName); } getEditLog().logSync(); + if (newBlockRef.get() != null) { + FSDirWriteFileOp.logAllocatedBlock(src, newBlockRef.get()); + } return lb; } diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/namenode/TestAddBlockRetry.java b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/namenode/TestAddBlockRetry.java index dc0d7e3ba0f42e..3b5f85c050cb28 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/namenode/TestAddBlockRetry.java +++ b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/namenode/TestAddBlockRetry.java @@ -24,6 +24,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.IOException; import java.util.EnumSet; +import java.util.concurrent.atomic.AtomicReference; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -122,7 +123,7 @@ public void testRetryAddBlockWhileInChooseTarget() throws Exception { LocatedBlock newBlock; try { newBlock = FSDirWriteFileOp.storeAllocatedBlock(ns, src, - HdfsConstants.GRANDFATHER_INODE_ID, "clientName", null, targets); + HdfsConstants.GRANDFATHER_INODE_ID, "clientName", null, targets, new AtomicReference<>()); } finally { ns.writeUnlock(RwLockMode.GLOBAL, "testRetryAddBlockWhileInChooseTarget"); }