HDFS-14633. The StorageType quota and consume in QuotaFeature is not handled for rename. Contributed by Jinglun.

(cherry picked from commit 62d71fbac3789c7d484bc76ced9ec7fa6ff94de1)
This commit is contained in:
Xiaoyu Yao 2019-08-30 16:46:04 -07:00
parent 269aa7ebfe
commit 259c6bb0c7
No known key found for this signature in database
GPG Key ID: 2A33E32176F50EF3
3 changed files with 72 additions and 2 deletions

View File

@ -76,7 +76,12 @@ class FSDirRenameOp {
while(src.getINode(i) == dst.getINode(i)) { i++; }
// src[i - 1] is the last common ancestor.
BlockStoragePolicySuite bsps = fsd.getBlockStoragePolicySuite();
final QuotaCounts delta = src.getLastINode().computeQuotaUsage(bsps);
// Assume dstParent existence check done by callers.
INode dstParent = dst.getINode(-2);
// Use the destination parent's storage policy for quota delta verify.
final QuotaCounts delta = src.getLastINode()
.computeQuotaUsage(bsps, dstParent.getStoragePolicyID(), false,
Snapshot.CURRENT_STATE_ID);
// Reduce the required quota by dst that is being removed
final INode dstINode = dst.getLastINode();

View File

@ -17,6 +17,7 @@
*/
package org.apache.hadoop.hdfs.server.namenode;
import org.apache.hadoop.hdfs.server.namenode.snapshot.Snapshot;
import org.apache.hadoop.util.StringUtils;
import com.google.common.annotations.VisibleForTesting;
@ -1298,7 +1299,9 @@ public class FSDirectory implements Closeable {
// always verify inode name
verifyINodeName(inode.getLocalNameBytes());
final QuotaCounts counts = inode.computeQuotaUsage(getBlockStoragePolicySuite());
final QuotaCounts counts = inode
.computeQuotaUsage(getBlockStoragePolicySuite(),
parent.getStoragePolicyID(), false, Snapshot.CURRENT_STATE_ID);
updateCount(existing, pos, counts, checkQuota);
boolean isRename = (inode.getParent() != null);

View File

@ -1565,6 +1565,57 @@ 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 testRename() throws Exception {
int fileLen = 1024;
short replication = 3;
final Path parent = new Path(PathUtils.getTestDir(getClass()).getPath(),
GenericTestUtils.getMethodName());
assertTrue(dfs.mkdirs(parent));
final Path srcDir = new Path(parent, "src-dir");
Path file = new Path(srcDir, "file1");
DFSTestUtil.createFile(dfs, file, fileLen, replication, 0);
dfs.setStoragePolicy(srcDir, HdfsConstants.HOT_STORAGE_POLICY_NAME);
final Path dstDir = new Path(parent, "dst-dir");
assertTrue(dfs.mkdirs(dstDir));
dfs.setStoragePolicy(dstDir, HdfsConstants.ALLSSD_STORAGE_POLICY_NAME);
dfs.setQuota(srcDir, 100000, 100000);
dfs.setQuota(dstDir, 100000, 100000);
Path dstFile = new Path(dstDir, "file1");
// Test quota check of rename. Expect a QuotaExceedException.
dfs.setQuotaByStorageType(dstDir, StorageType.SSD, 10);
try {
dfs.rename(file, dstFile);
fail("Expect QuotaExceedException.");
} catch (QuotaExceededException qe) {
}
// Set enough quota, expect a successful rename.
dfs.setQuotaByStorageType(dstDir, StorageType.SSD, fileLen * replication);
dfs.rename(file, dstFile);
// Verify the storage type usage is properly updated on source and dst.
checkQuotaAndCount(dfs, srcDir);
checkQuotaAndCount(dfs, dstDir);
}
@Test
public void testSpaceQuotaExceptionOnAppend() throws Exception {
GenericTestUtils.setLogLevel(DFSOutputStream.LOG, Level.TRACE);
@ -1635,4 +1686,15 @@ public class TestQuota {
}
scanner.close();
}
// quota and count should match.
private void checkQuotaAndCount(DistributedFileSystem fs, Path path)
throws IOException {
QuotaUsage qu = fs.getQuotaUsage(path);
ContentSummary cs = fs.getContentSummary(path);
for (StorageType st : StorageType.values()) {
// it will fail here, because the quota and consume is not handled right.
assertEquals(qu.getTypeConsumed(st), cs.getTypeConsumed(st));
}
}
}