HDFS-15076. Fix tests that hold FSDirectory lock, without holding FSNamesystem lock. Contributed by Konstantin V Shvachko.

(cherry picked from commit b98ac2a3af)
This commit is contained in:
Konstantin V Shvachko 2019-12-24 12:08:34 -08:00
parent cb5b80d6cb
commit 199c7cc62c
3 changed files with 63 additions and 23 deletions

View File

@ -380,16 +380,26 @@ public class TestDiskspaceQuotaUpdate {
HashMap<String, Long> dsMap = new HashMap<String, Long>(); HashMap<String, Long> dsMap = new HashMap<String, Long>();
scanDirsWithQuota(root, nsMap, dsMap, false); scanDirsWithQuota(root, nsMap, dsMap, false);
getFSDirectory().updateCountForQuota(1); updateCountForQuota(1);
scanDirsWithQuota(root, nsMap, dsMap, true); scanDirsWithQuota(root, nsMap, dsMap, true);
getFSDirectory().updateCountForQuota(2); updateCountForQuota(2);
scanDirsWithQuota(root, nsMap, dsMap, true); scanDirsWithQuota(root, nsMap, dsMap, true);
getFSDirectory().updateCountForQuota(4); updateCountForQuota(4);
scanDirsWithQuota(root, nsMap, dsMap, true); scanDirsWithQuota(root, nsMap, dsMap, true);
} }
private void updateCountForQuota(int i) {
FSNamesystem fsn = cluster.getNamesystem();
fsn.writeLock();
try {
getFSDirectory().updateCountForQuota(1);
} finally {
fsn.writeUnlock();
}
}
private void scanDirsWithQuota(INodeDirectory dir, private void scanDirsWithQuota(INodeDirectory dir,
HashMap<String, Long> nsMap, HashMap<String, Long> nsMap,
HashMap<String, Long> dsMap, boolean verify) { HashMap<String, Long> dsMap, boolean verify) {

View File

@ -89,7 +89,7 @@ public class TestFSNamesystem {
LeaseManager leaseMan = fsn.getLeaseManager(); LeaseManager leaseMan = fsn.getLeaseManager();
leaseMan.addLease("client1", fsn.getFSDirectory().allocateNewInodeId()); leaseMan.addLease("client1", fsn.getFSDirectory().allocateNewInodeId());
assertEquals(1, leaseMan.countLease()); assertEquals(1, leaseMan.countLease());
fsn.clear(); clearNamesystem(fsn);
leaseMan = fsn.getLeaseManager(); leaseMan = fsn.getLeaseManager();
assertEquals(0, leaseMan.countLease()); assertEquals(0, leaseMan.countLease());
} }
@ -184,8 +184,7 @@ public class TestFSNamesystem {
FSNamesystem fsn = new FSNamesystem(conf, fsImage); FSNamesystem fsn = new FSNamesystem(conf, fsImage);
fsn.imageLoadComplete(); fsn.imageLoadComplete();
assertTrue(fsn.isImageLoaded()); assertTrue(fsn.isImageLoaded());
fsn.clear(); clearNamesystem(fsn);
assertFalse(fsn.isImageLoaded());
final INodeDirectory root = (INodeDirectory) fsn.getFSDirectory() final INodeDirectory root = (INodeDirectory) fsn.getFSDirectory()
.getINode("/"); .getINode("/");
assertTrue(root.getChildrenList(Snapshot.CURRENT_STATE_ID).isEmpty()); assertTrue(root.getChildrenList(Snapshot.CURRENT_STATE_ID).isEmpty());
@ -193,6 +192,16 @@ public class TestFSNamesystem {
assertTrue(fsn.isImageLoaded()); assertTrue(fsn.isImageLoaded());
} }
private void clearNamesystem(FSNamesystem fsn) {
fsn.writeLock();
try {
fsn.clear();
assertFalse(fsn.isImageLoaded());
} finally {
fsn.writeUnlock();
}
}
@Test @Test
public void testGetEffectiveLayoutVersion() { public void testGetEffectiveLayoutVersion() {
assertEquals(-63, assertEquals(-63,

View File

@ -22,6 +22,7 @@ import org.apache.hadoop.fs.permission.FsPermission;
import org.apache.hadoop.fs.permission.PermissionStatus; import org.apache.hadoop.fs.permission.PermissionStatus;
import org.apache.hadoop.hdfs.server.blockmanagement.BlockInfo; import org.apache.hadoop.hdfs.server.blockmanagement.BlockInfo;
import org.apache.hadoop.hdfs.server.namenode.FSDirectory.DirOp; import org.apache.hadoop.hdfs.server.namenode.FSDirectory.DirOp;
import org.apache.hadoop.hdfs.server.namenode.NameNode.OperationCategory;
import org.junit.Test; import org.junit.Test;
import org.mockito.invocation.InvocationOnMock; import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer; import org.mockito.stubbing.Answer;
@ -61,22 +62,31 @@ public class TestGetBlockLocations {
@Test(timeout = 30000) @Test(timeout = 30000)
public void testGetBlockLocationsRacingWithDelete() throws IOException { public void testGetBlockLocationsRacingWithDelete() throws IOException {
FSNamesystem fsn = spy(setupFileSystem()); final FSNamesystem fsn = spy(setupFileSystem());
final FSDirectory fsd = fsn.getFSDirectory(); final FSDirectory fsd = fsn.getFSDirectory();
FSEditLog editlog = fsn.getEditLog(); FSEditLog editlog = fsn.getEditLog();
final boolean[] deleted = new boolean[]{false};
doAnswer(new Answer<Void>() { doAnswer(new Answer<Void>() {
@Override @Override
public Void answer(InvocationOnMock invocation) throws Throwable { public Void answer(InvocationOnMock invocation) throws Throwable {
INodesInPath iip = fsd.getINodesInPath(FILE_PATH, DirOp.READ); if(!deleted[0]) {
FSDirDeleteOp.delete(fsd, iip, new INode.BlocksMapUpdateInfo(), fsn.writeLock();
new ArrayList<INode>(), new ArrayList<Long>(), try {
now()); INodesInPath iip = fsd.getINodesInPath(FILE_PATH, DirOp.READ);
FSDirDeleteOp.delete(fsd, iip, new INode.BlocksMapUpdateInfo(),
new ArrayList<INode>(), new ArrayList<Long>(),
now());
} finally {
fsn.writeUnlock();
}
deleted[0] = true;
}
invocation.callRealMethod(); invocation.callRealMethod();
return null; return null;
} }
}).when(fsn).writeLock(); }).when(fsn).checkOperation(OperationCategory.WRITE);
fsn.getBlockLocations("dummy", RESERVED_PATH, 0, 1024); fsn.getBlockLocations("dummy", RESERVED_PATH, 0, 1024);
verify(editlog, never()).logTimes(anyString(), anyLong(), anyLong()); verify(editlog, never()).logTimes(anyString(), anyLong(), anyLong());
@ -85,26 +95,31 @@ public class TestGetBlockLocations {
@Test(timeout = 30000) @Test(timeout = 30000)
public void testGetBlockLocationsRacingWithRename() throws IOException { public void testGetBlockLocationsRacingWithRename() throws IOException {
FSNamesystem fsn = spy(setupFileSystem()); final FSNamesystem fsn = spy(setupFileSystem());
final FSDirectory fsd = fsn.getFSDirectory(); final FSDirectory fsd = fsn.getFSDirectory();
FSEditLog editlog = fsn.getEditLog(); FSEditLog editlog = fsn.getEditLog();
final String DST_PATH = "/bar"; final String DST_PATH = "/bar";
final boolean[] renamed = new boolean[1]; final boolean[] renamed = new boolean[] {false};
doAnswer(new Answer<Void>() { doAnswer(new Answer<Void>() {
@Override @Override
public Void answer(InvocationOnMock invocation) throws Throwable { public Void answer(InvocationOnMock invocation) throws Throwable {
invocation.callRealMethod();
if (!renamed[0]) { if (!renamed[0]) {
FSDirRenameOp.renameTo(fsd, fsd.getPermissionChecker(), FILE_PATH, fsn.writeLock();
DST_PATH, new INode.BlocksMapUpdateInfo(), try {
false); FSDirRenameOp.renameTo(fsd, fsd.getPermissionChecker(), FILE_PATH,
renamed[0] = true; DST_PATH, new INode.BlocksMapUpdateInfo(),
false);
renamed[0] = true;
} finally {
fsn.writeUnlock();
}
} }
invocation.callRealMethod();
return null; return null;
} }
}).when(fsn).writeLock(); }).when(fsn).checkOperation(OperationCategory.WRITE);
fsn.getBlockLocations("dummy", RESERVED_PATH, 0, 1024); fsn.getBlockLocations("dummy", RESERVED_PATH, 0, 1024);
verify(editlog).logTimes(eq(DST_PATH), anyLong(), anyLong()); verify(editlog).logTimes(eq(DST_PATH), anyLong(), anyLong());
@ -119,8 +134,6 @@ public class TestGetBlockLocations {
when(image.getEditLog()).thenReturn(editlog); when(image.getEditLog()).thenReturn(editlog);
final FSNamesystem fsn = new FSNamesystem(conf, image, true); final FSNamesystem fsn = new FSNamesystem(conf, image, true);
final FSDirectory fsd = fsn.getFSDirectory();
INodesInPath iip = fsd.getINodesInPath("/", DirOp.READ);
PermissionStatus perm = new PermissionStatus( PermissionStatus perm = new PermissionStatus(
"hdfs", "supergroup", "hdfs", "supergroup",
FsPermission.createImmutable((short) 0x1ff)); FsPermission.createImmutable((short) 0x1ff));
@ -128,7 +141,15 @@ public class TestGetBlockLocations {
MOCK_INODE_ID, FILE_NAME.getBytes(StandardCharsets.UTF_8), MOCK_INODE_ID, FILE_NAME.getBytes(StandardCharsets.UTF_8),
perm, 1, 1, new BlockInfo[] {}, (short) 1, perm, 1, 1, new BlockInfo[] {}, (short) 1,
DFS_BLOCK_SIZE_DEFAULT); DFS_BLOCK_SIZE_DEFAULT);
fsn.getFSDirectory().addINode(iip, file);
fsn.writeLock();
try {
final FSDirectory fsd = fsn.getFSDirectory();
INodesInPath iip = fsd.getINodesInPath("/", DirOp.READ);
fsd.addINode(iip, file);
} finally {
fsn.writeUnlock();
}
return fsn; return fsn;
} }