Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HDFS-16428. Source path with storagePolicy cause wrong typeConsumed while rename #3898

Merged
merged 3 commits into from
Jan 25, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,12 @@ private static void verifyQuotaForRename(FSDirectory fsd, INodesInPath src,
// Assume dstParent existence check done by callers.
INode dstParent = dst.getINode(-2);
// Use the destination parent's storage policy for quota delta verify.
final boolean isSrcSetSp = src.getLastINode().isSetStoragePolicy();
final byte storagePolicyID = isSrcSetSp ?
src.getLastINode().getLocalStoragePolicyID() :
dstParent.getStoragePolicyID();
final QuotaCounts delta = src.getLastINode()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we also add a test case to verify the quota check part.

.computeQuotaUsage(bsps, dstParent.getStoragePolicyID(), false,
.computeQuotaUsage(bsps, storagePolicyID, false,
Snapshot.CURRENT_STATE_ID);

// Reduce the required quota by dst that is being removed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1372,9 +1372,13 @@ public INodesInPath addLastINode(INodesInPath existing, INode inode,
// always verify inode name
verifyINodeName(inode.getLocalNameBytes());

final boolean isSrcSetSp = inode.isSetStoragePolicy();
final byte storagePolicyID = isSrcSetSp ?
inode.getLocalStoragePolicyID() :
parent.getStoragePolicyID();
final QuotaCounts counts = inode
.computeQuotaUsage(getBlockStoragePolicySuite(),
parent.getStoragePolicyID(), false, Snapshot.CURRENT_STATE_ID);
storagePolicyID, false, Snapshot.CURRENT_STATE_ID);
updateCount(existing, pos, counts, checkQuota);

boolean isRename = (inode.getParent() != null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,16 @@ public boolean isFile() {
return false;
}

/**
* Check if this inode itself has a storage policy set.
*/
public boolean isSetStoragePolicy() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A minor comment. It will be good if we add a comment to this method. People may confuse about "inheriting storage policy from its parent" and "containing storage policy itself". Add a comment like getStoragePolicyID() and getLocalStoragePolicyID().

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@wojiaodoubao thank you very much for your comment. I had fixed it and repush it.

if (isSymlink()) {
return false;
}
return getLocalStoragePolicyID() != HdfsConstants.BLOCK_STORAGE_POLICY_ID_UNSPECIFIED;
}

/** Cast this inode to an {@link INodeFile}. */
public INodeFile asFile() {
throw new IllegalStateException("Current inode is not a file: "
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.fs.QuotaUsage;
import org.apache.hadoop.fs.StorageType;
import org.apache.hadoop.fs.permission.FsPermission;
import org.apache.hadoop.hdfs.client.impl.LeaseRenewer;
import org.apache.hadoop.hdfs.protocol.DSQuotaExceededException;
import org.apache.hadoop.hdfs.protocol.HdfsConstants;
Expand Down Expand Up @@ -958,6 +959,44 @@ public void testQuotaByStorageType() throws Exception {
6 * fileSpace);
}

@Test
public void testRenameInodeWithStorageType() throws IOException {
final int size = 64;
final short repl = 1;
final Path foo = new Path("/foo");
final Path bs1 = new Path(foo, "bs1");
final Path wow = new Path(bs1, "wow");
final Path bs2 = new Path(foo, "bs2");
final Path wow2 = new Path(bs2, "wow2");
final Path wow3 = new Path(bs2, "wow3");

dfs.mkdirs(bs1, FsPermission.getDirDefault());
dfs.mkdirs(bs2, FsPermission.getDirDefault());
dfs.setQuota(bs1, 1000, 434217728);
dfs.setQuota(bs2, 1000, 434217728);
// file wow3 without storage policy
DFSTestUtil.createFile(dfs, wow3, size, repl, 0);

dfs.setStoragePolicy(bs2, HdfsConstants.ONESSD_STORAGE_POLICY_NAME);

DFSTestUtil.createFile(dfs, wow, size, repl, 0);
DFSTestUtil.createFile(dfs, wow2, size, repl, 0);
assertTrue("Without storage policy, typeConsumed should be 0.",
dfs.getQuotaUsage(bs1).getTypeConsumed(StorageType.SSD) == 0);
assertTrue("With storage policy, typeConsumed should not be 0.",
dfs.getQuotaUsage(bs2).getTypeConsumed(StorageType.SSD) != 0);
// wow3 without storage policy , rename will not change typeConsumed
dfs.rename(wow3, bs1);
assertTrue("Rename src without storagePolicy, dst typeConsumed should not be changed.",
dfs.getQuotaUsage(bs2).getTypeConsumed(StorageType.SSD) == 0);

long srcTypeQuota = dfs.getQuotaUsage(bs2).getTypeQuota(StorageType.SSD);
dfs.rename(bs2, bs1);
long dstTypeQuota = dfs.getQuotaUsage(bs1).getTypeConsumed(StorageType.SSD);
assertTrue("Rename with storage policy, typeConsumed should not be 0.",
dstTypeQuota != srcTypeQuota);
}

private static void checkContentSummary(final ContentSummary expected,
final ContentSummary computed) {
assertEquals(expected.toString(), computed.toString());
Expand Down