Adjust CacheFileTests.testCacheFileCreatedAsSparseFile for encryption at rest (#81527)

This test fails sometimes on CI when it is executed on encrypted
filesystems: the test tries to detect the block size by writing a single
byte at the end of a larger file, which should result in a single block
allocated, but on encrypted filesystems it can result in more than a
single block being reserved. This commit adjusts the test so that it
assumes that a default block size of 4KB is always used on Linux, and if
the default block size is different then it assumes that the test is
executed on an encrypted filesystem and that the allocated size stays
within an upper bound. Relates
https://github.com/elastic/elasticsearch/issues/81362#issuecomment-988333284
Closes #81362
This commit is contained in:
Tanguy Leroux 2021-12-09 10:48:28 +01:00 committed by GitHub
parent 7d69f1a974
commit 647e5fe648
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 27 additions and 14 deletions

View file

@ -25,6 +25,7 @@
sudo cryptsetup open --key-file key.secret "$LOOP" secret --verbose sudo cryptsetup open --key-file key.secret "$LOOP" secret --verbose
sudo mkfs.ext2 /dev/mapper/secret sudo mkfs.ext2 /dev/mapper/secret
sudo mkdir /mnt/secret sudo mkdir /mnt/secret
# Change /mnt/secret with care (at least a test makes assertion based on this name)
sudo mount /dev/mapper/secret /mnt/secret sudo mount /dev/mapper/secret /mnt/secret
sudo chown -R jenkins /mnt/secret sudo chown -R jenkins /mnt/secret
cp -r "$WORKSPACE" /mnt/secret cp -r "$WORKSPACE" /mnt/secret

View file

@ -90,7 +90,7 @@ final class LinuxFileSystemNatives implements FileSystemNatives.Provider {
final Stat stats = new Stat(); final Stat stats = new Stat();
final int rc = XStatLibrary.__xstat(STAT_VER, path.toString(), stats); final int rc = XStatLibrary.__xstat(STAT_VER, path.toString(), stats);
if (logger.isTraceEnabled()) { if (logger.isTraceEnabled()) {
logger.trace("executing native method __xstat() returned {} with error code [{}] for file [{}]", rc, stats, path); logger.trace("executing native method __xstat() returned {} with error code [{}] for file [{}]", stats, rc, path);
} }
return OptionalLong.of(stats.st_blocks * ST_BLOCKS_UNIT); return OptionalLong.of(stats.st_blocks * ST_BLOCKS_UNIT);
} catch (LastErrorException e) { } catch (LastErrorException e) {

View file

@ -436,13 +436,9 @@ public class CacheFileTests extends ESTestCase {
allOf(greaterThan(0L), lessThan(oneMb)) allOf(greaterThan(0L), lessThan(oneMb))
); );
final long blockSize; // on Linux we can infer the filesystem's block size if only 1 byte was written,
if (Constants.LINUX) { // but this is not always right with encryption at rest using dmcrypt
// on Linux we can infer the filesystem's block size if only 1 byte was written final long blockSize = Constants.LINUX ? sizeOnDisk.getAsLong() : 0L;
blockSize = sizeOnDisk.getAsLong();
} else {
blockSize = 0L;
}
fill(fileChannel, 0, Math.toIntExact(cacheFile.getLength())); fill(fileChannel, 0, Math.toIntExact(cacheFile.getLength()));
fileChannel.force(false); fileChannel.force(false);
@ -455,13 +451,29 @@ public class CacheFileTests extends ESTestCase {
greaterThanOrEqualTo(cacheFile.getLength()) greaterThanOrEqualTo(cacheFile.getLength())
); );
if (Constants.LINUX) { if (blockSize > 0L) {
final long nbBlocks = (cacheFile.getLength() + blockSize - 1) / blockSize; // ceil(cacheFile.getLength() / blockSize) final long nbBlocks = (cacheFile.getLength() + blockSize - 1) / blockSize; // ceil(cacheFile.getLength() / blockSize)
final long expectedSize = nbBlocks * blockSize;
if (blockSize == fourKb) {
assertThat( assertThat(
"Cache file size mismatches (block size: " + blockSize + ", number of blocks: " + nbBlocks + ')', "Cache file size mismatches (block size: "
+ blockSize
+ ", number of blocks: "
+ nbBlocks
+ ", file length: "
+ cacheFile.getLength()
+ ')',
sizeOnDisk.getAsLong(), sizeOnDisk.getAsLong(),
equalTo(nbBlocks * blockSize) equalTo(expectedSize)
); );
} else {
// block size other than usual default block size indicates that a special filesystem may be at use, let's verify this
assertThat(
"Non default block size only used in test executed with encryption at rest",
file.toAbsolutePath().toString(),
containsString("/mnt/secret")
);
}
} }
} finally { } finally {
cacheFile.release(listener); cacheFile.release(listener);