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

This commit is contained in:
Zhe Zhang 2016-10-05 16:01:02 -07:00
parent 23d4351174
commit 47fcae7da8
12 changed files with 246 additions and 231 deletions

View File

@ -47,6 +47,9 @@ Release 2.7.4 - UNRELEASED
HDFS-9145. Tracking methods that hold FSNamesytemLock for too long. HDFS-9145. Tracking methods that hold FSNamesytemLock for too long.
(Mingliang Liu via Haohui Mai) (Mingliang Liu via Haohui Mai)
HDFS-10745. Directly resolve paths into INodesInPath.
(Daryn Sharp via kihwal)
OPTIMIZATIONS OPTIMIZATIONS
HDFS-10896. Move lock logging logic from FSNamesystem into FSNamesystemLock. HDFS-10896. Move lock logging logic from FSNamesystem into FSNamesystemLock.

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

@ -55,8 +55,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 {
@ -73,8 +73,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)) {
@ -107,8 +107,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);
@ -137,8 +137,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);
} }
@ -200,8 +200,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

@ -78,8 +78,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

@ -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

@ -48,8 +48,8 @@ static DirectoryListing getListingInt(FSDirectory fsd, final String srcArg,
byte[] startAfter, boolean needLocation) throws IOException { byte[] startAfter, boolean needLocation) throws IOException {
FSPermissionChecker pc = fsd.getPermissionChecker(); FSPermissionChecker pc = fsd.getPermissionChecker();
final String startAfterString = DFSUtil.bytes2String(startAfter); final String startAfterString = DFSUtil.bytes2String(startAfter);
final String src = fsd.resolvePath(pc, srcArg); final INodesInPath iip = fsd.resolvePath(pc, srcArg);
final INodesInPath iip = fsd.getINodesInPath(src, true); final String src = iip.getPath();
// Get file name when startAfter is an INodePath // Get file name when startAfter is an INodePath
if (FSDirectory.isReservedName(startAfterString)) { if (FSDirectory.isReservedName(startAfterString)) {
@ -93,16 +93,16 @@ static HdfsFileStatus getFileInfo(
if (!DFSUtil.isValidName(src)) { if (!DFSUtil.isValidName(src)) {
throw new InvalidPathException("Invalid file name: " + src); throw new InvalidPathException("Invalid file name: " + src);
} }
FSPermissionChecker pc = fsd.getPermissionChecker();
src = fsd.resolvePath(pc, srcArg);
final INodesInPath iip = fsd.getINodesInPath(src, resolveLink);
boolean isSuperUser = true;
if (fsd.isPermissionEnabled()) { if (fsd.isPermissionEnabled()) {
FSPermissionChecker pc = fsd.getPermissionChecker();
final INodesInPath iip = fsd.resolvePath(pc, srcArg, resolveLink);
src = iip.getPath();
fsd.checkPermission(pc, iip, false, null, null, null, null, false); fsd.checkPermission(pc, iip, false, null, null, null, null, false);
isSuperUser = pc.isSuperUser(); } else {
src = FSDirectory.resolvePath(srcArg, fsd);
} }
return getFileInfo(fsd, src, resolveLink, return getFileInfo(fsd, src, FSDirectory.isReservedRawName(srcArg),
FSDirectory.isReservedRawName(srcArg), isSuperUser); resolveLink);
} }
/** /**
@ -110,8 +110,8 @@ 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); src = iip.getPath();
if (fsd.isPermissionEnabled()) { if (fsd.isPermissionEnabled()) {
fsd.checkTraverse(pc, iip); fsd.checkTraverse(pc, iip);
} }
@ -121,8 +121,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);
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);
@ -270,54 +269,55 @@ private static DirectoryListing getSnapshotsListing(
/** Get the file info for a specific file. /** Get the file info for a specific file.
* @param fsd FSDirectory * @param fsd FSDirectory
* @param iip The path to the file, the file is included * @param src The path to the file, the file is included
* @param isRawPath true if a /.reserved/raw pathname was passed by the user * @param isRawPath true if a /.reserved/raw pathname was passed by the user
* @param includeStoragePolicy whether to include storage policy * @param includeStoragePolicy whether to include storage policy
* @return object containing information regarding the file * @return object containing information regarding the file
* or null if file not found * or null if file not found
*/ */
static HdfsFileStatus getFileInfo( static HdfsFileStatus getFileInfo(
FSDirectory fsd, String path, INodesInPath iip, boolean isRawPath, FSDirectory fsd, String path, INodesInPath src, boolean isRawPath,
boolean includeStoragePolicy) boolean includeStoragePolicy)
throws IOException { throws IOException {
fsd.readLock(); fsd.readLock();
try { try {
final INode node = iip.getLastINode(); final INode i = src.getLastINode();
if (node == null) { if (i == null) {
return null; return null;
} }
byte policyId = includeStoragePolicy && !node.isSymlink() ? byte policyId = includeStoragePolicy && !i.isSymlink() ?
node.getStoragePolicyID() : i.getStoragePolicyID() :
BlockStoragePolicySuite.ID_UNSPECIFIED; BlockStoragePolicySuite.ID_UNSPECIFIED;
INodeAttributes nodeAttrs = getINodeAttributes(fsd, path, INodeAttributes nodeAttrs = getINodeAttributes(fsd, path,
HdfsFileStatus.EMPTY_NAME, HdfsFileStatus.EMPTY_NAME,
node, iip.getPathSnapshotId()); i, src.getPathSnapshotId());
return createFileStatus(fsd, HdfsFileStatus.EMPTY_NAME, nodeAttrs, return createFileStatus(fsd, HdfsFileStatus.EMPTY_NAME, nodeAttrs,
policyId, iip.getPathSnapshotId(), isRawPath, iip); policyId, src.getPathSnapshotId(), isRawPath, src);
} finally { } finally {
fsd.readUnlock(); fsd.readUnlock();
} }
} }
static HdfsFileStatus getFileInfo( static HdfsFileStatus getFileInfo(
FSDirectory fsd, String src, boolean resolveLink, boolean isRawPath, FSDirectory fsd, String src, boolean resolveLink, boolean isRawPath)
boolean includeStoragePolicy)
throws IOException { throws IOException {
String srcs = FSDirectory.normalizePath(src);
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,
BlockStoragePolicySuite.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, includeStoragePolicy); final INodesInPath iip = fsd.getINodesInPath(src, resolveLink);
if (FSDirectory.isExactReservedName(iip.getPathComponents())) {
status = new HdfsFileStatus(0, true, 0, 0, 0, 0, new FsPermission((short) 01770),
null, null, null, HdfsFileStatus.EMPTY_NAME, -1L, 0, null,
BlockStoragePolicySuite.ID_UNSPECIFIED);
} 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();
} }

View File

@ -55,8 +55,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

@ -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);
@ -133,13 +132,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);
} }
@ -166,8 +164,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);
@ -438,12 +436,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

