This is an automated email from the ASF dual-hosted git repository.
jojochuang 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 d4c06b2492e HDDS-15650. Fix snapshotUsedNamespace underflow when FSO
directory is deleted and purged (#10545)
d4c06b2492e is described below
commit d4c06b2492ee74d22e157dbddb7dd476ef411879
Author: Wei-Chiu Chuang <[email protected]>
AuthorDate: Tue Jun 23 11:04:29 2026 -0700
HDDS-15650. Fix snapshotUsedNamespace underflow when FSO directory is
deleted and purged (#10545)
Generated-by: Gemini 3.5 Flash
---
.../om/request/key/OMKeyDeleteRequestWithFSO.java | 2 +-
.../ozone/om/request/OMRequestTestUtils.java | 7 +++
.../request/key/TestOMKeyDeleteRequestWithFSO.java | 69 ++++++++++++++++++++++
3 files changed, 77 insertions(+), 1 deletion(-)
diff --git
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeyDeleteRequestWithFSO.java
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeyDeleteRequestWithFSO.java
index 4737b85373d..efe04a804b9 100644
---
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeyDeleteRequestWithFSO.java
+++
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeyDeleteRequestWithFSO.java
@@ -162,7 +162,7 @@ public OMClientResponse validateAndUpdateCache(OzoneManager
ozoneManager, Execut
// Empty entries won't be added to deleted table so this key shouldn't
get added to snapshotUsed space.
boolean isKeyNonEmpty = !OmKeyInfo.isKeyEmpty(omKeyInfo);
omBucketInfo.decrUsedBytes(quotaReleased, isKeyNonEmpty);
- omBucketInfo.decrUsedNamespace(1L, isKeyNonEmpty);
+ omBucketInfo.decrUsedNamespace(1L, isKeyNonEmpty ||
keyStatus.isDirectory());
// If omKeyInfo has hsync metadata, delete its corresponding open key as
well
String dbOpenKey = null;
diff --git
a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/OMRequestTestUtils.java
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/OMRequestTestUtils.java
index c7e80f166ae..0a7ad486235 100644
---
a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/OMRequestTestUtils.java
+++
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/OMRequestTestUtils.java
@@ -1030,6 +1030,13 @@ public static String deleteDir(String ozoneKey, String
volume, String bucket,
omDirectoryInfo.getName());
omMetadataManager.getDeletedDirTable().put(ozoneKey, omKeyInfo);
omMetadataManager.getDirectoryTable().delete(ozoneKey);
+
+ String bucketKey = omMetadataManager.getBucketKey(volume, bucket);
+ OmBucketInfo omBucketInfo =
omMetadataManager.getBucketTable().get(bucketKey);
+ if (omBucketInfo != null) {
+ omBucketInfo.decrUsedNamespace(1L, true);
+ omMetadataManager.getBucketTable().put(bucketKey, omBucketInfo);
+ }
return ozoneKey;
}
diff --git
a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/key/TestOMKeyDeleteRequestWithFSO.java
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/key/TestOMKeyDeleteRequestWithFSO.java
index c537b09c85b..cbaa6344699 100644
---
a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/key/TestOMKeyDeleteRequestWithFSO.java
+++
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/key/TestOMKeyDeleteRequestWithFSO.java
@@ -34,6 +34,7 @@
import org.apache.hadoop.ozone.om.OzonePrefixPathImpl;
import org.apache.hadoop.ozone.om.exceptions.OMException;
import org.apache.hadoop.ozone.om.helpers.BucketLayout;
+import org.apache.hadoop.ozone.om.helpers.OmBucketInfo;
import org.apache.hadoop.ozone.om.helpers.OmDirectoryInfo;
import org.apache.hadoop.ozone.om.helpers.OmKeyInfo;
import org.apache.hadoop.ozone.om.helpers.OzoneFileStatus;
@@ -333,4 +334,72 @@ public void testDeleteParentAfterChildDeleted() throws
Exception {
assertEquals(OzoneManagerProtocolProtos.Status.OK,
response.getOMResponse().getStatus(),
"Parent delete should succeed after children deleted");
}
+
+ @Test
+ public void testSnapshotUsedNamespaceAfterDirectoryDeleteAndPurge() throws
Exception {
+ OMRequestTestUtils.addVolumeAndBucketToDB(volumeName, bucketName,
omMetadataManager, getBucketLayout());
+
+ String dirName = "dir1";
+ String dirKeyPath = addKeyToDirTable(volumeName, bucketName, dirName);
+
+ long parentObjectID = 0L;
+ long dirObjectID = 12345L;
+ OmDirectoryInfo omDirectoryInfo =
OMRequestTestUtils.createOmDirectoryInfo(dirName, dirObjectID, parentObjectID);
+ omMetadataManager.getDirectoryTable().put(dirKeyPath, omDirectoryInfo);
+
+ String bucketKey = omMetadataManager.getBucketKey(volumeName, bucketName);
+ OmBucketInfo omBucketInfo =
omMetadataManager.getBucketTable().get(bucketKey);
+ assertNotNull(omBucketInfo);
+ // Initialize used namespace and snapshot used namespace for test
predictability
+ omBucketInfo.incrUsedNamespace(1);
+ omMetadataManager.getBucketTable().put(bucketKey, omBucketInfo);
+
+ // Delete the directory
+ long txnId = 100L;
+ OMRequest deleteRequest = doPreExecute(createDeleteKeyRequest(dirName,
false));
+ OMKeyDeleteRequest omKeyDeleteRequest =
getOmKeyDeleteRequest(deleteRequest);
+ OMClientResponse deleteResponse =
omKeyDeleteRequest.validateAndUpdateCache(ozoneManager, txnId++);
+ assertEquals(OzoneManagerProtocolProtos.Status.OK,
deleteResponse.getOMResponse().getStatus());
+
+ OmBucketInfo bucketInfoAfterDelete =
omMetadataManager.getBucketTable().get(bucketKey);
+
+ // Perform purge
+ OzoneManagerProtocolProtos.PurgeDirectoriesRequest.Builder purgeDirRequest
=
+ OzoneManagerProtocolProtos.PurgeDirectoriesRequest.newBuilder();
+
+ long volumeId = omMetadataManager.getVolumeId(volumeName);
+ long bucketId = bucketInfoAfterDelete.getObjectID();
+
+ OzoneManagerProtocolProtos.PurgePathRequest purgePathRequest =
+ OzoneManagerProtocolProtos.PurgePathRequest.newBuilder()
+ .setVolumeId(volumeId)
+ .setBucketId(bucketId)
+ .setDeletedDir(dirKeyPath)
+ .build();
+
+ purgeDirRequest.addDeletedPath(purgePathRequest);
+ purgeDirRequest.addBucketNameInfos(
+ OzoneManagerProtocolProtos.BucketNameInfo.newBuilder()
+ .setVolumeName(volumeName)
+ .setBucketName(bucketName)
+ .setBucketId(bucketId)
+ .setVolumeId(volumeId)
+ .build());
+
+ OMRequest purgeRequest = OMRequest.newBuilder()
+ .setCmdType(OzoneManagerProtocolProtos.Type.PurgeDirectories)
+ .setPurgeDirectoriesRequest(purgeDirRequest)
+ .setClientId(UUID.randomUUID().toString())
+ .build();
+
+ OMDirectoriesPurgeRequestWithFSO omPurgeRequest = new
OMDirectoriesPurgeRequestWithFSO(purgeRequest);
+ OMClientResponse purgeResponse =
omPurgeRequest.validateAndUpdateCache(ozoneManager, txnId);
+ assertEquals(OzoneManagerProtocolProtos.Status.OK,
purgeResponse.getOMResponse().getStatus());
+
+ OmBucketInfo bucketInfoAfterPurge =
omMetadataManager.getBucketTable().get(bucketKey);
+
+ // We expect snapshotUsedNamespace to not go negative
+ assertTrue(bucketInfoAfterPurge.getSnapshotUsedNamespace() >= 0,
+ "SnapshotUsedNamespace went negative (" +
bucketInfoAfterPurge.getSnapshotUsedNamespace() + ") due to bug.");
+ }
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]