HDFS-10745. Directly resolve paths into INodesInPath. Contributed by Daryn Sharp.

(cherry picked from commit 922d045e11)

Conflicts:
	hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSDirWriteFileOp.java
	hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/namenode/TestFsck.java
This commit is contained in:
Kihwal Lee 2016-09-02 11:44:01 -05:00
parent 3dac73080a
commit 69bdcd9b1e
16 changed files with 226 additions and 221 deletions

View File

@ -25,7 +25,6 @@ import org.apache.hadoop.fs.permission.FsAction;
import org.apache.hadoop.fs.permission.FsPermission; import org.apache.hadoop.fs.permission.FsPermission;
import org.apache.hadoop.hdfs.DFSConfigKeys; import org.apache.hadoop.hdfs.DFSConfigKeys;
import org.apache.hadoop.hdfs.protocol.AclException; import org.apache.hadoop.hdfs.protocol.AclException;
import org.apache.hadoop.hdfs.protocol.HdfsConstants;
import org.apache.hadoop.hdfs.protocol.HdfsFileStatus; import org.apache.hadoop.hdfs.protocol.HdfsFileStatus;
import java.io.IOException; import java.io.IOException;
@ -39,11 +38,11 @@ class FSDirAclOp {
String src = srcArg; String src = srcArg;
checkAclsConfigFlag(fsd); checkAclsConfigFlag(fsd);
FSPermissionChecker pc = fsd.getPermissionChecker(); FSPermissionChecker pc = fsd.getPermissionChecker();
src = fsd.resolvePath(pc, src);
INodesInPath iip; INodesInPath iip;
fsd.writeLock(); fsd.writeLock();
try { try {
iip = fsd.getINodesInPath4Write(FSDirectory.normalizePath(src), true); iip = fsd.resolvePathForWrite(pc, src);
src = iip.getPath();
fsd.checkOwner(pc, iip); fsd.checkOwner(pc, iip);
INode inode = FSDirectory.resolveLastINode(iip); INode inode = FSDirectory.resolveLastINode(iip);
int snapshotId = iip.getLatestSnapshotId(); int snapshotId = iip.getLatestSnapshotId();
@ -64,11 +63,11 @@ class FSDirAclOp {
String src = srcArg; String src = srcArg;
checkAclsConfigFlag(fsd); checkAclsConfigFlag(fsd);
FSPermissionChecker pc = fsd.getPermissionChecker(); FSPermissionChecker pc = fsd.getPermissionChecker();
src = fsd.resolvePath(pc, src);
INodesInPath iip; INodesInPath iip;
fsd.writeLock(); fsd.writeLock();
try { try {
iip = fsd.getINodesInPath4Write(FSDirectory.normalizePath(src), true); iip = fsd.resolvePathForWrite(pc, src);
src = iip.getPath();
fsd.checkOwner(pc, iip); fsd.checkOwner(pc, iip);
INode inode = FSDirectory.resolveLastINode(iip); INode inode = FSDirectory.resolveLastINode(iip);
int snapshotId = iip.getLatestSnapshotId(); int snapshotId = iip.getLatestSnapshotId();
@ -88,11 +87,11 @@ class FSDirAclOp {
String src = srcArg; String src = srcArg;
checkAclsConfigFlag(fsd); checkAclsConfigFlag(fsd);
FSPermissionChecker pc = fsd.getPermissionChecker(); FSPermissionChecker pc = fsd.getPermissionChecker();
src = fsd.resolvePath(pc, src);
INodesInPath iip; INodesInPath iip;
fsd.writeLock(); fsd.writeLock();
try { try {
iip = fsd.getINodesInPath4Write(FSDirectory.normalizePath(src), true); iip = fsd.resolvePathForWrite(pc, src);
src = iip.getPath();
fsd.checkOwner(pc, iip); fsd.checkOwner(pc, iip);
INode inode = FSDirectory.resolveLastINode(iip); INode inode = FSDirectory.resolveLastINode(iip);
int snapshotId = iip.getLatestSnapshotId(); int snapshotId = iip.getLatestSnapshotId();
@ -112,11 +111,11 @@ class FSDirAclOp {
String src = srcArg; String src = srcArg;
checkAclsConfigFlag(fsd); checkAclsConfigFlag(fsd);
FSPermissionChecker pc = fsd.getPermissionChecker(); FSPermissionChecker pc = fsd.getPermissionChecker();
src = fsd.resolvePath(pc, src);
INodesInPath iip; INodesInPath iip;
fsd.writeLock(); fsd.writeLock();
try { try {
iip = fsd.getINodesInPath4Write(src); iip = fsd.resolvePathForWrite(pc, src);
src = iip.getPath();
fsd.checkOwner(pc, iip); fsd.checkOwner(pc, iip);
unprotectedRemoveAcl(fsd, iip); unprotectedRemoveAcl(fsd, iip);
} finally { } finally {
@ -132,11 +131,11 @@ class FSDirAclOp {
String src = srcArg; String src = srcArg;
checkAclsConfigFlag(fsd); checkAclsConfigFlag(fsd);
FSPermissionChecker pc = fsd.getPermissionChecker(); FSPermissionChecker pc = fsd.getPermissionChecker();
src = fsd.resolvePath(pc, src);
INodesInPath iip; INodesInPath iip;
fsd.writeLock(); fsd.writeLock();
try { try {
iip = fsd.getINodesInPath4Write(src); iip = fsd.resolvePathForWrite(pc, src);
src = iip.getPath();
fsd.checkOwner(pc, iip); fsd.checkOwner(pc, iip);
List<AclEntry> newAcl = unprotectedSetAcl(fsd, src, aclSpec, false); List<AclEntry> newAcl = unprotectedSetAcl(fsd, src, aclSpec, false);
fsd.getEditLog().logSetAcl(src, newAcl); fsd.getEditLog().logSetAcl(src, newAcl);
@ -150,17 +149,15 @@ class FSDirAclOp {
FSDirectory fsd, String src) throws IOException { FSDirectory fsd, String src) throws IOException {
checkAclsConfigFlag(fsd); checkAclsConfigFlag(fsd);
FSPermissionChecker pc = fsd.getPermissionChecker(); FSPermissionChecker pc = fsd.getPermissionChecker();
src = fsd.resolvePath(pc, src);
String srcs = FSDirectory.normalizePath(src);
fsd.readLock(); fsd.readLock();
try { try {
INodesInPath iip = fsd.resolvePath(pc, src);
src = iip.getPath();
// There is no real inode for the path ending in ".snapshot", so return a // There is no real inode for the path ending in ".snapshot", so return a
// non-null, unpopulated AclStatus. This is similar to getFileInfo. // non-null, unpopulated AclStatus. This is similar to getFileInfo.
if (srcs.endsWith(HdfsConstants.SEPARATOR_DOT_SNAPSHOT_DIR) && if (iip.isDotSnapshotDir() && fsd.getINode4DotSnapshot(iip) != null) {
fsd.getINode4DotSnapshot(srcs) != null) {
return new AclStatus.Builder().owner("").group("").build(); return new AclStatus.Builder().owner("").group("").build();
} }
INodesInPath iip = fsd.getINodesInPath(srcs, true);
if (fsd.isPermissionEnabled()) { if (fsd.isPermissionEnabled()) {
fsd.checkTraverse(pc, iip); fsd.checkTraverse(pc, iip);
} }

View File

@ -87,8 +87,8 @@ final class FSDirAppendOp {
final String src; final String src;
fsd.writeLock(); fsd.writeLock();
try { try {
src = fsd.resolvePath(pc, srcArg); final INodesInPath iip = fsd.resolvePathForWrite(pc, srcArg);
final INodesInPath iip = fsd.getINodesInPath4Write(src); src = iip.getPath();
// Verify that the destination does not exist as a directory already // Verify that the destination does not exist as a directory already
final INode inode = iip.getLastINode(); final INode inode = iip.getLastINode();
final String path = iip.getPath(); final String path = iip.getPath();

View File

@ -60,8 +60,8 @@ public class FSDirAttrOp {
INodesInPath iip; INodesInPath iip;
fsd.writeLock(); fsd.writeLock();
try { try {
src = fsd.resolvePath(pc, src); iip = fsd.resolvePathForWrite(pc, src);
iip = fsd.getINodesInPath4Write(src); src = iip.getPath();
fsd.checkOwner(pc, iip); fsd.checkOwner(pc, iip);
unprotectedSetPermission(fsd, src, permission); unprotectedSetPermission(fsd, src, permission);
} finally { } finally {
@ -81,8 +81,8 @@ public class FSDirAttrOp {
INodesInPath iip; INodesInPath iip;
fsd.writeLock(); fsd.writeLock();
try { try {
src = fsd.resolvePath(pc, src); iip = fsd.resolvePathForWrite(pc, src);
iip = fsd.getINodesInPath4Write(src); src = iip.getPath();
fsd.checkOwner(pc, iip); fsd.checkOwner(pc, iip);
if (!pc.isSuperUser()) { if (!pc.isSuperUser()) {
if (username != null && !pc.getUser().equals(username)) { if (username != null && !pc.getUser().equals(username)) {
@ -108,8 +108,8 @@ public class FSDirAttrOp {
INodesInPath iip; INodesInPath iip;
fsd.writeLock(); fsd.writeLock();
try { try {
src = fsd.resolvePath(pc, src); iip = fsd.resolvePathForWrite(pc, src);
iip = fsd.getINodesInPath4Write(src); src = iip.getPath();
// Write access is required to set access and modification times // Write access is required to set access and modification times
if (fsd.isPermissionEnabled()) { if (fsd.isPermissionEnabled()) {
fsd.checkPathAccess(pc, iip, FsAction.WRITE); fsd.checkPathAccess(pc, iip, FsAction.WRITE);
@ -138,8 +138,8 @@ public class FSDirAttrOp {
FSPermissionChecker pc = fsd.getPermissionChecker(); FSPermissionChecker pc = fsd.getPermissionChecker();
fsd.writeLock(); fsd.writeLock();
try { try {
src = fsd.resolvePath(pc, src); final INodesInPath iip = fsd.resolvePathForWrite(pc, src);
final INodesInPath iip = fsd.getINodesInPath4Write(src); src = iip.getPath();
if (fsd.isPermissionEnabled()) { if (fsd.isPermissionEnabled()) {
fsd.checkPathAccess(pc, iip, FsAction.WRITE); fsd.checkPathAccess(pc, iip, FsAction.WRITE);
} }
@ -211,8 +211,7 @@ public class FSDirAttrOp {
FSPermissionChecker pc = fsd.getPermissionChecker(); FSPermissionChecker pc = fsd.getPermissionChecker();
fsd.readLock(); fsd.readLock();
try { try {
path = fsd.resolvePath(pc, path); final INodesInPath iip = fsd.resolvePath(pc, path, false);
final INodesInPath iip = fsd.getINodesInPath(path, false);
if (fsd.isPermissionEnabled()) { if (fsd.isPermissionEnabled()) {
fsd.checkPathAccess(pc, iip, FsAction.READ); fsd.checkPathAccess(pc, iip, FsAction.READ);
} }
@ -232,8 +231,8 @@ public class FSDirAttrOp {
FSPermissionChecker pc = fsd.getPermissionChecker(); FSPermissionChecker pc = fsd.getPermissionChecker();
fsd.readLock(); fsd.readLock();
try { try {
src = fsd.resolvePath(pc, src); final INodesInPath iip = fsd.resolvePath(pc, src, false);
final INodesInPath iip = fsd.getINodesInPath(src, false); src = iip.getPath();
if (fsd.isPermissionEnabled()) { if (fsd.isPermissionEnabled()) {
fsd.checkTraverse(pc, iip); fsd.checkTraverse(pc, iip);
} }

View File

@ -98,8 +98,8 @@ class FSDirDeleteOp {
FSDirectory fsd = fsn.getFSDirectory(); FSDirectory fsd = fsn.getFSDirectory();
FSPermissionChecker pc = fsd.getPermissionChecker(); FSPermissionChecker pc = fsd.getPermissionChecker();
src = fsd.resolvePath(pc, src); final INodesInPath iip = fsd.resolvePathForWrite(pc, src, false);
final INodesInPath iip = fsd.getINodesInPath4Write(src, false); src = iip.getPath();
if (!recursive && fsd.isNonEmptyDirectory(iip)) { if (!recursive && fsd.isNonEmptyDirectory(iip)) {
throw new PathIsNotEmptyDirectoryException(src + " is non empty"); throw new PathIsNotEmptyDirectoryException(src + " is non empty");
} }

View File

@ -155,7 +155,8 @@ final class FSDirEncryptionZoneOp {
fsd.writeLock(); fsd.writeLock();
try { try {
src = fsd.resolvePath(pc, srcArg); final INodesInPath iip = fsd.resolvePath(pc, srcArg);
src = iip.getPath();
final XAttr ezXAttr = fsd.ezManager.createEncryptionZone(src, suite, final XAttr ezXAttr = fsd.ezManager.createEncryptionZone(src, suite,
version, keyName); version, keyName);
xAttrs.add(ezXAttr); xAttrs.add(ezXAttr);
@ -178,13 +179,11 @@ final class FSDirEncryptionZoneOp {
static Map.Entry<EncryptionZone, HdfsFileStatus> getEZForPath( static Map.Entry<EncryptionZone, HdfsFileStatus> getEZForPath(
final FSDirectory fsd, final String srcArg, final FSPermissionChecker pc) final FSDirectory fsd, final String srcArg, final FSPermissionChecker pc)
throws IOException { throws IOException {
final String src;
final INodesInPath iip; final INodesInPath iip;
final EncryptionZone ret; final EncryptionZone ret;
fsd.readLock(); fsd.readLock();
try { try {
src = fsd.resolvePath(pc, srcArg); iip = fsd.resolvePath(pc, srcArg);
iip = fsd.getINodesInPath(src, true);
if (iip.getLastINode() == null) { if (iip.getLastINode() == null) {
throw new FileNotFoundException("Path not found: " + iip.getPath()); throw new FileNotFoundException("Path not found: " + iip.getPath());
} }

View File

@ -52,8 +52,8 @@ class FSDirMkdirOp {
FSPermissionChecker pc = fsd.getPermissionChecker(); FSPermissionChecker pc = fsd.getPermissionChecker();
fsd.writeLock(); fsd.writeLock();
try { try {
src = fsd.resolvePath(pc, src); INodesInPath iip = fsd.resolvePathForWrite(pc, src);
INodesInPath iip = fsd.getINodesInPath4Write(src); src = iip.getPath();
if (fsd.isPermissionEnabled()) { if (fsd.isPermissionEnabled()) {
fsd.checkTraverse(pc, iip); fsd.checkTraverse(pc, iip);
} }

View File

@ -65,12 +65,14 @@ class FSDirRenameOp {
FSPermissionChecker pc = fsd.getPermissionChecker(); FSPermissionChecker pc = fsd.getPermissionChecker();
HdfsFileStatus resultingStat = null; HdfsFileStatus resultingStat = null;
src = fsd.resolvePath(pc, src); // Rename does not operate on link targets
dst = fsd.resolvePath(pc, dst); // Do not resolveLink when checking permissions of src and dst
INodesInPath srcIIP = fsd.resolvePathForWrite(pc, src, false);
INodesInPath dstIIP = fsd.resolvePathForWrite(pc, dst, false);
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
final boolean status = renameTo(fsd, pc, src, dst, logRetryCache); final boolean status = renameTo(fsd, pc, srcIIP, dstIIP, logRetryCache);
if (status) { if (status) {
INodesInPath dstIIP = fsd.getINodesInPath(dst, false); dstIIP = fsd.getINodesInPath(dstIIP.getPath(), false);
resultingStat = fsd.getAuditFileInfo(dstIIP); resultingStat = fsd.getAuditFileInfo(dstIIP);
} }
return new RenameOldResult(status, resultingStat); return new RenameOldResult(status, resultingStat);
@ -238,9 +240,8 @@ class FSDirRenameOp {
final FSPermissionChecker pc = fsd.getPermissionChecker(); final FSPermissionChecker pc = fsd.getPermissionChecker();
BlocksMapUpdateInfo collectedBlocks = new BlocksMapUpdateInfo(); BlocksMapUpdateInfo collectedBlocks = new BlocksMapUpdateInfo();
src = fsd.resolvePath(pc, src); // returns resolved path
dst = fsd.resolvePath(pc, dst); dst = renameTo(fsd, pc, src, dst, collectedBlocks, logRetryCache, options);
renameTo(fsd, pc, src, dst, collectedBlocks, logRetryCache, options);
INodesInPath dstIIP = fsd.getINodesInPath(dst, false); INodesInPath dstIIP = fsd.getINodesInPath(dst, false);
HdfsFileStatus resultingStat = fsd.getAuditFileInfo(dstIIP); HdfsFileStatus resultingStat = fsd.getAuditFileInfo(dstIIP);
@ -252,11 +253,13 @@ class FSDirRenameOp {
* @see {@link #unprotectedRenameTo(FSDirectory, String, String, INodesInPath, * @see {@link #unprotectedRenameTo(FSDirectory, String, String, INodesInPath,
* INodesInPath, long, BlocksMapUpdateInfo, Options.Rename...)} * INodesInPath, long, BlocksMapUpdateInfo, Options.Rename...)}
*/ */
static void renameTo(FSDirectory fsd, FSPermissionChecker pc, String src, static String renameTo(FSDirectory fsd, FSPermissionChecker pc, String src,
String dst, BlocksMapUpdateInfo collectedBlocks, boolean logRetryCache, String dst, BlocksMapUpdateInfo collectedBlocks, boolean logRetryCache,
Options.Rename... options) throws IOException { Options.Rename... options) throws IOException {
final INodesInPath srcIIP = fsd.getINodesInPath4Write(src, false); final INodesInPath srcIIP = fsd.resolvePathForWrite(pc, src, false);
final INodesInPath dstIIP = fsd.getINodesInPath4Write(dst, false); final INodesInPath dstIIP = fsd.resolvePathForWrite(pc, dst, false);
src = srcIIP.getPath();
dst = dstIIP.getPath();
if (fsd.isPermissionEnabled()) { if (fsd.isPermissionEnabled()) {
// Rename does not operate on link targets // Rename does not operate on link targets
// Do not resolveLink when checking permissions of src and dst // Do not resolveLink when checking permissions of src and dst
@ -283,6 +286,7 @@ class FSDirRenameOp {
fsd.writeUnlock(); fsd.writeUnlock();
} }
fsd.getEditLog().logRename(src, dst, mtime, logRetryCache, options); fsd.getEditLog().logRename(src, dst, mtime, logRetryCache, options);
return dst;
} }
/** /**
@ -441,16 +445,17 @@ class FSDirRenameOp {
@Deprecated @Deprecated
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
private static boolean renameTo(FSDirectory fsd, FSPermissionChecker pc, private static boolean renameTo(FSDirectory fsd, FSPermissionChecker pc,
String src, String dst, boolean logRetryCache) throws IOException { INodesInPath srcIIP, INodesInPath dstIIP, boolean logRetryCache)
// Rename does not operate on link targets throws IOException {
// Do not resolveLink when checking permissions of src and dst String src = srcIIP.getPath();
// Check write access to parent of src String dst = dstIIP.getPath();
final INodesInPath srcIIP = fsd.getINodesInPath4Write(src, false);
// Note: We should not be doing this. This is move() not renameTo(). // Note: We should not be doing this. This is move() not renameTo().
final String actualDst = fsd.isDir(dst) ? if (fsd.isDir(dst)) {
dst + Path.SEPARATOR + new Path(src).getName() : dst; dstIIP = INodesInPath.append(dstIIP, null, srcIIP.getLastLocalName());
final INodesInPath dstIIP = fsd.getINodesInPath4Write(actualDst, false); }
final String actualDst = dstIIP.getPath();
if (fsd.isPermissionEnabled()) { if (fsd.isPermissionEnabled()) {
// Check write access to parent of src
fsd.checkPermission(pc, srcIIP, false, null, FsAction.WRITE, null, null, fsd.checkPermission(pc, srcIIP, false, null, FsAction.WRITE, null, null,
false); false);
// Check write access to ancestor of dst // Check write access to ancestor of dst

View File

@ -53,11 +53,14 @@ class FSDirStatAndListingOp {
final String startAfterString = DFSUtil.bytes2String(startAfter); final String startAfterString = DFSUtil.bytes2String(startAfter);
String src = null; String src = null;
final INodesInPath iip;
if (fsd.isPermissionEnabled()) { if (fsd.isPermissionEnabled()) {
FSPermissionChecker pc = fsd.getPermissionChecker(); FSPermissionChecker pc = fsd.getPermissionChecker();
src = fsd.resolvePath(pc, srcArg); iip = fsd.resolvePath(pc, srcArg);
src = iip.getPath();
} else { } else {
src = FSDirectory.resolvePath(srcArg, fsd); src = FSDirectory.resolvePath(srcArg, fsd);
iip = fsd.getINodesInPath(src, true);
} }
// Get file name when startAfter is an INodePath // Get file name when startAfter is an INodePath
@ -73,7 +76,6 @@ class FSDirStatAndListingOp {
} }
} }
final INodesInPath iip = fsd.getINodesInPath(src, true);
boolean isSuperUser = true; boolean isSuperUser = true;
if (fsd.isPermissionEnabled()) { if (fsd.isPermissionEnabled()) {
FSPermissionChecker pc = fsd.getPermissionChecker(); FSPermissionChecker pc = fsd.getPermissionChecker();
@ -106,8 +108,8 @@ class FSDirStatAndListingOp {
} }
if (fsd.isPermissionEnabled()) { if (fsd.isPermissionEnabled()) {
FSPermissionChecker pc = fsd.getPermissionChecker(); FSPermissionChecker pc = fsd.getPermissionChecker();
src = fsd.resolvePath(pc, srcArg); final INodesInPath iip = fsd.resolvePath(pc, srcArg, resolveLink);
final INodesInPath iip = fsd.getINodesInPath(src, resolveLink); src = iip.getPath();
fsd.checkPermission(pc, iip, false, null, null, null, null, false); fsd.checkPermission(pc, iip, false, null, null, null, null, false);
} else { } else {
src = FSDirectory.resolvePath(srcArg, fsd); src = FSDirectory.resolvePath(srcArg, fsd);
@ -121,8 +123,7 @@ class FSDirStatAndListingOp {
*/ */
static boolean isFileClosed(FSDirectory fsd, String src) throws IOException { static boolean isFileClosed(FSDirectory fsd, String src) throws IOException {
FSPermissionChecker pc = fsd.getPermissionChecker(); FSPermissionChecker pc = fsd.getPermissionChecker();
src = fsd.resolvePath(pc, src); final INodesInPath iip = fsd.resolvePath(pc, src);
final INodesInPath iip = fsd.getINodesInPath(src, true);
if (fsd.isPermissionEnabled()) { if (fsd.isPermissionEnabled()) {
fsd.checkTraverse(pc, iip); fsd.checkTraverse(pc, iip);
} }
@ -132,8 +133,7 @@ class FSDirStatAndListingOp {
static ContentSummary getContentSummary( static ContentSummary getContentSummary(
FSDirectory fsd, String src) throws IOException { FSDirectory fsd, String src) throws IOException {
FSPermissionChecker pc = fsd.getPermissionChecker(); FSPermissionChecker pc = fsd.getPermissionChecker();
src = fsd.resolvePath(pc, src); final INodesInPath iip = fsd.resolvePath(pc, src, false);
final INodesInPath iip = fsd.getINodesInPath(src, false);
if (fsd.isPermissionEnabled()) { if (fsd.isPermissionEnabled()) {
fsd.checkPermission(pc, iip, false, null, null, null, fsd.checkPermission(pc, iip, false, null, null, null,
FsAction.READ_EXECUTE); FsAction.READ_EXECUTE);
@ -158,8 +158,8 @@ class FSDirStatAndListingOp {
boolean isReservedName = FSDirectory.isReservedRawName(src); boolean isReservedName = FSDirectory.isReservedRawName(src);
fsd.readLock(); fsd.readLock();
try { try {
src = fsd.resolvePath(pc, src); final INodesInPath iip = fsd.resolvePath(pc, src);
final INodesInPath iip = fsd.getINodesInPath(src, true); src = iip.getPath();
final INodeFile inode = INodeFile.valueOf(iip.getLastINode(), src); final INodeFile inode = INodeFile.valueOf(iip.getLastINode(), src);
if (fsd.isPermissionEnabled()) { if (fsd.isPermissionEnabled()) {
fsd.checkPathAccess(pc, iip, FsAction.READ); fsd.checkPathAccess(pc, iip, FsAction.READ);
@ -383,24 +383,20 @@ class FSDirStatAndListingOp {
static HdfsFileStatus getFileInfo( static HdfsFileStatus getFileInfo(
FSDirectory fsd, String src, boolean resolveLink, boolean isRawPath) FSDirectory fsd, String src, boolean resolveLink, boolean isRawPath)
throws IOException { throws IOException {
String srcs = FSDirectory.normalizePath(src);
if (FSDirectory.isExactReservedName(src)) {
return FSDirectory.DOT_RESERVED_STATUS;
}
if (srcs.endsWith(HdfsConstants.SEPARATOR_DOT_SNAPSHOT_DIR)) {
if (fsd.getINode4DotSnapshot(srcs) != null) {
return new HdfsFileStatus(0, true, 0, 0, 0, 0, null, null, null, null,
HdfsFileStatus.EMPTY_NAME, -1L, 0, null,
HdfsConstants.BLOCK_STORAGE_POLICY_ID_UNSPECIFIED);
}
return null;
}
fsd.readLock(); fsd.readLock();
try { try {
final INodesInPath iip = fsd.getINodesInPath(srcs, resolveLink); HdfsFileStatus status = null;
return getFileInfo(fsd, src, iip, isRawPath, true); final INodesInPath iip = fsd.getINodesInPath(src, resolveLink);
if (FSDirectory.isExactReservedName(iip.getPathComponents())) {
status = FSDirectory.DOT_RESERVED_STATUS;
} else if (iip.isDotSnapshotDir()) {
if (fsd.getINode4DotSnapshot(iip) != null) {
status = FSDirectory.DOT_SNAPSHOT_DIR_STATUS;
}
} else {
status = getFileInfo(fsd, src, iip, isRawPath, true);
}
return status;
} finally { } finally {
fsd.readUnlock(); fsd.readUnlock();
} }
@ -609,8 +605,7 @@ class FSDirStatAndListingOp {
final INodesInPath iip; final INodesInPath iip;
fsd.readLock(); fsd.readLock();
try { try {
src = fsd.resolvePath(pc, src); iip = fsd.resolvePath(pc, src, false);
iip = fsd.getINodesInPath(src, false);
if (fsd.isPermissionEnabled()) { if (fsd.isPermissionEnabled()) {
fsd.checkPermission(pc, iip, false, null, null, null, fsd.checkPermission(pc, iip, false, null, null, null,
FsAction.READ_EXECUTE); FsAction.READ_EXECUTE);

View File

@ -56,8 +56,8 @@ class FSDirSymlinkOp {
INodesInPath iip; INodesInPath iip;
fsd.writeLock(); fsd.writeLock();
try { try {
link = fsd.resolvePath(pc, link); iip = fsd.resolvePathForWrite(pc, link, false);
iip = fsd.getINodesInPath4Write(link, false); link = iip.getPath();
if (!createParent) { if (!createParent) {
fsd.verifyParentDir(iip, link); fsd.verifyParentDir(iip, link);
} }

View File

@ -76,8 +76,8 @@ final class FSDirTruncateOp {
Block truncateBlock = null; Block truncateBlock = null;
fsd.writeLock(); fsd.writeLock();
try { try {
src = fsd.resolvePath(pc, srcArg); iip = fsd.resolvePathForWrite(pc, srcArg);
iip = fsd.getINodesInPath4Write(src, true); src = iip.getPath();
if (fsd.isPermissionEnabled()) { if (fsd.isPermissionEnabled()) {
fsd.checkPathAccess(pc, iip, FsAction.WRITE); fsd.checkPathAccess(pc, iip, FsAction.WRITE);
} }

View File

@ -39,7 +39,6 @@ import org.apache.hadoop.hdfs.protocol.ClientProtocol;
import org.apache.hadoop.hdfs.protocol.DatanodeInfo; import org.apache.hadoop.hdfs.protocol.DatanodeInfo;
import org.apache.hadoop.hdfs.protocol.EncryptionZone; import org.apache.hadoop.hdfs.protocol.EncryptionZone;
import org.apache.hadoop.hdfs.protocol.ExtendedBlock; import org.apache.hadoop.hdfs.protocol.ExtendedBlock;
import org.apache.hadoop.hdfs.protocol.HdfsConstants;
import org.apache.hadoop.hdfs.protocol.FSLimitException; import org.apache.hadoop.hdfs.protocol.FSLimitException;
import org.apache.hadoop.hdfs.protocol.HdfsFileStatus; import org.apache.hadoop.hdfs.protocol.HdfsFileStatus;
import org.apache.hadoop.hdfs.protocol.LocatedBlock; import org.apache.hadoop.hdfs.protocol.LocatedBlock;
@ -117,25 +116,10 @@ class FSDirWriteFileOp {
static void abandonBlock( static void abandonBlock(
FSDirectory fsd, FSPermissionChecker pc, ExtendedBlock b, long fileId, FSDirectory fsd, FSPermissionChecker pc, ExtendedBlock b, long fileId,
String src, String holder) throws IOException { String src, String holder) throws IOException {
src = fsd.resolvePath(pc, src); final INodesInPath iip = fsd.resolvePath(pc, src, fileId);
src = iip.getPath();
final INode inode;
final INodesInPath iip;
if (fileId == HdfsConstants.GRANDFATHER_INODE_ID) {
// Older clients may not have given us an inode ID to work with.
// In this case, we have to try to resolve the path and hope it
// hasn't changed or been deleted since the file was opened for write.
iip = fsd.getINodesInPath(src, true);
inode = iip.getLastINode();
} else {
inode = fsd.getInode(fileId);
iip = INodesInPath.fromINode(inode);
if (inode != null) {
src = iip.getPath();
}
}
FSNamesystem fsn = fsd.getFSNamesystem(); FSNamesystem fsn = fsd.getFSNamesystem();
final INodeFile file = fsn.checkLease(src, holder, inode, fileId); final INodeFile file = fsn.checkLease(iip, holder, fileId);
Preconditions.checkState(file.isUnderConstruction()); Preconditions.checkState(file.isUnderConstruction());
Block localBlock = ExtendedBlock.getLocalBlock(b); Block localBlock = ExtendedBlock.getLocalBlock(b);
@ -178,8 +162,8 @@ class FSDirWriteFileOp {
final byte storagePolicyID; final byte storagePolicyID;
String clientMachine; String clientMachine;
src = fsn.dir.resolvePath(pc, src); INodesInPath iip = fsn.dir.resolvePath(pc, src, fileId);
FileState fileState = analyzeFileState(fsn, src, fileId, clientName, FileState fileState = analyzeFileState(fsn, iip, fileId, clientName,
previous, onRetryBlock); previous, onRetryBlock);
if (onRetryBlock[0] != null && onRetryBlock[0].getLocations().length > 0) { if (onRetryBlock[0] != null && onRetryBlock[0].getLocations().length > 0) {
// This is a retry. No need to generate new locations. // This is a retry. No need to generate new locations.
@ -229,7 +213,8 @@ class FSDirWriteFileOp {
// Run the full analysis again, since things could have changed // Run the full analysis again, since things could have changed
// while chooseTarget() was executing. // while chooseTarget() was executing.
LocatedBlock[] onRetryBlock = new LocatedBlock[1]; LocatedBlock[] onRetryBlock = new LocatedBlock[1];
FileState fileState = analyzeFileState(fsn, src, fileId, clientName, INodesInPath iip = fsn.dir.resolvePath(null, src, fileId);
FileState fileState = analyzeFileState(fsn, iip, fileId, clientName,
previous, onRetryBlock); previous, onRetryBlock);
final INodeFile pendingFile = fileState.inode; final INodeFile pendingFile = fileState.inode;
src = fileState.path; src = fileState.path;
@ -340,8 +325,8 @@ class FSDirWriteFileOp {
boolean isRawPath = FSDirectory.isReservedRawName(src); boolean isRawPath = FSDirectory.isReservedRawName(src);
FSDirectory fsd = fsn.getFSDirectory(); FSDirectory fsd = fsn.getFSDirectory();
src = fsd.resolvePath(pc, src); INodesInPath iip = fsd.resolvePathForWrite(pc, src);
INodesInPath iip = fsd.getINodesInPath4Write(src); src = iip.getPath();
// Verify that the destination does not exist as a directory already. // Verify that the destination does not exist as a directory already.
final INode inode = iip.getLastINode(); final INode inode = iip.getLastINode();
@ -450,8 +435,7 @@ class FSDirWriteFileOp {
CryptoProtocolVersion[] supportedVersions) CryptoProtocolVersion[] supportedVersions)
throws IOException { throws IOException {
FSDirectory fsd = fsn.getFSDirectory(); FSDirectory fsd = fsn.getFSDirectory();
src = fsd.resolvePath(pc, src); INodesInPath iip = fsd.resolvePathForWrite(pc, src);
INodesInPath iip = fsd.getINodesInPath4Write(src);
// Nothing to do if the path is not within an EZ // Nothing to do if the path is not within an EZ
final EncryptionZone zone = FSDirEncryptionZoneOp.getEZForPath(fsd, iip); final EncryptionZone zone = FSDirEncryptionZoneOp.getEZForPath(fsd, iip);
if (zone == null) { if (zone == null) {
@ -587,11 +571,11 @@ class FSDirWriteFileOp {
} }
private static FileState analyzeFileState( private static FileState analyzeFileState(
FSNamesystem fsn, String src, long fileId, String clientName, FSNamesystem fsn, INodesInPath iip, long fileId, String clientName,
ExtendedBlock previous, LocatedBlock[] onRetryBlock) ExtendedBlock previous, LocatedBlock[] onRetryBlock)
throws IOException { throws IOException {
assert fsn.hasReadLock(); assert fsn.hasReadLock();
String src = iip.getPath();
checkBlock(fsn, previous); checkBlock(fsn, previous);
onRetryBlock[0] = null; onRetryBlock[0] = null;
fsn.checkNameNodeSafeMode("Cannot add block to " + src); fsn.checkNameNodeSafeMode("Cannot add block to " + src);
@ -600,24 +584,7 @@ class FSDirWriteFileOp {
fsn.checkFsObjectLimit(); fsn.checkFsObjectLimit();
Block previousBlock = ExtendedBlock.getLocalBlock(previous); Block previousBlock = ExtendedBlock.getLocalBlock(previous);
final INode inode; final INodeFile file = fsn.checkLease(iip, clientName, fileId);
final INodesInPath iip;
if (fileId == HdfsConstants.GRANDFATHER_INODE_ID) {
// Older clients may not have given us an inode ID to work with.
// In this case, we have to try to resolve the path and hope it
// hasn't changed or been deleted since the file was opened for write.
iip = fsn.dir.getINodesInPath4Write(src);
inode = iip.getLastINode();
} else {
// Newer clients pass the inode ID, so we can just get the inode
// directly.
inode = fsn.dir.getInode(fileId);
iip = INodesInPath.fromINode(inode);
if (inode != null) {
src = iip.getPath();
}
}
final INodeFile file = fsn.checkLease(src, clientName, inode, fileId);
BlockInfo lastBlockInFile = file.getLastBlock(); BlockInfo lastBlockInFile = file.getLastBlock();
if (!Block.matchingIdAndGenStamp(previousBlock, lastBlockInFile)) { if (!Block.matchingIdAndGenStamp(previousBlock, lastBlockInFile)) {
// The block that the client claims is the current last block // The block that the client claims is the current last block
@ -696,8 +663,8 @@ class FSDirWriteFileOp {
src + " for " + holder); src + " for " + holder);
} }
checkBlock(fsn, last); checkBlock(fsn, last);
src = fsn.dir.resolvePath(pc, src); INodesInPath iip = fsn.dir.resolvePath(pc, src, fileId);
boolean success = completeFileInternal(fsn, src, holder, boolean success = completeFileInternal(fsn, iip, holder,
ExtendedBlock.getLocalBlock(last), ExtendedBlock.getLocalBlock(last),
fileId); fileId);
if (success) { if (success) {
@ -708,27 +675,16 @@ class FSDirWriteFileOp {
} }
private static boolean completeFileInternal( private static boolean completeFileInternal(
FSNamesystem fsn, String src, String holder, Block last, long fileId) FSNamesystem fsn, INodesInPath iip,
String holder, Block last, long fileId)
throws IOException { throws IOException {
assert fsn.hasWriteLock(); assert fsn.hasWriteLock();
final String src = iip.getPath();
final INodeFile pendingFile; final INodeFile pendingFile;
final INodesInPath iip;
INode inode = null; INode inode = null;
try { try {
if (fileId == HdfsConstants.GRANDFATHER_INODE_ID) { inode = iip.getLastINode();
// Older clients may not have given us an inode ID to work with. pendingFile = fsn.checkLease(iip, holder, fileId);
// In this case, we have to try to resolve the path and hope it
// hasn't changed or been deleted since the file was opened for write.
iip = fsn.dir.getINodesInPath(src, true);
inode = iip.getLastINode();
} else {
inode = fsn.dir.getInode(fileId);
iip = INodesInPath.fromINode(inode);
if (inode != null) {
src = iip.getPath();
}
}
pendingFile = fsn.checkLease(src, holder, inode, fileId);
} catch (LeaseExpiredException lee) { } catch (LeaseExpiredException lee) {
if (inode != null && inode.isFile() && if (inode != null && inode.isFile() &&
!inode.asFile().isUnderConstruction()) { !inode.asFile().isUnderConstruction()) {

View File

@ -67,13 +67,13 @@ class FSDirXAttrOp {
FSPermissionChecker pc = fsd.getPermissionChecker(); FSPermissionChecker pc = fsd.getPermissionChecker();
XAttrPermissionFilter.checkPermissionForApi( XAttrPermissionFilter.checkPermissionForApi(
pc, xAttr, FSDirectory.isReservedRawName(src)); pc, xAttr, FSDirectory.isReservedRawName(src));
src = fsd.resolvePath(pc, src);
List<XAttr> xAttrs = Lists.newArrayListWithCapacity(1); List<XAttr> xAttrs = Lists.newArrayListWithCapacity(1);
xAttrs.add(xAttr); xAttrs.add(xAttr);
INodesInPath iip; INodesInPath iip;
fsd.writeLock(); fsd.writeLock();
try { try {
iip = fsd.getINodesInPath4Write(src); iip = fsd.resolvePathForWrite(pc, src);
src = iip.getPath();
checkXAttrChangeAccess(fsd, iip, xAttr, pc); checkXAttrChangeAccess(fsd, iip, xAttr, pc);
unprotectedSetXAttrs(fsd, src, xAttrs, flag); unprotectedSetXAttrs(fsd, src, xAttrs, flag);
} finally { } finally {
@ -94,12 +94,11 @@ class FSDirXAttrOp {
if (!getAll) { if (!getAll) {
XAttrPermissionFilter.checkPermissionForApi(pc, xAttrs, isRawPath); XAttrPermissionFilter.checkPermissionForApi(pc, xAttrs, isRawPath);
} }
src = fsd.resolvePath(pc, src); final INodesInPath iip = fsd.resolvePath(pc, src);
final INodesInPath iip = fsd.getINodesInPath(src, true);
if (fsd.isPermissionEnabled()) { if (fsd.isPermissionEnabled()) {
fsd.checkPathAccess(pc, iip, FsAction.READ); fsd.checkPathAccess(pc, iip, FsAction.READ);
} }
List<XAttr> all = FSDirXAttrOp.getXAttrs(fsd, src); List<XAttr> all = FSDirXAttrOp.getXAttrs(fsd, iip);
List<XAttr> filteredAll = XAttrPermissionFilter. List<XAttr> filteredAll = XAttrPermissionFilter.
filterXAttrsForApi(pc, all, isRawPath); filterXAttrsForApi(pc, all, isRawPath);
@ -134,13 +133,12 @@ class FSDirXAttrOp {
FSDirXAttrOp.checkXAttrsConfigFlag(fsd); FSDirXAttrOp.checkXAttrsConfigFlag(fsd);
final FSPermissionChecker pc = fsd.getPermissionChecker(); final FSPermissionChecker pc = fsd.getPermissionChecker();
final boolean isRawPath = FSDirectory.isReservedRawName(src); final boolean isRawPath = FSDirectory.isReservedRawName(src);
src = fsd.resolvePath(pc, src); final INodesInPath iip = fsd.resolvePath(pc, src);
final INodesInPath iip = fsd.getINodesInPath(src, true);
if (fsd.isPermissionEnabled()) { if (fsd.isPermissionEnabled()) {
/* To access xattr names, you need EXECUTE in the owning directory. */ /* To access xattr names, you need EXECUTE in the owning directory. */
fsd.checkParentAccess(pc, iip, FsAction.EXECUTE); fsd.checkParentAccess(pc, iip, FsAction.EXECUTE);
} }
final List<XAttr> all = FSDirXAttrOp.getXAttrs(fsd, src); final List<XAttr> all = FSDirXAttrOp.getXAttrs(fsd, iip);
return XAttrPermissionFilter. return XAttrPermissionFilter.
filterXAttrsForApi(pc, all, isRawPath); filterXAttrsForApi(pc, all, isRawPath);
} }
@ -167,8 +165,8 @@ class FSDirXAttrOp {
INodesInPath iip; INodesInPath iip;
fsd.writeLock(); fsd.writeLock();
try { try {
src = fsd.resolvePath(pc, src); iip = fsd.resolvePathForWrite(pc, src);
iip = fsd.getINodesInPath4Write(src); src = iip.getPath();
checkXAttrChangeAccess(fsd, iip, xAttr, pc); checkXAttrChangeAccess(fsd, iip, xAttr, pc);
List<XAttr> removedXAttrs = unprotectedRemoveXAttrs(fsd, src, xAttrs); List<XAttr> removedXAttrs = unprotectedRemoveXAttrs(fsd, src, xAttrs);
@ -427,12 +425,11 @@ class FSDirXAttrOp {
} }
} }
private static List<XAttr> getXAttrs(FSDirectory fsd, private static List<XAttr> getXAttrs(FSDirectory fsd, INodesInPath iip)
String src) throws IOException { throws IOException {
String srcs = FSDirectory.normalizePath(src);
fsd.readLock(); fsd.readLock();
try { try {
INodesInPath iip = fsd.getINodesInPath(srcs, true); String src = iip.getPath();
INode inode = FSDirectory.resolveLastINode(iip); INode inode = FSDirectory.resolveLastINode(iip);
int snapshotId = iip.getPathSnapshotId(); int snapshotId = iip.getPathSnapshotId();
return XAttrStorage.readINodeXAttrs(fsd.getAttributes(src, return XAttrStorage.readINodeXAttrs(fsd.getAttributes(src,

View File

@ -129,6 +129,11 @@ public class FSDirectory implements Closeable {
null, null, null, HdfsFileStatus.EMPTY_NAME, -1L, 0, null, null, null, null, HdfsFileStatus.EMPTY_NAME, -1L, 0, null,
HdfsConstants.BLOCK_STORAGE_POLICY_ID_UNSPECIFIED); HdfsConstants.BLOCK_STORAGE_POLICY_ID_UNSPECIFIED);
public final static HdfsFileStatus DOT_SNAPSHOT_DIR_STATUS =
new HdfsFileStatus(0, true, 0, 0, 0, 0, null, null, null, null,
HdfsFileStatus.EMPTY_NAME, -1L, 0, null,
HdfsConstants.BLOCK_STORAGE_POLICY_ID_UNSPECIFIED);
INodeDirectory rootDir; INodeDirectory rootDir;
private final FSNamesystem namesystem; private final FSNamesystem namesystem;
private volatile boolean skipQuotaCheck = false; //skip while consuming edits private volatile boolean skipQuotaCheck = false; //skip while consuming edits
@ -486,12 +491,66 @@ public class FSDirectory implements Closeable {
* @throws FileNotFoundException * @throws FileNotFoundException
* @throws AccessControlException * @throws AccessControlException
*/ */
String resolvePath(FSPermissionChecker pc, String path) INodesInPath resolvePath(FSPermissionChecker pc, String src)
throws FileNotFoundException, AccessControlException { throws UnresolvedLinkException, FileNotFoundException,
if (isReservedRawName(path) && isPermissionEnabled) { AccessControlException {
return resolvePath(pc, src, true);
}
INodesInPath resolvePath(FSPermissionChecker pc, String src,
boolean resolveLink) throws UnresolvedLinkException,
FileNotFoundException, AccessControlException {
byte[][] components = INode.getPathComponents(src);
if (isPermissionEnabled && pc != null && isReservedRawName(components)) {
pc.checkSuperuserPrivilege(); pc.checkSuperuserPrivilege();
} }
return resolvePath(path, this); components = resolveComponents(components, this);
return INodesInPath.resolve(rootDir, components, resolveLink);
}
INodesInPath resolvePathForWrite(FSPermissionChecker pc, String src)
throws UnresolvedLinkException, FileNotFoundException,
AccessControlException {
return resolvePathForWrite(pc, src, true);
}
INodesInPath resolvePathForWrite(FSPermissionChecker pc, String src,
boolean resolveLink) throws UnresolvedLinkException,
FileNotFoundException, AccessControlException {
INodesInPath iip = resolvePath(pc, src, resolveLink);
if (iip.isSnapshot()) {
throw new SnapshotAccessControlException(
"Modification on a read-only snapshot is disallowed");
}
return iip;
}
INodesInPath resolvePath(FSPermissionChecker pc, String src, long fileId)
throws UnresolvedLinkException, FileNotFoundException,
AccessControlException {
// Older clients may not have given us an inode ID to work with.
// In this case, we have to try to resolve the path and hope it
// hasn't changed or been deleted since the file was opened for write.
INodesInPath iip;
if (fileId == HdfsConstants.GRANDFATHER_INODE_ID) {
iip = resolvePath(pc, src);
} else {
INode inode = getInode(fileId);
if (inode == null) {
iip = INodesInPath.fromComponents(INode.getPathComponents(src));
} else {
iip = INodesInPath.fromINode(inode);
}
}
return iip;
}
// this method can be removed after IIP is used more extensively
static String resolvePath(String src,
FSDirectory fsd) throws FileNotFoundException {
byte[][] pathComponents = INode.getPathComponents(src);
pathComponents = resolveComponents(pathComponents, fsd);
return DFSUtil.byteArray2PathString(pathComponents);
} }
/** /**
@ -1265,6 +1324,12 @@ public class FSDirectory implements Closeable {
return CHECK_RESERVED_FILE_NAMES && src.equals(DOT_RESERVED_PATH_PREFIX); return CHECK_RESERVED_FILE_NAMES && src.equals(DOT_RESERVED_PATH_PREFIX);
} }
public static boolean isExactReservedName(byte[][] components) {
return CHECK_RESERVED_FILE_NAMES &&
(components.length == 2) &&
isReservedName(components);
}
static boolean isReservedRawName(String src) { static boolean isReservedRawName(String src) {
return src.startsWith(DOT_RESERVED_PATH_PREFIX + return src.startsWith(DOT_RESERVED_PATH_PREFIX +
Path.SEPARATOR + RAW_STRING); Path.SEPARATOR + RAW_STRING);
@ -1276,11 +1341,17 @@ public class FSDirectory implements Closeable {
} }
static boolean isReservedName(byte[][] components) { static boolean isReservedName(byte[][] components) {
return (components.length > 2) && return (components.length > 1) &&
Arrays.equals(INodeDirectory.ROOT_NAME, components[0]) && Arrays.equals(INodeDirectory.ROOT_NAME, components[0]) &&
Arrays.equals(DOT_RESERVED, components[1]); Arrays.equals(DOT_RESERVED, components[1]);
} }
static boolean isReservedRawName(byte[][] components) {
return (components.length > 2) &&
isReservedName(components) &&
Arrays.equals(RAW, components[2]);
}
/** /**
* Resolve a /.reserved/... path to a non-reserved path. * Resolve a /.reserved/... path to a non-reserved path.
* <p/> * <p/>
@ -1299,19 +1370,18 @@ public class FSDirectory implements Closeable {
* /.reserved/raw/a/b/c is equivalent (they both refer to the same * /.reserved/raw/a/b/c is equivalent (they both refer to the same
* unencrypted file). * unencrypted file).
* *
* @param src path that is being processed * @param pathComponents to be resolved
* @param fsd FSDirectory * @param fsd FSDirectory
* @return if the path indicates an inode, return path after replacing up to * @return if the path indicates an inode, return path after replacing up to
* <inodeid> with the corresponding path of the inode, else the path * <inodeid> with the corresponding path of the inode, else the path
* in {@code src} as is. If the path refers to a path in the "raw" * in {@code pathComponents} as is. If the path refers to a path in
* directory, return the non-raw pathname. * the "raw" directory, return the non-raw pathname.
* @throws FileNotFoundException if inodeid is invalid * @throws FileNotFoundException if inodeid is invalid
*/ */
static String resolvePath(String src, static byte[][] resolveComponents(byte[][] pathComponents,
FSDirectory fsd) throws FileNotFoundException { FSDirectory fsd) throws FileNotFoundException {
byte[][] pathComponents = INode.getPathComponents(src);
final int nComponents = pathComponents.length; final int nComponents = pathComponents.length;
if (!isReservedName(pathComponents)) { if (nComponents < 3 || !isReservedName(pathComponents)) {
/* This is not a /.reserved/ path so do nothing. */ /* This is not a /.reserved/ path so do nothing. */
} else if (Arrays.equals(DOT_INODES, pathComponents[2])) { } else if (Arrays.equals(DOT_INODES, pathComponents[2])) {
/* It's a /.reserved/.inodes path. */ /* It's a /.reserved/.inodes path. */
@ -1332,9 +1402,7 @@ public class FSDirectory implements Closeable {
} }
} }
} }
// this double conversion will be unnecessary when resolving returns return pathComponents;
// INodesInPath (needs components byte[][])
return DFSUtil.byteArray2PathString(pathComponents);
} }
private static byte[][] resolveDotInodesPath( private static byte[][] resolveDotInodesPath(
@ -1388,15 +1456,12 @@ public class FSDirectory implements Closeable {
return components; return components;
} }
INode getINode4DotSnapshot(String src) throws UnresolvedLinkException { INode getINode4DotSnapshot(INodesInPath iip) throws UnresolvedLinkException {
Preconditions.checkArgument( Preconditions.checkArgument(
src.endsWith(HdfsConstants.SEPARATOR_DOT_SNAPSHOT_DIR), iip.isDotSnapshotDir(), "%s does not end with %s",
"%s does not end with %s", src, HdfsConstants.SEPARATOR_DOT_SNAPSHOT_DIR); iip.getPath(), HdfsConstants.SEPARATOR_DOT_SNAPSHOT_DIR);
final String dirPath = normalizePath(src.substring(0, final INode node = iip.getINode(-2);
src.length() - HdfsConstants.DOT_SNAPSHOT_DIR.length()));
final INode node = this.getINode(dirPath);
if (node != null && node.isDirectory() if (node != null && node.isDirectory()
&& node.asDirectory().isSnapshottable()) { && node.asDirectory().isSnapshottable()) {
return node; return node;

View File

@ -1835,8 +1835,9 @@ public class FSNamesystem implements Namesystem, FSNamesystemMBean,
* HDFS-7463. A better fix is to change the edit log of SetTime to * HDFS-7463. A better fix is to change the edit log of SetTime to
* use inode id instead of a path. * use inode id instead of a path.
*/ */
src = dir.resolvePath(pc, srcArg); final INodesInPath iip = dir.resolvePath(pc, srcArg);
final INodesInPath iip = dir.getINodesInPath(src, true); src = iip.getPath();
INode inode = iip.getLastINode(); INode inode = iip.getLastINode();
boolean updateAccessTime = inode != null && boolean updateAccessTime = inode != null &&
now > inode.getAccessTime() + dir.getAccessTimePrecision(); now > inode.getAccessTime() + dir.getAccessTimePrecision();
@ -2317,8 +2318,8 @@ public class FSNamesystem implements Namesystem, FSNamesystemMBean,
try { try {
checkOperation(OperationCategory.WRITE); checkOperation(OperationCategory.WRITE);
checkNameNodeSafeMode("Cannot recover the lease of " + src); checkNameNodeSafeMode("Cannot recover the lease of " + src);
src = dir.resolvePath(pc, src); final INodesInPath iip = dir.resolvePathForWrite(pc, src);
final INodesInPath iip = dir.getINodesInPath4Write(src); src = iip.getPath();
final INodeFile inode = INodeFile.valueOf(iip.getLastINode(), src); final INodeFile inode = INodeFile.valueOf(iip.getLastINode(), src);
if (!inode.isUnderConstruction()) { if (!inode.isUnderConstruction()) {
return true; return true;
@ -2569,20 +2570,11 @@ public class FSNamesystem implements Namesystem, FSNamesystemMBean,
checkOperation(OperationCategory.READ); checkOperation(OperationCategory.READ);
//check safe mode //check safe mode
checkNameNodeSafeMode("Cannot add datanode; src=" + src + ", blk=" + blk); checkNameNodeSafeMode("Cannot add datanode; src=" + src + ", blk=" + blk);
src = dir.resolvePath(pc, src); final INodesInPath iip = dir.resolvePath(pc, src, fileId);
src = iip.getPath();
//check lease //check lease
final INode inode; final INodeFile file = checkLease(iip, clientName, fileId);
if (fileId == HdfsConstants.GRANDFATHER_INODE_ID) {
// Older clients may not have given us an inode ID to work with.
// In this case, we have to try to resolve the path and hope it
// hasn't changed or been deleted since the file was opened for write.
inode = dir.getINode(src);
} else {
inode = dir.getInode(fileId);
if (inode != null) src = inode.getFullPathName();
}
final INodeFile file = checkLease(src, clientName, inode, fileId);
clientMachine = file.getFileUnderConstructionFeature().getClientMachine(); clientMachine = file.getFileUnderConstructionFeature().getClientMachine();
clientnode = blockManager.getDatanodeManager().getDatanodeByHost(clientMachine); clientnode = blockManager.getDatanodeManager().getDatanodeByHost(clientMachine);
preferredblocksize = file.getPreferredBlockSize(); preferredblocksize = file.getPreferredBlockSize();
@ -2640,8 +2632,10 @@ public class FSNamesystem implements Namesystem, FSNamesystemMBean,
: "Holder " + holder + " does not have any open files."); : "Holder " + holder + " does not have any open files.");
} }
INodeFile checkLease(String src, String holder, INode inode, long fileId) INodeFile checkLease(INodesInPath iip, String holder, long fileId)
throws LeaseExpiredException, FileNotFoundException { throws LeaseExpiredException, FileNotFoundException {
String src = iip.getPath();
INode inode = iip.getLastINode();
assert hasReadLock(); assert hasReadLock();
if (inode == null) { if (inode == null) {
throw new FileNotFoundException("File does not exist: " throw new FileNotFoundException("File does not exist: "
@ -3128,18 +3122,9 @@ public class FSNamesystem implements Namesystem, FSNamesystemMBean,
try { try {
checkOperation(OperationCategory.WRITE); checkOperation(OperationCategory.WRITE);
checkNameNodeSafeMode("Cannot fsync file " + src); checkNameNodeSafeMode("Cannot fsync file " + src);
src = dir.resolvePath(pc, src); INodesInPath iip = dir.resolvePath(pc, src, fileId);
final INode inode; src = iip.getPath();
if (fileId == HdfsConstants.GRANDFATHER_INODE_ID) { final INodeFile pendingFile = checkLease(iip, clientName, fileId);
// Older clients may not have given us an inode ID to work with.
// In this case, we have to try to resolve the path and hope it
// hasn't changed or been deleted since the file was opened for write.
inode = dir.getINode(src);
} else {
inode = dir.getInode(fileId);
if (inode != null) src = inode.getFullPathName();
}
final INodeFile pendingFile = checkLease(src, clientName, inode, fileId);
if (lastBlockLength > 0) { if (lastBlockLength > 0) {
pendingFile.getFileUnderConstructionFeature().updateLengthOfLastBlock( pendingFile.getFileUnderConstructionFeature().updateLengthOfLastBlock(
pendingFile, lastBlockLength); pendingFile, lastBlockLength);
@ -7463,17 +7448,17 @@ public class FSNamesystem implements Namesystem, FSNamesystemMBean,
void checkAccess(String src, FsAction mode) throws IOException { void checkAccess(String src, FsAction mode) throws IOException {
checkOperation(OperationCategory.READ); checkOperation(OperationCategory.READ);
FSPermissionChecker pc = getPermissionChecker();
readLock(); readLock();
try { try {
checkOperation(OperationCategory.READ); checkOperation(OperationCategory.READ);
src = FSDirectory.resolvePath(src, dir); final INodesInPath iip = dir.resolvePath(pc, src);
final INodesInPath iip = dir.getINodesInPath(src, true); src = iip.getPath();
INode inode = iip.getLastINode(); INode inode = iip.getLastINode();
if (inode == null) { if (inode == null) {
throw new FileNotFoundException("Path not found"); throw new FileNotFoundException("Path not found");
} }
if (isPermissionEnabled) { if (isPermissionEnabled) {
FSPermissionChecker pc = getPermissionChecker();
dir.checkPathAccess(pc, iip, mode); dir.checkPathAccess(pc, iip, mode);
} }
} catch (AccessControlException e) { } catch (AccessControlException e) {

View File

@ -73,6 +73,10 @@ public class INodesInPath {
return new INodesInPath(inodes, path); return new INodesInPath(inodes, path);
} }
static INodesInPath fromComponents(byte[][] components) {
return new INodesInPath(new INode[components.length], components);
}
/** /**
* Given some components, create a path name. * Given some components, create a path name.
* @param components The path components * @param components The path components
@ -434,6 +438,10 @@ public class INodesInPath {
return this.isSnapshot; return this.isSnapshot;
} }
boolean isDotSnapshotDir() {
return isDotSnapshotDir(getLastLocalName());
}
private static String toString(INode inode) { private static String toString(INode inode) {
return inode == null? null: inode.getLocalName(); return inode == null? null: inode.getLocalName();
} }

View File

@ -25,7 +25,6 @@ import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;
import static org.mockito.Matchers.any; import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Matchers.anyLong; import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
@ -1200,7 +1199,7 @@ public class TestFsck {
when(fsName.getBlockManager()).thenReturn(blockManager); when(fsName.getBlockManager()).thenReturn(blockManager);
when(fsName.getFSDirectory()).thenReturn(fsd); when(fsName.getFSDirectory()).thenReturn(fsd);
when(fsd.getFSNamesystem()).thenReturn(fsName); when(fsd.getFSNamesystem()).thenReturn(fsName);
when(fsd.getINodesInPath(anyString(), anyBoolean())).thenReturn(iip); when(fsd.resolvePath(any(FSPermissionChecker.class), anyString())).thenReturn(iip);
when(blockManager.getDatanodeManager()).thenReturn(dnManager); when(blockManager.getDatanodeManager()).thenReturn(dnManager);
NamenodeFsck fsck = new NamenodeFsck(conf, namenode, nettop, pmap, out, NamenodeFsck fsck = new NamenodeFsck(conf, namenode, nettop, pmap, out,