You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ozone.apache.org by ch...@apache.org on 2026/10/22 11:08:53 UTC
(ozone) branch master updated: HDDS-17024. Failed .container write during mark for close rolls the container back to OPEN without its space reservation (#11622)
This is an automated email from the ASF dual-hosted git repository.
chungen0126 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 f39f7ce8b4c HDDS-17024. Failed .container write during mark for close rolls the container back to OPEN without its space reservation (#11622)
f39f7ce8b4c is described below
commit f39f7ce8b4c08b40c868332d60b982b29cb0e5a1
Author: Gargi Jaiswal <13...@users.noreply.github.com>
AuthorDate: Thu Oct 22 16:38:47 2026 +0530
HDDS-17024. Failed .container write during mark for close rolls the container back to OPEN without its space reservation (#11622)
---
.../container/keyvalue/KeyValueContainer.java | 18 +++++++++++---
.../container/keyvalue/TestKeyValueContainer.java | 28 ++++++++++++++++++++++
2 files changed, 43 insertions(+), 3 deletions(-)
diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/KeyValueContainer.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/KeyValueContainer.java
index 06a73b33373..fd016f3078b 100644
--- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/KeyValueContainer.java
+++ b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/KeyValueContainer.java
@@ -480,16 +480,24 @@ private void updateContainerState(State newState) throws StorageContainerExcepti
}
/**
- *
+ * Applies {@code update} to the in-memory container data and persists it to the .container file.
* Must be invoked with the writeLock held.
+ * <p>
+ * The rollback only covers a failed write of the .container file: {@code update} is a {@link Runnable}, so it
+ * cannot throw a {@link StorageContainerException}, and only {@code updateContainerFile} can. When the write
+ * fails, the in-memory change has already been applied, so the previous state is restored to match the file on
+ * disk, unless the container became UNHEALTHY in the meantime. Leaving OPEN releases the space reserved for the
+ * container, and restoring OPEN does not reserve it again, so the reservation
+ * is restored explicitly.
*
- * @param update
- * @throws StorageContainerException
+ * @param update the change to apply to the in-memory container data
+ * @throws StorageContainerException if the .container file cannot be written
*/
private void updateContainerData(Runnable update)
throws StorageContainerException {
Preconditions.checkState(hasWriteLock());
final State oldState = containerData.getState();
+ final boolean committedSpace = containerData.isCommittedSpace();
try {
update.run();
// update the new container data to .container File
@@ -500,6 +508,10 @@ private void updateContainerData(Runnable update)
// Failed to update .container file. Reset the state to old state only
// if the current state is not unhealthy.
containerData.setState(oldState);
+ // Leaving the old state may have released the reserved space, reserve it again.
+ if (committedSpace && !containerData.isCommittedSpace()) {
+ containerData.commitSpace();
+ }
}
throw ex;
}
diff --git a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/keyvalue/TestKeyValueContainer.java b/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/keyvalue/TestKeyValueContainer.java
index 0e64de71f74..13b714df5e9 100644
--- a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/keyvalue/TestKeyValueContainer.java
+++ b/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/keyvalue/TestKeyValueContainer.java
@@ -846,6 +846,34 @@ public void testCloseContainer(ContainerTestVersionInfo versionInfo)
keyValueContainerData.getState());
}
+ @ContainerTestVersionInfo.ContainerTest
+ public void testReservationKeptWhenMarkForCloseFails(ContainerTestVersionInfo versionInfo) throws Exception {
+ init(versionInfo);
+ createContainer();
+ // Reserve the space as the volume choosing policy does on create.
+ HddsVolume volume = keyValueContainerData.getVolume();
+ volume.incCommittedBytes(keyValueContainerData.getMaxSize());
+
+ // The .container file cannot be updated, so marking for close fails and rolls back to OPEN.
+ File metadataDir = new File(keyValueContainerData.getMetadataPath());
+ assertThat(metadataDir.setWritable(false)).isTrue();
+ try {
+ StorageContainerException ex = assertThrows(StorageContainerException.class,
+ () -> keyValueContainer.markContainerForClose());
+ assertThat(ex.getResult()).isEqualTo(ContainerProtos.Result.CONTAINER_FILES_CREATE_ERROR);
+ } finally {
+ assertThat(metadataDir.setWritable(true)).isTrue();
+ }
+ assertThat(keyValueContainerData.getState()).isEqualTo(ContainerProtos.ContainerDataProto.State.OPEN);
+ assertThat(keyValueContainerData.isCommittedSpace()).isTrue();
+ assertThat(volume.getCommittedBytes()).isEqualTo(keyValueContainerData.getMaxSize());
+
+ // Once the file can be written, marking for close succeeds and releases the space.
+ keyValueContainer.markContainerForClose();
+ assertThat(keyValueContainerData.getState()).isEqualTo(ContainerProtos.ContainerDataProto.State.CLOSING);
+ assertThat(volume.getCommittedBytes()).isZero();
+ }
+
@ContainerTestVersionInfo.ContainerTest
public void testReportOfUnhealthyContainer(
ContainerTestVersionInfo versionInfo) throws Exception {
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@ozone.apache.org
For additional commands, e-mail: commits-help@ozone.apache.org