diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSDirAttrOp.java b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSDirAttrOp.java index 1dbee96985c..6da59eda09f 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSDirAttrOp.java +++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSDirAttrOp.java @@ -332,38 +332,35 @@ public class FSDirAttrOp { INodeDirectory dirNode = INodeDirectory.valueOf(iip.getLastINode(), iip.getPath()); + final QuotaCounts oldQuota = dirNode.getQuotaCounts(); + final long oldNsQuota = oldQuota.getNameSpace(); + final long oldSsQuota = oldQuota.getStorageSpace(); if (dirNode.isRoot() && nsQuota == HdfsConstants.QUOTA_RESET) { - throw new IllegalArgumentException("Cannot clear namespace quota on root."); - } else { // a directory inode - final QuotaCounts oldQuota = dirNode.getQuotaCounts(); - final long oldNsQuota = oldQuota.getNameSpace(); - final long oldSsQuota = oldQuota.getStorageSpace(); + nsQuota = HdfsConstants.QUOTA_DONT_SET; + } else if (nsQuota == HdfsConstants.QUOTA_DONT_SET) { + nsQuota = oldNsQuota; + } // a directory inode + if (ssQuota == HdfsConstants.QUOTA_DONT_SET) { + ssQuota = oldSsQuota; + } - if (nsQuota == HdfsConstants.QUOTA_DONT_SET) { - nsQuota = oldNsQuota; - } - if (ssQuota == HdfsConstants.QUOTA_DONT_SET) { - ssQuota = oldSsQuota; - } + // unchanged space/namespace quota + if (type == null && oldNsQuota == nsQuota && oldSsQuota == ssQuota) { + return null; + } - // unchanged space/namespace quota - if (type == null && oldNsQuota == nsQuota && oldSsQuota == ssQuota) { + // unchanged type quota + if (type != null) { + EnumCounters oldTypeQuotas = oldQuota.getTypeSpaces(); + if (oldTypeQuotas != null && oldTypeQuotas.get(type) == ssQuota) { return null; } - - // unchanged type quota - if (type != null) { - EnumCounters oldTypeQuotas = oldQuota.getTypeSpaces(); - if (oldTypeQuotas != null && oldTypeQuotas.get(type) == ssQuota) { - return null; - } - } - - final int latest = iip.getLatestSnapshotId(); - dirNode.recordModification(latest); - dirNode.setQuota(fsd.getBlockStoragePolicySuite(), nsQuota, ssQuota, type); - return dirNode; } + + final int latest = iip.getLatestSnapshotId(); + dirNode.recordModification(latest); + dirNode.setQuota(fsd.getBlockStoragePolicySuite(), nsQuota, ssQuota, type); + return dirNode; } static BlockInfo[] unprotectedSetReplication( diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestQuota.java b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestQuota.java index 1c4855fc701..f5d232c0a6b 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestQuota.java +++ b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestQuota.java @@ -413,13 +413,13 @@ public class TestQuota { } }); - // 19: clrQuota on the root directory ("/") should fail - runCommand(admin, true, "-clrQuota", "/"); + // 19: clrQuota on the root directory ("/") should pass. + runCommand(admin, false, "-clrQuota", "/"); // 20: setQuota on the root directory ("/") should succeed runCommand(admin, false, "-setQuota", "1000000", "/"); - runCommand(admin, true, "-clrQuota", "/"); + runCommand(admin, false, "-clrQuota", "/"); runCommand(admin, false, "-clrSpaceQuota", "/"); runCommand(admin, new String[]{"-clrQuota", parent.toString()}, false); runCommand(admin, false, "-clrSpaceQuota", parent.toString()); @@ -456,7 +456,7 @@ public class TestQuota { final Path childFile4 = new Path(dir, "datafile2"); final Path childFile5 = new Path(dir, "datafile3"); - runCommand(admin, true, "-clrQuota", "/"); + runCommand(admin, false, "-clrQuota", "/"); runCommand(admin, false, "-clrSpaceQuota", "/"); // set space quota to a real low value runCommand(admin, false, "-setSpaceQuota", Long.toString(spaceQuota2), "/"); @@ -1565,6 +1565,19 @@ public class TestQuota { assertEquals(0, cluster.getNamesystem().getNumFilesUnderConstruction()); } + @Test + public void testClrQuotaOnRoot() throws Exception { + long orignalQuota = dfs.getQuotaUsage(new Path("/")).getQuota(); + DFSAdmin admin = new DFSAdmin(conf); + String[] args; + args = new String[] {"-setQuota", "3K", "/"}; + runCommand(admin, args, false); + assertEquals(3 * 1024, dfs.getQuotaUsage(new Path("/")).getQuota()); + args = new String[] {"-clrQuota", "/"}; + runCommand(admin, args, false); + assertEquals(orignalQuota, dfs.getQuotaUsage(new Path("/")).getQuota()); + } + @Test public void testSpaceQuotaExceptionOnAppend() throws Exception { GenericTestUtils.setLogLevel(DFSOutputStream.LOG, Level.TRACE);