Skip to content

Commit d4c06b2

Browse files
authored
HDDS-15650. Fix snapshotUsedNamespace underflow when FSO directory is deleted and purged (#10545)
Generated-by: Gemini 3.5 Flash
1 parent 74e454b commit d4c06b2

3 files changed

Lines changed: 77 additions & 1 deletion

File tree

hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeyDeleteRequestWithFSO.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ public OMClientResponse validateAndUpdateCache(OzoneManager ozoneManager, Execut
162162
// Empty entries won't be added to deleted table so this key shouldn't get added to snapshotUsed space.
163163
boolean isKeyNonEmpty = !OmKeyInfo.isKeyEmpty(omKeyInfo);
164164
omBucketInfo.decrUsedBytes(quotaReleased, isKeyNonEmpty);
165-
omBucketInfo.decrUsedNamespace(1L, isKeyNonEmpty);
165+
omBucketInfo.decrUsedNamespace(1L, isKeyNonEmpty || keyStatus.isDirectory());
166166

167167
// If omKeyInfo has hsync metadata, delete its corresponding open key as well
168168
String dbOpenKey = null;

hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/OMRequestTestUtils.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1030,6 +1030,13 @@ public static String deleteDir(String ozoneKey, String volume, String bucket,
10301030
omDirectoryInfo.getName());
10311031
omMetadataManager.getDeletedDirTable().put(ozoneKey, omKeyInfo);
10321032
omMetadataManager.getDirectoryTable().delete(ozoneKey);
1033+
1034+
String bucketKey = omMetadataManager.getBucketKey(volume, bucket);
1035+
OmBucketInfo omBucketInfo = omMetadataManager.getBucketTable().get(bucketKey);
1036+
if (omBucketInfo != null) {
1037+
omBucketInfo.decrUsedNamespace(1L, true);
1038+
omMetadataManager.getBucketTable().put(bucketKey, omBucketInfo);
1039+
}
10331040
return ozoneKey;
10341041
}
10351042

hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/key/TestOMKeyDeleteRequestWithFSO.java

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import org.apache.hadoop.ozone.om.OzonePrefixPathImpl;
3535
import org.apache.hadoop.ozone.om.exceptions.OMException;
3636
import org.apache.hadoop.ozone.om.helpers.BucketLayout;
37+
import org.apache.hadoop.ozone.om.helpers.OmBucketInfo;
3738
import org.apache.hadoop.ozone.om.helpers.OmDirectoryInfo;
3839
import org.apache.hadoop.ozone.om.helpers.OmKeyInfo;
3940
import org.apache.hadoop.ozone.om.helpers.OzoneFileStatus;
@@ -333,4 +334,72 @@ public void testDeleteParentAfterChildDeleted() throws Exception {
333334
assertEquals(OzoneManagerProtocolProtos.Status.OK, response.getOMResponse().getStatus(),
334335
"Parent delete should succeed after children deleted");
335336
}
337+
338+
@Test
339+
public void testSnapshotUsedNamespaceAfterDirectoryDeleteAndPurge() throws Exception {
340+
OMRequestTestUtils.addVolumeAndBucketToDB(volumeName, bucketName, omMetadataManager, getBucketLayout());
341+
342+
String dirName = "dir1";
343+
String dirKeyPath = addKeyToDirTable(volumeName, bucketName, dirName);
344+
345+
long parentObjectID = 0L;
346+
long dirObjectID = 12345L;
347+
OmDirectoryInfo omDirectoryInfo = OMRequestTestUtils.createOmDirectoryInfo(dirName, dirObjectID, parentObjectID);
348+
omMetadataManager.getDirectoryTable().put(dirKeyPath, omDirectoryInfo);
349+
350+
String bucketKey = omMetadataManager.getBucketKey(volumeName, bucketName);
351+
OmBucketInfo omBucketInfo = omMetadataManager.getBucketTable().get(bucketKey);
352+
assertNotNull(omBucketInfo);
353+
// Initialize used namespace and snapshot used namespace for test predictability
354+
omBucketInfo.incrUsedNamespace(1);
355+
omMetadataManager.getBucketTable().put(bucketKey, omBucketInfo);
356+
357+
// Delete the directory
358+
long txnId = 100L;
359+
OMRequest deleteRequest = doPreExecute(createDeleteKeyRequest(dirName, false));
360+
OMKeyDeleteRequest omKeyDeleteRequest = getOmKeyDeleteRequest(deleteRequest);
361+
OMClientResponse deleteResponse = omKeyDeleteRequest.validateAndUpdateCache(ozoneManager, txnId++);
362+
assertEquals(OzoneManagerProtocolProtos.Status.OK, deleteResponse.getOMResponse().getStatus());
363+
364+
OmBucketInfo bucketInfoAfterDelete = omMetadataManager.getBucketTable().get(bucketKey);
365+
366+
// Perform purge
367+
OzoneManagerProtocolProtos.PurgeDirectoriesRequest.Builder purgeDirRequest =
368+
OzoneManagerProtocolProtos.PurgeDirectoriesRequest.newBuilder();
369+
370+
long volumeId = omMetadataManager.getVolumeId(volumeName);
371+
long bucketId = bucketInfoAfterDelete.getObjectID();
372+
373+
OzoneManagerProtocolProtos.PurgePathRequest purgePathRequest =
374+
OzoneManagerProtocolProtos.PurgePathRequest.newBuilder()
375+
.setVolumeId(volumeId)
376+
.setBucketId(bucketId)
377+
.setDeletedDir(dirKeyPath)
378+
.build();
379+
380+
purgeDirRequest.addDeletedPath(purgePathRequest);
381+
purgeDirRequest.addBucketNameInfos(
382+
OzoneManagerProtocolProtos.BucketNameInfo.newBuilder()
383+
.setVolumeName(volumeName)
384+
.setBucketName(bucketName)
385+
.setBucketId(bucketId)
386+
.setVolumeId(volumeId)
387+
.build());
388+
389+
OMRequest purgeRequest = OMRequest.newBuilder()
390+
.setCmdType(OzoneManagerProtocolProtos.Type.PurgeDirectories)
391+
.setPurgeDirectoriesRequest(purgeDirRequest)
392+
.setClientId(UUID.randomUUID().toString())
393+
.build();
394+
395+
OMDirectoriesPurgeRequestWithFSO omPurgeRequest = new OMDirectoriesPurgeRequestWithFSO(purgeRequest);
396+
OMClientResponse purgeResponse = omPurgeRequest.validateAndUpdateCache(ozoneManager, txnId);
397+
assertEquals(OzoneManagerProtocolProtos.Status.OK, purgeResponse.getOMResponse().getStatus());
398+
399+
OmBucketInfo bucketInfoAfterPurge = omMetadataManager.getBucketTable().get(bucketKey);
400+
401+
// We expect snapshotUsedNamespace to not go negative
402+
assertTrue(bucketInfoAfterPurge.getSnapshotUsedNamespace() >= 0,
403+
"SnapshotUsedNamespace went negative (" + bucketInfoAfterPurge.getSnapshotUsedNamespace() + ") due to bug.");
404+
}
336405
}

0 commit comments

Comments
 (0)