HDFS-10955. Pass IIP for FSDirAttr methods. Contributed by Daryn Sharp.

This commit is contained in:
Kihwal Lee 2016-10-06 16:31:29 -05:00
parent a28ffd0fde
commit e3a9666d28
3 changed files with 83 additions and 92 deletions

View File

@ -50,9 +50,8 @@ import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_STORAGE_POLICY_ENABLED_KE
public class FSDirAttrOp { public class FSDirAttrOp {
static HdfsFileStatus setPermission( static HdfsFileStatus setPermission(
FSDirectory fsd, final String srcArg, FsPermission permission) FSDirectory fsd, final String src, FsPermission permission)
throws IOException { throws IOException {
String src = srcArg;
if (FSDirectory.isExactReservedName(src)) { if (FSDirectory.isExactReservedName(src)) {
throw new InvalidPathException(src); throw new InvalidPathException(src);
} }
@ -61,13 +60,12 @@ public class FSDirAttrOp {
fsd.writeLock(); fsd.writeLock();
try { try {
iip = fsd.resolvePathForWrite(pc, src); iip = fsd.resolvePathForWrite(pc, src);
src = iip.getPath();
fsd.checkOwner(pc, iip); fsd.checkOwner(pc, iip);
unprotectedSetPermission(fsd, src, permission); unprotectedSetPermission(fsd, iip, permission);
} finally { } finally {
fsd.writeUnlock(); fsd.writeUnlock();
} }
fsd.getEditLog().logSetPermissions(src, permission); fsd.getEditLog().logSetPermissions(iip.getPath(), permission);
return fsd.getAuditFileInfo(iip); return fsd.getAuditFileInfo(iip);
} }
@ -82,7 +80,6 @@ public class FSDirAttrOp {
fsd.writeLock(); fsd.writeLock();
try { try {
iip = fsd.resolvePathForWrite(pc, src); iip = fsd.resolvePathForWrite(pc, 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)) {
@ -92,11 +89,11 @@ public class FSDirAttrOp {
throw new AccessControlException("User does not belong to " + group); throw new AccessControlException("User does not belong to " + group);
} }
} }
unprotectedSetOwner(fsd, src, username, group); unprotectedSetOwner(fsd, iip, username, group);
} finally { } finally {
fsd.writeUnlock(); fsd.writeUnlock();
} }
fsd.getEditLog().logSetOwner(src, username, group); fsd.getEditLog().logSetOwner(iip.getPath(), username, group);
return fsd.getAuditFileInfo(iip); return fsd.getAuditFileInfo(iip);
} }
@ -109,20 +106,18 @@ public class FSDirAttrOp {
fsd.writeLock(); fsd.writeLock();
try { try {
iip = fsd.resolvePathForWrite(pc, src); iip = fsd.resolvePathForWrite(pc, 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);
} }
final INode inode = iip.getLastINode(); final INode inode = iip.getLastINode();
if (inode == null) { if (inode == null) {
throw new FileNotFoundException("File/Directory " + src + throw new FileNotFoundException("File/Directory " + iip.getPath() +
" does not exist."); " does not exist.");
} }
boolean changed = unprotectedSetTimes(fsd, inode, mtime, atime, true, boolean changed = unprotectedSetTimes(fsd, iip, mtime, atime, true);
iip.getLatestSnapshotId());
if (changed) { if (changed) {
fsd.getEditLog().logTimes(src, mtime, atime); fsd.getEditLog().logTimes(iip.getPath(), mtime, atime);
} }
} finally { } finally {
fsd.writeUnlock(); fsd.writeUnlock();
@ -139,16 +134,15 @@ public class FSDirAttrOp {
fsd.writeLock(); fsd.writeLock();
try { try {
final INodesInPath iip = fsd.resolvePathForWrite(pc, src); final INodesInPath iip = fsd.resolvePathForWrite(pc, src);
src = iip.getPath();
if (fsd.isPermissionEnabled()) { if (fsd.isPermissionEnabled()) {
fsd.checkPathAccess(pc, iip, FsAction.WRITE); fsd.checkPathAccess(pc, iip, FsAction.WRITE);
} }
final BlockInfo[] blocks = unprotectedSetReplication(fsd, src, final BlockInfo[] blocks = unprotectedSetReplication(fsd, iip,
replication); replication);
isFile = blocks != null; isFile = blocks != null;
if (isFile) { if (isFile) {
fsd.getEditLog().logSetReplication(src, replication); fsd.getEditLog().logSetReplication(iip.getPath(), replication);
} }
} finally { } finally {
fsd.writeUnlock(); fsd.writeUnlock();
@ -186,15 +180,14 @@ public class FSDirAttrOp {
INodesInPath iip; INodesInPath iip;
fsd.writeLock(); fsd.writeLock();
try { try {
src = FSDirectory.resolvePath(src, fsd); iip = fsd.resolvePathForWrite(pc, src);
iip = fsd.getINodesInPath4Write(src);
if (fsd.isPermissionEnabled()) { if (fsd.isPermissionEnabled()) {
fsd.checkPathAccess(pc, iip, FsAction.WRITE); fsd.checkPathAccess(pc, iip, FsAction.WRITE);
} }
unprotectedSetStoragePolicy(fsd, bm, iip, policyId); unprotectedSetStoragePolicy(fsd, bm, iip, policyId);
fsd.getEditLog().logSetStoragePolicy(src, policyId); fsd.getEditLog().logSetStoragePolicy(iip.getPath(), policyId);
} finally { } finally {
fsd.writeUnlock(); fsd.writeUnlock();
} }
@ -232,11 +225,10 @@ public class FSDirAttrOp {
fsd.readLock(); fsd.readLock();
try { try {
final INodesInPath iip = fsd.resolvePath(pc, src, false); final INodesInPath iip = fsd.resolvePath(pc, src, false);
src = iip.getPath();
if (fsd.isPermissionEnabled()) { if (fsd.isPermissionEnabled()) {
fsd.checkTraverse(pc, iip); fsd.checkTraverse(pc, iip);
} }
return INodeFile.valueOf(iip.getLastINode(), src) return INodeFile.valueOf(iip.getLastINode(), iip.getPath())
.getPreferredBlockSize(); .getPreferredBlockSize();
} finally { } finally {
fsd.readUnlock(); fsd.readUnlock();
@ -250,14 +242,16 @@ public class FSDirAttrOp {
*/ */
static void setQuota(FSDirectory fsd, String src, long nsQuota, long ssQuota, static void setQuota(FSDirectory fsd, String src, long nsQuota, long ssQuota,
StorageType type) throws IOException { StorageType type) throws IOException {
if (fsd.isPermissionEnabled()) {
FSPermissionChecker pc = fsd.getPermissionChecker(); FSPermissionChecker pc = fsd.getPermissionChecker();
if (fsd.isPermissionEnabled()) {
pc.checkSuperuserPrivilege(); pc.checkSuperuserPrivilege();
} }
fsd.writeLock(); fsd.writeLock();
try { try {
INodeDirectory changed = unprotectedSetQuota(fsd, src, nsQuota, ssQuota, type); INodesInPath iip = fsd.resolvePathForWrite(pc, src);
INodeDirectory changed =
unprotectedSetQuota(fsd, iip, nsQuota, ssQuota, type);
if (changed != null) { if (changed != null) {
final QuotaCounts q = changed.getQuotaCounts(); final QuotaCounts q = changed.getQuotaCounts();
if (type == null) { if (type == null) {
@ -273,58 +267,40 @@ public class FSDirAttrOp {
} }
static void unprotectedSetPermission( static void unprotectedSetPermission(
FSDirectory fsd, String src, FsPermission permissions) FSDirectory fsd, INodesInPath iip, FsPermission permissions)
throws FileNotFoundException, UnresolvedLinkException, throws FileNotFoundException, UnresolvedLinkException,
QuotaExceededException, SnapshotAccessControlException { QuotaExceededException, SnapshotAccessControlException {
assert fsd.hasWriteLock(); assert fsd.hasWriteLock();
final INodesInPath inodesInPath = fsd.getINodesInPath4Write(src, true); final INode inode = FSDirectory.resolveLastINode(iip);
final INode inode = inodesInPath.getLastINode(); int snapshotId = iip.getLatestSnapshotId();
if (inode == null) {
throw new FileNotFoundException("File does not exist: " + src);
}
int snapshotId = inodesInPath.getLatestSnapshotId();
inode.setPermission(permissions, snapshotId); inode.setPermission(permissions, snapshotId);
} }
static void unprotectedSetOwner( static void unprotectedSetOwner(
FSDirectory fsd, String src, String username, String groupname) FSDirectory fsd, INodesInPath iip, String username, String groupname)
throws FileNotFoundException, UnresolvedLinkException, throws FileNotFoundException, UnresolvedLinkException,
QuotaExceededException, SnapshotAccessControlException { QuotaExceededException, SnapshotAccessControlException {
assert fsd.hasWriteLock(); assert fsd.hasWriteLock();
final INodesInPath inodesInPath = fsd.getINodesInPath4Write(src, true); final INode inode = FSDirectory.resolveLastINode(iip);
INode inode = inodesInPath.getLastINode();
if (inode == null) {
throw new FileNotFoundException("File does not exist: " + src);
}
if (username != null) { if (username != null) {
inode = inode.setUser(username, inodesInPath.getLatestSnapshotId()); inode.setUser(username, iip.getLatestSnapshotId());
} }
if (groupname != null) { if (groupname != null) {
inode.setGroup(groupname, inodesInPath.getLatestSnapshotId()); inode.setGroup(groupname, iip.getLatestSnapshotId());
} }
} }
static boolean setTimes( static boolean setTimes(
FSDirectory fsd, INode inode, long mtime, long atime, boolean force, FSDirectory fsd, INodesInPath iip, long mtime, long atime, boolean force)
int latestSnapshotId) throws QuotaExceededException { throws QuotaExceededException {
fsd.writeLock(); fsd.writeLock();
try { try {
return unprotectedSetTimes(fsd, inode, mtime, atime, force, return unprotectedSetTimes(fsd, iip, mtime, atime, force);
latestSnapshotId);
} finally { } finally {
fsd.writeUnlock(); fsd.writeUnlock();
} }
} }
static boolean unprotectedSetTimes(
FSDirectory fsd, String src, long mtime, long atime, boolean force)
throws UnresolvedLinkException, QuotaExceededException {
assert fsd.hasWriteLock();
final INodesInPath i = fsd.getINodesInPath(src, true);
return unprotectedSetTimes(fsd, i.getLastINode(), mtime, atime,
force, i.getLatestSnapshotId());
}
/** /**
* See {@link org.apache.hadoop.hdfs.protocol.ClientProtocol#setQuota(String, * See {@link org.apache.hadoop.hdfs.protocol.ClientProtocol#setQuota(String,
* long, long, StorageType)} * long, long, StorageType)}
@ -339,7 +315,8 @@ public class FSDirAttrOp {
* @throws SnapshotAccessControlException if path is in RO snapshot * @throws SnapshotAccessControlException if path is in RO snapshot
*/ */
static INodeDirectory unprotectedSetQuota( static INodeDirectory unprotectedSetQuota(
FSDirectory fsd, String src, long nsQuota, long ssQuota, StorageType type) FSDirectory fsd, INodesInPath iip, long nsQuota,
long ssQuota, StorageType type)
throws FileNotFoundException, PathIsNotDirectoryException, throws FileNotFoundException, PathIsNotDirectoryException,
QuotaExceededException, UnresolvedLinkException, QuotaExceededException, UnresolvedLinkException,
SnapshotAccessControlException, UnsupportedActionException { SnapshotAccessControlException, UnsupportedActionException {
@ -363,9 +340,8 @@ public class FSDirAttrOp {
nsQuota); nsQuota);
} }
String srcs = FSDirectory.normalizePath(src); INodeDirectory dirNode =
final INodesInPath iip = fsd.getINodesInPath4Write(srcs, true); INodeDirectory.valueOf(iip.getLastINode(), iip.getPath());
INodeDirectory dirNode = INodeDirectory.valueOf(iip.getLastINode(), srcs);
if (dirNode.isRoot() && nsQuota == HdfsConstants.QUOTA_RESET) { if (dirNode.isRoot() && nsQuota == HdfsConstants.QUOTA_RESET) {
throw new IllegalArgumentException("Cannot clear namespace quota on root."); throw new IllegalArgumentException("Cannot clear namespace quota on root.");
} else { // a directory inode } else { // a directory inode
@ -401,13 +377,12 @@ public class FSDirAttrOp {
} }
static BlockInfo[] unprotectedSetReplication( static BlockInfo[] unprotectedSetReplication(
FSDirectory fsd, String src, short replication) FSDirectory fsd, INodesInPath iip, short replication)
throws QuotaExceededException, UnresolvedLinkException, throws QuotaExceededException, UnresolvedLinkException,
SnapshotAccessControlException { SnapshotAccessControlException {
assert fsd.hasWriteLock(); assert fsd.hasWriteLock();
final BlockManager bm = fsd.getBlockManager(); final BlockManager bm = fsd.getBlockManager();
final INodesInPath iip = fsd.getINodesInPath4Write(src, true);
final INode inode = iip.getLastINode(); final INode inode = iip.getLastINode();
if (inode == null || !inode.isFile()) { if (inode == null || !inode.isFile()) {
return null; return null;
@ -437,10 +412,10 @@ public class FSDirAttrOp {
if (oldBR != -1) { if (oldBR != -1) {
if (oldBR > targetReplication) { if (oldBR > targetReplication) {
FSDirectory.LOG.info("Decreasing replication from {} to {} for {}", FSDirectory.LOG.info("Decreasing replication from {} to {} for {}",
oldBR, targetReplication, src); oldBR, targetReplication, iip.getPath());
} else { } else {
FSDirectory.LOG.info("Increasing replication from {} to {} for {}", FSDirectory.LOG.info("Increasing replication from {} to {} for {}",
oldBR, targetReplication, src); oldBR, targetReplication, iip.getPath());
} }
} }
return file.getBlocks(); return file.getBlocks();
@ -475,8 +450,7 @@ public class FSDirAttrOp {
} }
inode.asFile().setStoragePolicyID(policyId, snapshotId); inode.asFile().setStoragePolicyID(policyId, snapshotId);
} else if (inode.isDirectory()) { } else if (inode.isDirectory()) {
setDirStoragePolicy(fsd, inode.asDirectory(), policyId, setDirStoragePolicy(fsd, iip, policyId);
snapshotId);
} else { } else {
throw new FileNotFoundException(iip.getPath() throw new FileNotFoundException(iip.getPath()
+ " is not a file or directory"); + " is not a file or directory");
@ -484,8 +458,8 @@ public class FSDirAttrOp {
} }
private static void setDirStoragePolicy( private static void setDirStoragePolicy(
FSDirectory fsd, INodeDirectory inode, byte policyId, FSDirectory fsd, INodesInPath iip, byte policyId) throws IOException {
int latestSnapshotId) throws IOException { INode inode = FSDirectory.resolveLastINode(iip);
List<XAttr> existingXAttrs = XAttrStorage.readINodeXAttrs(inode); List<XAttr> existingXAttrs = XAttrStorage.readINodeXAttrs(inode);
XAttr xAttr = BlockStoragePolicySuite.buildXAttr(policyId); XAttr xAttr = BlockStoragePolicySuite.buildXAttr(policyId);
List<XAttr> newXAttrs = null; List<XAttr> newXAttrs = null;
@ -500,14 +474,16 @@ public class FSDirAttrOp {
Arrays.asList(xAttr), Arrays.asList(xAttr),
EnumSet.of(XAttrSetFlag.CREATE, XAttrSetFlag.REPLACE)); EnumSet.of(XAttrSetFlag.CREATE, XAttrSetFlag.REPLACE));
} }
XAttrStorage.updateINodeXAttrs(inode, newXAttrs, latestSnapshotId); XAttrStorage.updateINodeXAttrs(inode, newXAttrs, iip.getLatestSnapshotId());
} }
private static boolean unprotectedSetTimes( static boolean unprotectedSetTimes(
FSDirectory fsd, INode inode, long mtime, long atime, boolean force, FSDirectory fsd, INodesInPath iip, long mtime, long atime, boolean force)
int latest) throws QuotaExceededException { throws QuotaExceededException {
assert fsd.hasWriteLock(); assert fsd.hasWriteLock();
boolean status = false; boolean status = false;
INode inode = iip.getLastINode();
int latest = iip.getLatestSnapshotId();
if (mtime != -1) { if (mtime != -1) {
inode = inode.setModificationTime(mtime, latest); inode = inode.setModificationTime(mtime, latest);
status = true; status = true;

View File

@ -508,10 +508,12 @@ public class FSEditLogLoader {
} }
case OP_SET_REPLICATION: { case OP_SET_REPLICATION: {
SetReplicationOp setReplicationOp = (SetReplicationOp)op; SetReplicationOp setReplicationOp = (SetReplicationOp)op;
String src = renameReservedPathsOnUpgrade(
setReplicationOp.path, logVersion);
INodesInPath iip = fsDir.getINodesInPath4Write(src);
short replication = fsNamesys.getBlockManager().adjustReplication( short replication = fsNamesys.getBlockManager().adjustReplication(
setReplicationOp.replication); setReplicationOp.replication);
FSDirAttrOp.unprotectedSetReplication(fsDir, renameReservedPathsOnUpgrade( FSDirAttrOp.unprotectedSetReplication(fsDir, iip, replication);
setReplicationOp.path, logVersion), replication);
break; break;
} }
case OP_CONCAT_DELETE: { case OP_CONCAT_DELETE: {
@ -576,52 +578,66 @@ public class FSEditLogLoader {
} }
case OP_SET_PERMISSIONS: { case OP_SET_PERMISSIONS: {
SetPermissionsOp setPermissionsOp = (SetPermissionsOp)op; SetPermissionsOp setPermissionsOp = (SetPermissionsOp)op;
FSDirAttrOp.unprotectedSetPermission(fsDir, renameReservedPathsOnUpgrade( final String src =
setPermissionsOp.src, logVersion), setPermissionsOp.permissions); renameReservedPathsOnUpgrade(setPermissionsOp.src, logVersion);
final INodesInPath iip = fsDir.getINodesInPath4Write(src);
FSDirAttrOp.unprotectedSetPermission(fsDir, iip,
setPermissionsOp.permissions);
break; break;
} }
case OP_SET_OWNER: { case OP_SET_OWNER: {
SetOwnerOp setOwnerOp = (SetOwnerOp)op; SetOwnerOp setOwnerOp = (SetOwnerOp)op;
FSDirAttrOp.unprotectedSetOwner( final String src = renameReservedPathsOnUpgrade(
fsDir, renameReservedPathsOnUpgrade(setOwnerOp.src, logVersion), setOwnerOp.src, logVersion);
final INodesInPath iip = fsDir.getINodesInPath4Write(src);
FSDirAttrOp.unprotectedSetOwner(fsDir, iip,
setOwnerOp.username, setOwnerOp.groupname); setOwnerOp.username, setOwnerOp.groupname);
break; break;
} }
case OP_SET_NS_QUOTA: { case OP_SET_NS_QUOTA: {
SetNSQuotaOp setNSQuotaOp = (SetNSQuotaOp)op; SetNSQuotaOp setNSQuotaOp = (SetNSQuotaOp)op;
FSDirAttrOp.unprotectedSetQuota( final String src = renameReservedPathsOnUpgrade(
fsDir, renameReservedPathsOnUpgrade(setNSQuotaOp.src, logVersion), setNSQuotaOp.src, logVersion);
final INodesInPath iip = fsDir.getINodesInPath4Write(src);
FSDirAttrOp.unprotectedSetQuota(fsDir, iip,
setNSQuotaOp.nsQuota, HdfsConstants.QUOTA_DONT_SET, null); setNSQuotaOp.nsQuota, HdfsConstants.QUOTA_DONT_SET, null);
break; break;
} }
case OP_CLEAR_NS_QUOTA: { case OP_CLEAR_NS_QUOTA: {
ClearNSQuotaOp clearNSQuotaOp = (ClearNSQuotaOp)op; ClearNSQuotaOp clearNSQuotaOp = (ClearNSQuotaOp)op;
FSDirAttrOp.unprotectedSetQuota( final String src = renameReservedPathsOnUpgrade(
fsDir, renameReservedPathsOnUpgrade(clearNSQuotaOp.src, logVersion), clearNSQuotaOp.src, logVersion);
final INodesInPath iip = fsDir.getINodesInPath4Write(src);
FSDirAttrOp.unprotectedSetQuota(fsDir, iip,
HdfsConstants.QUOTA_RESET, HdfsConstants.QUOTA_DONT_SET, null); HdfsConstants.QUOTA_RESET, HdfsConstants.QUOTA_DONT_SET, null);
break; break;
} }
case OP_SET_QUOTA: {
case OP_SET_QUOTA:
SetQuotaOp setQuotaOp = (SetQuotaOp) op; SetQuotaOp setQuotaOp = (SetQuotaOp) op;
FSDirAttrOp.unprotectedSetQuota(fsDir, final String src = renameReservedPathsOnUpgrade(
renameReservedPathsOnUpgrade(setQuotaOp.src, logVersion), setQuotaOp.src, logVersion);
final INodesInPath iip = fsDir.getINodesInPath4Write(src);
FSDirAttrOp.unprotectedSetQuota(fsDir, iip,
setQuotaOp.nsQuota, setQuotaOp.dsQuota, null); setQuotaOp.nsQuota, setQuotaOp.dsQuota, null);
break; break;
}
case OP_SET_QUOTA_BY_STORAGETYPE: case OP_SET_QUOTA_BY_STORAGETYPE: {
FSEditLogOp.SetQuotaByStorageTypeOp setQuotaByStorageTypeOp = FSEditLogOp.SetQuotaByStorageTypeOp setQuotaByStorageTypeOp =
(FSEditLogOp.SetQuotaByStorageTypeOp) op; (FSEditLogOp.SetQuotaByStorageTypeOp) op;
FSDirAttrOp.unprotectedSetQuota(fsDir, final String src = renameReservedPathsOnUpgrade(
renameReservedPathsOnUpgrade(setQuotaByStorageTypeOp.src, logVersion), setQuotaByStorageTypeOp.src, logVersion);
final INodesInPath iip = fsDir.getINodesInPath4Write(src);
FSDirAttrOp.unprotectedSetQuota(fsDir, iip,
HdfsConstants.QUOTA_DONT_SET, setQuotaByStorageTypeOp.dsQuota, HdfsConstants.QUOTA_DONT_SET, setQuotaByStorageTypeOp.dsQuota,
setQuotaByStorageTypeOp.type); setQuotaByStorageTypeOp.type);
break; break;
}
case OP_TIMES: { case OP_TIMES: {
TimesOp timesOp = (TimesOp)op; TimesOp timesOp = (TimesOp)op;
FSDirAttrOp.unprotectedSetTimes( final String src = renameReservedPathsOnUpgrade(
fsDir, renameReservedPathsOnUpgrade(timesOp.path, logVersion), timesOp.path, logVersion);
final INodesInPath iip = fsDir.getINodesInPath4Write(src);
FSDirAttrOp.unprotectedSetTimes(fsDir, iip,
timesOp.mtime, timesOp.atime, true); timesOp.mtime, timesOp.atime, true);
break; break;
} }

View File

@ -1784,8 +1784,7 @@ public class FSNamesystem implements Namesystem, FSNamesystemMBean,
boolean updateAccessTime = inode != null && boolean updateAccessTime = inode != null &&
now > inode.getAccessTime() + dir.getAccessTimePrecision(); now > inode.getAccessTime() + dir.getAccessTimePrecision();
if (!isInSafeMode() && updateAccessTime) { if (!isInSafeMode() && updateAccessTime) {
boolean changed = FSDirAttrOp.setTimes(dir, boolean changed = FSDirAttrOp.setTimes(dir, iip, -1, now, false);
inode, -1, now, false, iip.getLatestSnapshotId());
if (changed) { if (changed) {
getEditLog().logTimes(src, -1, now); getEditLog().logTimes(src, -1, now);
} }