HDFS-6718. Remove EncryptionZoneManager lock. (wang)

git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/branches/fs-encryption@1612439 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Andrew Wang 2014-07-22 00:55:20 +00:00
parent 7b466b3b70
commit b57ec16567
2 changed files with 65 additions and 127 deletions

View File

@ -52,6 +52,8 @@ fs-encryption (Unreleased)
HDFS-6716. Update usage of KeyProviderCryptoExtension APIs on NameNode. HDFS-6716. Update usage of KeyProviderCryptoExtension APIs on NameNode.
(wang) (wang)
HDFS-6718. Remove EncryptionZoneManager lock. (wang)
OPTIMIZATIONS OPTIMIZATIONS
BUG FIXES BUG FIXES

View File

@ -60,35 +60,6 @@ long getINodeId() {
} }
/**
* Protects the <tt>encryptionZones</tt> map and its contents.
*/
private final ReentrantReadWriteLock lock;
private void readLock() {
lock.readLock().lock();
}
private void readUnlock() {
lock.readLock().unlock();
}
private void writeLock() {
lock.writeLock().lock();
}
private void writeUnlock() {
lock.writeLock().unlock();
}
public boolean hasWriteLock() {
return lock.isWriteLockedByCurrentThread();
}
public boolean hasReadLock() {
return lock.getReadHoldCount() > 0 || hasWriteLock();
}
private final Map<Long, EncryptionZoneInt> encryptionZones; private final Map<Long, EncryptionZoneInt> encryptionZones;
private final FSDirectory dir; private final FSDirectory dir;
private final KeyProvider provider; private final KeyProvider provider;
@ -101,7 +72,6 @@ public boolean hasReadLock() {
public EncryptionZoneManager(FSDirectory dir, KeyProvider provider) { public EncryptionZoneManager(FSDirectory dir, KeyProvider provider) {
this.dir = dir; this.dir = dir;
this.provider = provider; this.provider = provider;
lock = new ReentrantReadWriteLock();
encryptionZones = new HashMap<Long, EncryptionZoneInt>(); encryptionZones = new HashMap<Long, EncryptionZoneInt>();
} }
@ -116,12 +86,7 @@ public EncryptionZoneManager(FSDirectory dir, KeyProvider provider) {
void addEncryptionZone(Long inodeId, String keyId) { void addEncryptionZone(Long inodeId, String keyId) {
assert dir.hasWriteLock(); assert dir.hasWriteLock();
final EncryptionZoneInt ez = new EncryptionZoneInt(inodeId, keyId); final EncryptionZoneInt ez = new EncryptionZoneInt(inodeId, keyId);
writeLock(); encryptionZones.put(inodeId, ez);
try {
encryptionZones.put(inodeId, ez);
} finally {
writeUnlock();
}
} }
/** /**
@ -131,12 +96,7 @@ void addEncryptionZone(Long inodeId, String keyId) {
*/ */
void removeEncryptionZone(Long inodeId) { void removeEncryptionZone(Long inodeId) {
assert dir.hasWriteLock(); assert dir.hasWriteLock();
writeLock(); encryptionZones.remove(inodeId);
try {
encryptionZones.remove(inodeId);
} finally {
writeUnlock();
}
} }
/** /**
@ -147,12 +107,7 @@ void removeEncryptionZone(Long inodeId) {
boolean isInAnEZ(INodesInPath iip) boolean isInAnEZ(INodesInPath iip)
throws UnresolvedLinkException, SnapshotAccessControlException { throws UnresolvedLinkException, SnapshotAccessControlException {
assert dir.hasReadLock(); assert dir.hasReadLock();
readLock(); return (getEncryptionZoneForPath(iip) != null);
try {
return (getEncryptionZoneForPath(iip) != null);
} finally {
readUnlock();
}
} }
/** /**
@ -172,16 +127,12 @@ private String getFullPathName(EncryptionZoneInt ezi) {
* Called while holding the FSDirectory lock. * Called while holding the FSDirectory lock.
*/ */
String getKeyName(final INodesInPath iip) { String getKeyName(final INodesInPath iip) {
readLock(); assert dir.hasReadLock();
try { EncryptionZoneInt ezi = getEncryptionZoneForPath(iip);
EncryptionZoneInt ezi = getEncryptionZoneForPath(iip); if (ezi == null) {
if (ezi == null) { return null;
return null;
}
return ezi.getKeyName();
} finally {
readUnlock();
} }
return ezi.getKeyName();
} }
/** /**
@ -191,7 +142,7 @@ String getKeyName(final INodesInPath iip) {
* Must be called while holding the manager lock. * Must be called while holding the manager lock.
*/ */
private EncryptionZoneInt getEncryptionZoneForPath(INodesInPath iip) { private EncryptionZoneInt getEncryptionZoneForPath(INodesInPath iip) {
assert hasReadLock(); assert dir.hasReadLock();
Preconditions.checkNotNull(iip); Preconditions.checkNotNull(iip);
final INode[] inodes = iip.getINodes(); final INode[] inodes = iip.getINodes();
for (int i = inodes.length - 1; i >= 0; i--) { for (int i = inodes.length - 1; i >= 0; i--) {
@ -220,41 +171,36 @@ private EncryptionZoneInt getEncryptionZoneForPath(INodesInPath iip) {
void checkMoveValidity(INodesInPath srcIIP, INodesInPath dstIIP, String src) void checkMoveValidity(INodesInPath srcIIP, INodesInPath dstIIP, String src)
throws IOException { throws IOException {
assert dir.hasReadLock(); assert dir.hasReadLock();
readLock(); final EncryptionZoneInt srcEZI = getEncryptionZoneForPath(srcIIP);
try { final EncryptionZoneInt dstEZI = getEncryptionZoneForPath(dstIIP);
final EncryptionZoneInt srcEZI = getEncryptionZoneForPath(srcIIP); final boolean srcInEZ = (srcEZI != null);
final EncryptionZoneInt dstEZI = getEncryptionZoneForPath(dstIIP); final boolean dstInEZ = (dstEZI != null);
final boolean srcInEZ = (srcEZI != null); if (srcInEZ) {
final boolean dstInEZ = (dstEZI != null); if (!dstInEZ) {
if (srcInEZ) { throw new IOException(
if (!dstInEZ) { src + " can't be moved from an encryption zone.");
throw new IOException(
src + " can't be moved from an encryption zone.");
}
} else {
if (dstInEZ) {
throw new IOException(
src + " can't be moved into an encryption zone.");
}
} }
} else {
if (dstInEZ) {
throw new IOException(
src + " can't be moved into an encryption zone.");
}
}
if (srcInEZ || dstInEZ) { if (srcInEZ || dstInEZ) {
Preconditions.checkState(srcEZI != null, "couldn't find src EZ?"); Preconditions.checkState(srcEZI != null, "couldn't find src EZ?");
Preconditions.checkState(dstEZI != null, "couldn't find dst EZ?"); Preconditions.checkState(dstEZI != null, "couldn't find dst EZ?");
if (srcEZI != dstEZI) { if (srcEZI != dstEZI) {
final String srcEZPath = getFullPathName(srcEZI); final String srcEZPath = getFullPathName(srcEZI);
final String dstEZPath = getFullPathName(dstEZI); final String dstEZPath = getFullPathName(dstEZI);
final StringBuilder sb = new StringBuilder(src); final StringBuilder sb = new StringBuilder(src);
sb.append(" can't be moved from encryption zone "); sb.append(" can't be moved from encryption zone ");
sb.append(srcEZPath); sb.append(srcEZPath);
sb.append(" to encryption zone "); sb.append(" to encryption zone ");
sb.append(dstEZPath); sb.append(dstEZPath);
sb.append("."); sb.append(".");
throw new IOException(sb.toString()); throw new IOException(sb.toString());
}
} }
} finally {
readUnlock();
} }
} }
@ -266,34 +212,29 @@ void checkMoveValidity(INodesInPath srcIIP, INodesInPath dstIIP, String src)
XAttr createEncryptionZone(String src, String keyId, KeyVersion keyVersion) XAttr createEncryptionZone(String src, String keyId, KeyVersion keyVersion)
throws IOException { throws IOException {
assert dir.hasWriteLock(); assert dir.hasWriteLock();
writeLock(); if (dir.isNonEmptyDirectory(src)) {
try { throw new IOException(
if (dir.isNonEmptyDirectory(src)) { "Attempt to create an encryption zone for a non-empty directory.");
throw new IOException(
"Attempt to create an encryption zone for a non-empty directory.");
}
final INodesInPath srcIIP = dir.getINodesInPath4Write(src, false);
EncryptionZoneInt ezi = getEncryptionZoneForPath(srcIIP);
if (ezi != null) {
throw new IOException("Directory " + src + " is already in an " +
"encryption zone. (" + getFullPathName(ezi) + ")");
}
final XAttr keyIdXAttr = XAttrHelper
.buildXAttr(CRYPTO_XATTR_ENCRYPTION_ZONE, keyId.getBytes());
final List<XAttr> xattrs = Lists.newArrayListWithCapacity(1);
xattrs.add(keyIdXAttr);
// updating the xattr will call addEncryptionZone,
// done this way to handle edit log loading
dir.unprotectedSetXAttrs(src, xattrs, EnumSet.of(XAttrSetFlag.CREATE));
// Re-get the new encryption zone add the latest key version
ezi = getEncryptionZoneForPath(srcIIP);
return keyIdXAttr;
} finally {
writeUnlock();
} }
final INodesInPath srcIIP = dir.getINodesInPath4Write(src, false);
EncryptionZoneInt ezi = getEncryptionZoneForPath(srcIIP);
if (ezi != null) {
throw new IOException("Directory " + src + " is already in an " +
"encryption zone. (" + getFullPathName(ezi) + ")");
}
final XAttr keyIdXAttr = XAttrHelper
.buildXAttr(CRYPTO_XATTR_ENCRYPTION_ZONE, keyId.getBytes());
final List<XAttr> xattrs = Lists.newArrayListWithCapacity(1);
xattrs.add(keyIdXAttr);
// updating the xattr will call addEncryptionZone,
// done this way to handle edit log loading
dir.unprotectedSetXAttrs(src, xattrs, EnumSet.of(XAttrSetFlag.CREATE));
// Re-get the new encryption zone add the latest key version
ezi = getEncryptionZoneForPath(srcIIP);
return keyIdXAttr;
} }
/** /**
@ -303,16 +244,11 @@ XAttr createEncryptionZone(String src, String keyId, KeyVersion keyVersion)
*/ */
List<EncryptionZone> listEncryptionZones() throws IOException { List<EncryptionZone> listEncryptionZones() throws IOException {
assert dir.hasReadLock(); assert dir.hasReadLock();
readLock(); final List<EncryptionZone> ret =
try { Lists.newArrayListWithExpectedSize(encryptionZones.size());
final List<EncryptionZone> ret = for (EncryptionZoneInt ezi : encryptionZones.values()) {
Lists.newArrayListWithExpectedSize(encryptionZones.size()); ret.add(new EncryptionZone(getFullPathName(ezi), ezi.getKeyName()));
for (EncryptionZoneInt ezi : encryptionZones.values()) {
ret.add(new EncryptionZone(getFullPathName(ezi), ezi.getKeyName()));
}
return ret;
} finally {
readUnlock();
} }
return ret;
} }
} }