From 647e5fe64861eb64b7daeb965768f79ed99105d7 Mon Sep 17 00:00:00 2001 From: Tanguy Leroux Date: Thu, 9 Dec 2021 10:48:28 +0100 Subject: [PATCH] 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 --- .../elastic+elasticsearch+periodic+ear.yml | 1 + .../filesystem/LinuxFileSystemNatives.java | 2 +- .../cache/common/CacheFileTests.java | 38 ++++++++++++------- 3 files changed, 27 insertions(+), 14 deletions(-) diff --git a/.ci/jobs.t/elastic+elasticsearch+periodic+ear.yml b/.ci/jobs.t/elastic+elasticsearch+periodic+ear.yml index ee2d1b57cac2..0a7404117f93 100644 --- a/.ci/jobs.t/elastic+elasticsearch+periodic+ear.yml +++ b/.ci/jobs.t/elastic+elasticsearch+periodic+ear.yml @@ -25,6 +25,7 @@ sudo cryptsetup open --key-file key.secret "$LOOP" secret --verbose sudo mkfs.ext2 /dev/mapper/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 chown -R jenkins /mnt/secret cp -r "$WORKSPACE" /mnt/secret diff --git a/server/src/main/java/org/elasticsearch/common/filesystem/LinuxFileSystemNatives.java b/server/src/main/java/org/elasticsearch/common/filesystem/LinuxFileSystemNatives.java index 3d69ac8a89e3..66fb54d92e0a 100644 --- a/server/src/main/java/org/elasticsearch/common/filesystem/LinuxFileSystemNatives.java +++ b/server/src/main/java/org/elasticsearch/common/filesystem/LinuxFileSystemNatives.java @@ -90,7 +90,7 @@ final class LinuxFileSystemNatives implements FileSystemNatives.Provider { final Stat stats = new Stat(); final int rc = XStatLibrary.__xstat(STAT_VER, path.toString(), stats); 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); } catch (LastErrorException e) { diff --git a/x-pack/plugin/searchable-snapshots/src/test/java/org/elasticsearch/xpack/searchablesnapshots/cache/common/CacheFileTests.java b/x-pack/plugin/searchable-snapshots/src/test/java/org/elasticsearch/xpack/searchablesnapshots/cache/common/CacheFileTests.java index 7c105dc360db..8ad0c83fcbc7 100644 --- a/x-pack/plugin/searchable-snapshots/src/test/java/org/elasticsearch/xpack/searchablesnapshots/cache/common/CacheFileTests.java +++ b/x-pack/plugin/searchable-snapshots/src/test/java/org/elasticsearch/xpack/searchablesnapshots/cache/common/CacheFileTests.java @@ -436,13 +436,9 @@ public class CacheFileTests extends ESTestCase { allOf(greaterThan(0L), lessThan(oneMb)) ); - final long blockSize; - if (Constants.LINUX) { - // on Linux we can infer the filesystem's block size if only 1 byte was written - blockSize = sizeOnDisk.getAsLong(); - } else { - blockSize = 0L; - } + // on Linux we can infer the filesystem's block size if only 1 byte was written, + // but this is not always right with encryption at rest using dmcrypt + final long blockSize = Constants.LINUX ? sizeOnDisk.getAsLong() : 0L; fill(fileChannel, 0, Math.toIntExact(cacheFile.getLength())); fileChannel.force(false); @@ -455,13 +451,29 @@ public class CacheFileTests extends ESTestCase { greaterThanOrEqualTo(cacheFile.getLength()) ); - if (Constants.LINUX) { + if (blockSize > 0L) { final long nbBlocks = (cacheFile.getLength() + blockSize - 1) / blockSize; // ceil(cacheFile.getLength() / blockSize) - assertThat( - "Cache file size mismatches (block size: " + blockSize + ", number of blocks: " + nbBlocks + ')', - sizeOnDisk.getAsLong(), - equalTo(nbBlocks * blockSize) - ); + final long expectedSize = nbBlocks * blockSize; + if (blockSize == fourKb) { + assertThat( + "Cache file size mismatches (block size: " + + blockSize + + ", number of blocks: " + + nbBlocks + + ", file length: " + + cacheFile.getLength() + + ')', + sizeOnDisk.getAsLong(), + 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 { cacheFile.release(listener);