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

This commit is contained in:
Kihwal Lee 2016-08-18 12:37:57 -05:00
parent d464483bf7
commit 922d045e11
16 changed files with 227 additions and 221 deletions

View File

@ -25,7 +25,6 @@
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 @@ static HdfsFileStatus modifyAclEntries(
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 @@ static HdfsFileStatus removeAclEntries(
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 @@ static HdfsFileStatus removeDefaultAcl(FSDirectory fsd, final String srcArg)
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 @@ static HdfsFileStatus removeAcl(FSDirectory fsd, final String srcArg)
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 @@ static HdfsFileStatus setAcl(
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 @@ static AclStatus getAclStatus(
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 @@ static LastBlockWithStatus appendFile(final FSNamesystem fsn,
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 @@ static HdfsFileStatus setPermission(
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 @@ static HdfsFileStatus setOwner(
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 @@ static HdfsFileStatus setTimes(
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 @@ static boolean setReplication(
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 @@ static BlockStoragePolicy getStoragePolicy(FSDirectory fsd, BlockManager bm,
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 @@ static long getPreferredBlockSize(FSDirectory fsd, String src)
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 @@ static BlocksMapUpdateInfo delete(
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 @@ static HdfsFileStatus createEncryptionZone(final FSDirectory fsd,
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 @@ static HdfsFileStatus createEncryptionZone(final FSDirectory fsd,
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 @@ static HdfsFileStatus mkdirs(FSNamesystem fsn, String src,
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 @@ static RenameOldResult renameToInt(
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 @@ static Map.Entry<BlocksMapUpdateInfo, HdfsFileStatus> renameToInt(
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 @@ static Map.Entry<BlocksMapUpdateInfo, HdfsFileStatus> renameToInt(
* @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 @@ static void renameTo(FSDirectory fsd, FSPermissionChecker pc, String src,
fsd.writeUnlock(); fsd.writeUnlock();
} }
fsd.getEditLog().logRename(src, dst, mtime, logRetryCache, options); fsd.getEditLog().logRename(src, dst, mtime, logRetryCache, options);
return dst;
} }
/** /**
@ -442,16 +446,17 @@ static boolean unprotectedRenameTo(FSDirectory fsd, String src, String dst,
@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 @@ static DirectoryListing getListingInt(FSDirectory fsd, final String srcArg,
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 @@ static DirectoryListing getListingInt(FSDirectory fsd, final String srcArg,
} }
} }
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 @@ static HdfsFileStatus getFileInfo(
} }
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 @@ static HdfsFileStatus getFileInfo(
*/ */
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 @@ static boolean isFileClosed(FSDirectory fsd, String src) throws IOException {
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 @@ static GetBlockLocationsResult getBlockLocations(
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);
@ -386,24 +386,20 @@ static HdfsFileStatus getFileInfo(
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();
} }
@ -614,8 +610,7 @@ static QuotaUsage getQuotaUsage(
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 @@ static HdfsFileStatus createSymlinkInt(
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

@ -77,8 +77,8 @@ static TruncateResult truncate(final FSNamesystem fsn, final String srcArg,
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.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.HdfsFileStatus; import org.apache.hadoop.hdfs.protocol.HdfsFileStatus;
import org.apache.hadoop.hdfs.protocol.LocatedBlock; import org.apache.hadoop.hdfs.protocol.LocatedBlock;
import org.apache.hadoop.hdfs.protocol.QuotaExceededException; import org.apache.hadoop.hdfs.protocol.QuotaExceededException;
@ -116,25 +115,10 @@ static void persistBlocks(
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);
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(); 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);
@ -177,8 +161,8 @@ static ValidateAddBlockResult validateAddBlock(
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.
@ -228,7 +212,8 @@ static LocatedBlock storeAllocatedBlock(FSNamesystem fsn, String src,
// 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;
@ -339,8 +324,8 @@ static HdfsFileStatus startFile(
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();
@ -449,8 +434,7 @@ static EncryptionKeyInfo getEncryptionKeyInfo(FSNamesystem fsn,
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) {
@ -583,11 +567,11 @@ private static INodesInPath addFile(
} }
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);
@ -596,24 +580,7 @@ private static FileState analyzeFileState(
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
@ -692,8 +659,8 @@ static boolean completeFile(FSNamesystem fsn, FSPermissionChecker pc,
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) {
@ -704,27 +671,16 @@ static boolean completeFile(FSNamesystem fsn, FSPermissionChecker pc,
} }
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) {
// 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.getINodesInPath(src, true);
inode = iip.getLastINode(); inode = iip.getLastINode();
} else { pendingFile = fsn.checkLease(iip, holder, fileId);
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 @@ static HdfsFileStatus setXAttr(
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 @@ static List<XAttr> getXAttrs(FSDirectory fsd, final String srcArg,
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 @@ static List<XAttr> listXAttrs(
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 @@ static HdfsFileStatus removeXAttr(
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 @@ private static void checkXAttrsConfigFlag(FSDirectory fsd) throws
} }
} }
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

@ -132,6 +132,11 @@ private static INodeDirectory createRoot(FSNamesystem namesystem) {
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
@ -526,12 +531,66 @@ void disableQuotaChecks() {
* @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);
} }
/** /**
@ -1305,6 +1364,12 @@ public static boolean isExactReservedName(String src) {
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);
@ -1316,11 +1381,17 @@ static boolean isReservedInodesName(String src) {
} }
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/>
@ -1339,19 +1410,18 @@ static boolean isReservedName(byte[][] components) {
* /.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. */
@ -1372,9 +1442,7 @@ static String resolvePath(String src,
} }
} }
} }
// 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(
@ -1428,15 +1496,12 @@ private static byte[][] constructRemainingPath(byte[][] components,
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

@ -1800,8 +1800,9 @@ LocatedBlocks getBlockLocations(String clientMachine, String srcArg,
* 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();
@ -2276,8 +2277,8 @@ boolean recoverLease(String src, String holder, String clientMachine)
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;
@ -2526,20 +2527,11 @@ LocatedBlock getAdditionalDatanode(String src, long fileId,
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();
@ -2596,8 +2588,10 @@ private String leaseExceptionString(String src, long fileId, String holder) {
: "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: "
@ -3031,18 +3025,9 @@ void fsync(String src, long fileId, String clientName, long lastBlockLength)
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);
@ -6700,17 +6685,17 @@ void removeXAttr(String src, XAttr xAttr, boolean logRetryCache)
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 @@ static INodesInPath fromINode(INode inode) {
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 @@ boolean isSnapshot() {
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

@ -24,7 +24,7 @@
import static org.junit.Assert.assertNull; 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.anyBoolean; import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
@ -1204,7 +1204,7 @@ public void testFsckFileNotFound() throws Exception {
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,