@ -130,6 +130,11 @@ private static INodeDirectory createRoot(FSNamesystem namesystem) {
private final static byte[] DOT_DOT = private final static byte[] DOT_DOT =
DFSUtil.string2Bytes(".."); DFSUtil.string2Bytes("..");
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,
BlockStoragePolicySuite.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
@ -565,12 +570,66 @@ boolean unprotectedRemoveBlock(String path, INodesInPath iip,
* @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 == INodeId.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);
} }
/** /**
@ -1426,17 +1485,29 @@ public static boolean isReservedName(String src) {
return src.startsWith(DOT_RESERVED_PATH_PREFIX + Path.SEPARATOR); return src.startsWith(DOT_RESERVED_PATH_PREFIX + Path.SEPARATOR);
} }
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);
} }
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/>
@ -1455,19 +1526,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. */
@ -1483,9 +1553,7 @@ static String resolvePath(String src,
new byte[][]{INodeDirectory.ROOT_NAME}, pathComponents, 3); new byte[][]{INodeDirectory.ROOT_NAME}, pathComponents, 3);
} }
} }
// 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(
@ -1539,15 +1607,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

@ -1740,8 +1740,8 @@ 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, src);
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() + getAccessTimePrecision(); now > inode.getAccessTime() + getAccessTimePrecision();
@ -1817,8 +1817,8 @@ private GetBlockLocationsResult getBlockLocationsInt(
boolean needBlockToken) boolean needBlockToken)
throws IOException { throws IOException {
String src = srcArg; String src = srcArg;
src = dir.resolvePath(pc, srcArg); final INodesInPath iip = dir.resolvePath(pc, src);
final INodesInPath iip = dir.getINodesInPath(src, true); src = iip.getPath();
final INodeFile inode = INodeFile.valueOf(iip.getLastINode(), src); final INodeFile inode = INodeFile.valueOf(iip.getLastINode(), src);
if (isPermissionEnabled) { if (isPermissionEnabled) {
dir.checkPathAccess(pc, iip, FsAction.READ); dir.checkPathAccess(pc, iip, FsAction.READ);
@ -2016,7 +2016,8 @@ boolean truncateInt(String srcArg, long newLength,
try { try {
checkOperation(OperationCategory.WRITE); checkOperation(OperationCategory.WRITE);
checkNameNodeSafeMode("Cannot truncate for " + src); checkNameNodeSafeMode("Cannot truncate for " + src);
src = dir.resolvePath(pc, src); INodesInPath iip = dir.resolvePath(pc, src);
src = iip.getPath();
res = truncateInternal(src, newLength, clientName, res = truncateInternal(src, newLength, clientName,
clientMachine, mtime, pc, toRemoveBlocks); clientMachine, mtime, pc, toRemoveBlocks);
stat = dir.getAuditFileInfo(dir.getINodesInPath4Write(src, false)); stat = dir.getAuditFileInfo(dir.getINodesInPath4Write(src, false));
@ -2399,8 +2400,8 @@ private HdfsFileStatus startFileInt(final String srcArg,
if (provider != null) { if (provider != null) {
readLock(); readLock();
try { try {
src = dir.resolvePath(pc, src); INodesInPath iip = dir.resolvePathForWrite(pc, src);
INodesInPath iip = dir.getINodesInPath4Write(src); src = iip.getPath();
// 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 = dir.getEZForPath(iip); final EncryptionZone zone = dir.getEZForPath(iip);
if (zone != null) { if (zone != null) {
@ -2437,8 +2438,8 @@ private HdfsFileStatus startFileInt(final String srcArg,
checkNameNodeSafeMode("Cannot create file" + src); checkNameNodeSafeMode("Cannot create file" + src);
dir.writeLock(); dir.writeLock();
try { try {
src = dir.resolvePath(pc, src); final INodesInPath iip = dir.resolvePathForWrite(pc, src);
final INodesInPath iip = dir.getINodesInPath4Write(src); src = iip.getPath();
toRemoveBlocks = startFileInternal( toRemoveBlocks = startFileInternal(
pc, iip, permissions, holder, pc, iip, permissions, holder,
clientMachine, create, overwrite, clientMachine, create, overwrite,
@ -2446,7 +2447,7 @@ private HdfsFileStatus startFileInt(final String srcArg,
isLazyPersist, suite, protocolVersion, edek, isLazyPersist, suite, protocolVersion, edek,
logRetryCache); logRetryCache);
stat = FSDirStatAndListingOp.getFileInfo( stat = FSDirStatAndListingOp.getFileInfo(
dir, src, false, FSDirectory.isReservedRawName(srcArg), true); dir, src, false, FSDirectory.isReservedRawName(srcArg));
} finally { } finally {
dir.writeUnlock(); dir.writeUnlock();
} }
@ -2815,8 +2816,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;
@ -2967,12 +2968,12 @@ private LastBlockWithStatus appendFileInt(final String srcArg, String holder,
try { try {
checkOperation(OperationCategory.WRITE); checkOperation(OperationCategory.WRITE);
checkNameNodeSafeMode("Cannot append to file" + src); checkNameNodeSafeMode("Cannot append to file" + src);
src = dir.resolvePath(pc, src); final INodesInPath iip = dir.resolvePathForWrite(pc, src);
final INodesInPath iip = dir.getINodesInPath4Write(src); src = iip.getPath();
lb = appendFileInternal(pc, iip, holder, clientMachine, newBlock, lb = appendFileInternal(pc, iip, holder, clientMachine, newBlock,
logRetryCache); logRetryCache);
stat = FSDirStatAndListingOp.getFileInfo(dir, src, false, stat = FSDirStatAndListingOp.getFileInfo(dir, src, false,
FSDirectory.isReservedRawName(srcArg), true); FSDirectory.isReservedRawName(srcArg));
} catch (StandbyException se) { } catch (StandbyException se) {
skipSync = true; skipSync = true;
throw se; throw se;
@ -3056,9 +3057,10 @@ DatanodeStorageInfo[] getNewBlockTargets(String src, long fileId,
readLock(); readLock();
try { try {
checkOperation(OperationCategory.READ); checkOperation(OperationCategory.READ);
src = dir.resolvePath(pc, src); INodesInPath iip = dir.resolvePath(pc, src, fileId);
src = iip.getPath();
FileState fileState = analyzeFileState( FileState fileState = analyzeFileState(
src, fileId, clientName, previous, onRetryBlock); iip, fileId, clientName, 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.
// Use the last block if it has locations. // Use the last block if it has locations.
@ -3117,8 +3119,9 @@ LocatedBlock storeAllocatedBlock(String src, long fileId, String clientName,
// 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];
final INodesInPath iip = dir.resolvePath(null, src, fileId);
FileState fileState = FileState fileState =
analyzeFileState(src, fileId, clientName, previous, onRetryBlock); analyzeFileState(iip, fileId, clientName, previous, onRetryBlock);
final INodeFile pendingFile = fileState.inode; final INodeFile pendingFile = fileState.inode;
src = fileState.path; src = fileState.path;
@ -3186,14 +3189,12 @@ public FileState(INodeFile inode, String fullPath, INodesInPath iip) {
} }
} }
FileState analyzeFileState(String src, private FileState analyzeFileState(
long fileId, INodesInPath iip, long fileId, String clientName,
String clientName, ExtendedBlock previous, LocatedBlock[] onRetryBlock)
ExtendedBlock previous,
LocatedBlock[] onRetryBlock)
throws IOException { throws IOException {
assert hasReadLock(); assert hasReadLock();
String src = iip.getPath();
checkBlock(previous); checkBlock(previous);
onRetryBlock[0] = null; onRetryBlock[0] = null;
checkNameNodeSafeMode("Cannot add block to " + src); checkNameNodeSafeMode("Cannot add block to " + src);
@ -3202,24 +3203,7 @@ FileState analyzeFileState(String src,
checkFsObjectLimit(); checkFsObjectLimit();
Block previousBlock = ExtendedBlock.getLocalBlock(previous); Block previousBlock = ExtendedBlock.getLocalBlock(previous);
final INode inode; final INodeFile pendingFile = checkLease(iip, clientName, fileId);
final INodesInPath iip;
if (fileId == INodeId.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 = dir.getINodesInPath4Write(src);
inode = iip.getLastINode();
} else {
// Newer clients pass the inode ID, so we can just get the inode
// directly.
inode = dir.getInode(fileId);
iip = INodesInPath.fromINode(inode);
if (inode != null) {
src = iip.getPath();
}
}
final INodeFile pendingFile = checkLease(src, clientName, inode, fileId);
BlockInfoContiguous lastBlockInFile = pendingFile.getLastBlock(); BlockInfoContiguous lastBlockInFile = pendingFile.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
@ -3317,20 +3301,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 == INodeId.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();
@ -3369,27 +3344,12 @@ boolean abandonBlock(ExtendedBlock b, long fileId, String src, String holder)
FSPermissionChecker pc = getPermissionChecker(); FSPermissionChecker pc = getPermissionChecker();
waitForLoadingFSImage(); waitForLoadingFSImage();
writeLock(); writeLock();
final INodesInPath iip = dir.resolvePath(pc, src, fileId);
src = iip.getPath();
try { try {
checkOperation(OperationCategory.WRITE); checkOperation(OperationCategory.WRITE);
checkNameNodeSafeMode("Cannot abandon block " + b + " for file" + src); checkNameNodeSafeMode("Cannot abandon block " + b + " for file" + src);
src = dir.resolvePath(pc, src); final INodeFile file = checkLease(iip, holder, fileId);
final INode inode;
final INodesInPath iip;
if (fileId == INodeId.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 = dir.getINodesInPath(src, true);
inode = iip.getLastINode();
} else {
inode = dir.getInode(fileId);
iip = INodesInPath.fromINode(inode);
if (inode != null) {
src = iip.getPath();
}
}
final INodeFile file = checkLease(src, holder, inode, fileId);
// Remove the block from the pending creates list // Remove the block from the pending creates list
boolean removed = dir.removeBlock(src, iip, file, boolean removed = dir.removeBlock(src, iip, file,
@ -3408,8 +3368,10 @@ boolean abandonBlock(ExtendedBlock b, long fileId, String src, String holder)
return true; return true;
} }
private INodeFile checkLease(String src, String holder, INode inode, private INodeFile checkLease(INodesInPath iip, String holder, long fileId)
long fileId) throws LeaseExpiredException, FileNotFoundException { throws LeaseExpiredException, FileNotFoundException {
String src = iip.getPath();
INode inode = iip.getLastINode();
assert hasReadLock(); assert hasReadLock();
final String ident = src + " (inode " + fileId + ")"; final String ident = src + " (inode " + fileId + ")";
if (inode == null) { if (inode == null) {
@ -3463,13 +3425,11 @@ boolean completeFile(final String srcArg, String holder,
checkBlock(last); checkBlock(last);
boolean success = false; boolean success = false;
checkOperation(OperationCategory.WRITE); checkOperation(OperationCategory.WRITE);
FSPermissionChecker pc = getPermissionChecker();
waitForLoadingFSImage(); waitForLoadingFSImage();
writeLock(); writeLock();
try { try {
checkOperation(OperationCategory.WRITE); checkOperation(OperationCategory.WRITE);
checkNameNodeSafeMode("Cannot complete file " + src); checkNameNodeSafeMode("Cannot complete file " + src);
src = dir.resolvePath(pc, src);
success = completeFileInternal(src, holder, success = completeFileInternal(src, holder,
ExtendedBlock.getLocalBlock(last), fileId); ExtendedBlock.getLocalBlock(last), fileId);
} finally { } finally {
@ -3487,23 +3447,13 @@ private boolean completeFileInternal(String src, String holder, Block last,
long fileId) throws IOException { long fileId) throws IOException {
assert hasWriteLock(); assert hasWriteLock();
final INodeFile pendingFile; final INodeFile pendingFile;
final INodesInPath iip; FSPermissionChecker pc = getPermissionChecker();
final INodesInPath iip = dir.resolvePath(pc, src, fileId);
src = iip.getPath();
INode inode = null; INode inode = null;
try { try {
if (fileId == INodeId.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 = dir.getINodesInPath(src, true);
inode = iip.getLastINode(); inode = iip.getLastINode();
} else { pendingFile = checkLease(iip, holder, fileId);
inode = dir.getInode(fileId);
iip = INodesInPath.fromINode(inode);
if (inode != null) {
src = iip.getPath();
}
}
pendingFile = 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()) {
@ -3967,18 +3917,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 == INodeId.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);
@ -8021,7 +7962,8 @@ private void createEncryptionZoneInt(final String srcArg, String cipher,
checkSuperuserPrivilege(); checkSuperuserPrivilege();
checkOperation(OperationCategory.WRITE); checkOperation(OperationCategory.WRITE);
checkNameNodeSafeMode("Cannot create encryption zone on " + src); checkNameNodeSafeMode("Cannot create encryption zone on " + src);
src = dir.resolvePath(pc, src); final INodesInPath iip = dir.resolvePathForWrite(pc, src);
src = iip.getPath();
final CipherSuite suite = CipherSuite.convert(cipher); final CipherSuite suite = CipherSuite.convert(cipher);
// For now this is hardcoded, as we only support one method. // For now this is hardcoded, as we only support one method.
@ -8032,7 +7974,6 @@ private void createEncryptionZoneInt(final String srcArg, String cipher,
List<XAttr> xAttrs = Lists.newArrayListWithCapacity(1); List<XAttr> xAttrs = Lists.newArrayListWithCapacity(1);
xAttrs.add(ezXAttr); xAttrs.add(ezXAttr);
getEditLog().logSetXAttrs(src, xAttrs, logRetryCache); getEditLog().logSetXAttrs(src, xAttrs, logRetryCache);
final INodesInPath iip = dir.getINodesInPath4Write(src, false);
resultingStat = dir.getAuditFileInfo(iip); resultingStat = dir.getAuditFileInfo(iip);
} finally { } finally {
writeUnlock(); writeUnlock();
@ -8059,8 +8000,7 @@ EncryptionZone getEZForPath(final String srcArg)
readLock(); readLock();
try { try {
checkOperation(OperationCategory.READ); checkOperation(OperationCategory.READ);
src = dir.resolvePath(pc, src); INodesInPath iip = dir.resolvePath(pc, src);
final INodesInPath iip = dir.getINodesInPath(src, true);
if (isPermissionEnabled) { if (isPermissionEnabled) {
dir.checkPathAccess(pc, iip, FsAction.READ); dir.checkPathAccess(pc, iip, FsAction.READ);
} }
@ -8161,17 +8101,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

@ -72,6 +72,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
@ -433,6 +437,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();
} }