|
@@ -496,6 +496,15 @@ public class FSNamesystem implements Namesystem, FSNamesystemMBean,
|
|
|
/** Lock to protect FSNamesystem. */
|
|
|
private final FSNamesystemLock fsLock;
|
|
|
|
|
|
+ /**
|
|
|
+ * Checkpoint lock to protect FSNamesystem modification on standby NNs.
|
|
|
+ * Unlike fsLock, it does not affect block updates. On active NNs, this lock
|
|
|
+ * does not provide proper protection, because there are operations that
|
|
|
+ * modify both block and name system state. Even on standby, fsLock is
|
|
|
+ * used when block state changes need to be blocked.
|
|
|
+ */
|
|
|
+ private final ReentrantLock cpLock;
|
|
|
+
|
|
|
/**
|
|
|
* Used when this NN is in standby state to read from the shared edit log.
|
|
|
*/
|
|
@@ -758,6 +767,8 @@ public class FSNamesystem implements Namesystem, FSNamesystemMBean,
|
|
|
LOG.info("fsLock is fair:" + fair);
|
|
|
fsLock = new FSNamesystemLock(fair);
|
|
|
cond = fsLock.writeLock().newCondition();
|
|
|
+ cpLock = new ReentrantLock();
|
|
|
+
|
|
|
this.fsImage = fsImage;
|
|
|
try {
|
|
|
resourceRecheckInterval = conf.getLong(
|
|
@@ -1554,6 +1565,22 @@ public class FSNamesystem implements Namesystem, FSNamesystemMBean,
|
|
|
return this.fsLock.getWriteHoldCount();
|
|
|
}
|
|
|
|
|
|
+ /** Lock the checkpoint lock */
|
|
|
+ public void cpLock() {
|
|
|
+ this.cpLock.lock();
|
|
|
+ }
|
|
|
+
|
|
|
+ /** Lock the checkpoint lock interrupibly */
|
|
|
+ public void cpLockInterruptibly() throws InterruptedException {
|
|
|
+ this.cpLock.lockInterruptibly();
|
|
|
+ }
|
|
|
+
|
|
|
+ /** Unlock the checkpoint lock */
|
|
|
+ public void cpUnlock() {
|
|
|
+ this.cpLock.unlock();
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
NamespaceInfo getNamespaceInfo() {
|
|
|
readLock();
|
|
|
try {
|
|
@@ -5274,7 +5301,7 @@ public class FSNamesystem implements Namesystem, FSNamesystemMBean,
|
|
|
checkOperation(OperationCategory.UNCHECKED);
|
|
|
checkSuperuserPrivilege();
|
|
|
|
|
|
-
|
|
|
+ cpLock(); // Block if a checkpointing is in progress on standby.
|
|
|
readLock();
|
|
|
try {
|
|
|
checkOperation(OperationCategory.UNCHECKED);
|
|
@@ -5286,6 +5313,7 @@ public class FSNamesystem implements Namesystem, FSNamesystemMBean,
|
|
|
getFSImage().saveNamespace(this);
|
|
|
} finally {
|
|
|
readUnlock();
|
|
|
+ cpUnlock();
|
|
|
}
|
|
|
LOG.info("New namespace image has been created");
|
|
|
}
|
|
@@ -5300,6 +5328,7 @@ public class FSNamesystem implements Namesystem, FSNamesystemMBean,
|
|
|
StandbyException {
|
|
|
checkSuperuserPrivilege();
|
|
|
checkOperation(OperationCategory.UNCHECKED);
|
|
|
+ cpLock(); // Block if a checkpointing is in progress on standby.
|
|
|
writeLock();
|
|
|
try {
|
|
|
checkOperation(OperationCategory.UNCHECKED);
|
|
@@ -5314,6 +5343,7 @@ public class FSNamesystem implements Namesystem, FSNamesystemMBean,
|
|
|
return val;
|
|
|
} finally {
|
|
|
writeUnlock();
|
|
|
+ cpUnlock();
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -5324,12 +5354,14 @@ public class FSNamesystem implements Namesystem, FSNamesystemMBean,
|
|
|
void finalizeUpgrade() throws IOException {
|
|
|
checkSuperuserPrivilege();
|
|
|
checkOperation(OperationCategory.UNCHECKED);
|
|
|
+ cpLock(); // Block if a checkpointing is in progress on standby.
|
|
|
writeLock();
|
|
|
try {
|
|
|
checkOperation(OperationCategory.UNCHECKED);
|
|
|
getFSImage().finalizeUpgrade(this.isHaEnabled() && inActiveState());
|
|
|
} finally {
|
|
|
writeUnlock();
|
|
|
+ cpUnlock();
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -7542,6 +7574,11 @@ public class FSNamesystem implements Namesystem, FSNamesystemMBean,
|
|
|
return fsLock.longReadLock;
|
|
|
}
|
|
|
|
|
|
+ @VisibleForTesting
|
|
|
+ public ReentrantLock getCpLockForTests() {
|
|
|
+ return cpLock;
|
|
|
+ }
|
|
|
+
|
|
|
@VisibleForTesting
|
|
|
public SafeModeInfo getSafeModeInfoForTests() {
|
|
|
return safeMode;
|