Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1410,7 +1410,7 @@ public ReplicaHandler append(ExtendedBlock b,
// The other reason is that an "append" is occurring to this block.

// check the validity of the parameter
if (newGS < b.getGenerationStamp()) {
if (newGS <= b.getGenerationStamp()) {
throw new IOException("The new generation stamp " + newGS +
" should be greater than the replica " + b + "'s generation stamp");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2121,6 +2121,54 @@ public void delayGetMetaDataInputStream() {
}
}

/**
* HDFS-17850: Verify that append() rejects a newGS equal to the replica's
* current generation stamp. A client bug that reuses the same GS should
* fail immediately rather than silently corrupting the replica state.
*/
@Test
@Timeout(value = 60)
public void testAppendRejectsSameGenerationStamp() throws Exception {
MiniDFSCluster cluster = new MiniDFSCluster.Builder(conf)
.numDataNodes(1).build();
try {
cluster.waitActive();
BlockReaderTestUtil util = new BlockReaderTestUtil(cluster,
new HdfsConfiguration(conf));
Path path = new Path("/testAppendSameGS");
util.writeFile(path, 1);
String bpid = cluster.getNameNode().getNamesystem().getBlockPoolId();
DataNode dn = cluster.getDataNodes().get(0);
FsDatasetImpl dnFSDataset = (FsDatasetImpl) dn.getFSDataset();
LocatedBlock blk = util.getFileBlocks(path, 512).get(0);
ExtendedBlock block = blk.getBlock();
long currentGS = block.getGenerationStamp();

// newGS == currentGS must be rejected (HDFS-17850 fix)
try {
dnFSDataset.append(block, currentGS, block.getNumBytes());
fail("Expected IOException when newGS equals current generation stamp");
} catch (IOException e) {
assertTrue(e.getMessage().contains("should be greater than"),
"Unexpected error message: " + e.getMessage());
}

// newGS < currentGS must also be rejected (pre-existing behaviour)
try {
dnFSDataset.append(block, currentGS - 1, block.getNumBytes());
fail("Expected IOException when newGS is less than current generation stamp");
} catch (IOException e) {
assertTrue(e.getMessage().contains("should be greater than"),
"Unexpected error message: " + e.getMessage());
}

// newGS > currentGS must succeed
dnFSDataset.append(block, currentGS + 1, block.getNumBytes());
} finally {
cluster.shutdown();
}
}

@Test
@Timeout(value = 30)
public void testAppend() {
Expand Down