summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2021-09-20 22:44:00 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2021-09-20 22:44:00 +0000
commit611286b39576d28919839078fa53e1813120160d (patch)
tree7664caf564aa324a52b94d5de25335f279188b1e
parent012f638b12fede33417e7ae4c99059958fbb41c7 (diff)
parent777df0107f858402794214dd6a7dec4dd36334c9 (diff)
downloadincremental_delivery-611286b39576d28919839078fa53e1813120160d.tar.gz
Merge cherrypicks of [15873636, 15873851, 15873852, 15873654, 15873655, 15873656, 15873657, 15873637, 15873638, 15873639, 15873339, 15873340, 15873341, 15873342, 15873343, 15873344, 15873345, 15873346, 15873947, 15873948, 15873949, 15873950, 15873951, 15873952, 15873953, 15873954, 15873955, 15873956, 15873957, 15873958, 15873959, 15873960, 15873961, 15873642, 15873122, 15873323, 15873123, 15873324, 15872698, 15872700, 15873987, 15873962, 15873963, 15873964, 15873965, 15873557, 15873558, 15873816, 15873643, 15873817, 15873660, 15873559, 15873988, 15873644, 15873645, 15873646, 15873325, 15873661, 15873662, 15873663, 15874027, 15874028, 15874029, 15874030, 15874031, 15874032, 15874033, 15874034, 15874035, 15874036, 15874037, 15874038, 15874039, 15874040, 15874041, 15874042, 15873560, 15873561, 15873854, 15873855, 15873562, 15873563, 15873564, 15873565, 15873566, 15874047, 15874048, 15873326, 15873124, 15874043, 15872622, 15872623, 15873857, 15872701, 15872702] into sc-d1-releaseandroid-12.0.0_r15android-12.0.0_r14android-12.0.0_r13android-12.0.0_r12android12-d1-s6-releaseandroid12-d1-s5-releaseandroid12-d1-release
Change-Id: I8ffdbd3b23ef72e909436319923b5e8811f1072e
-rw-r--r--incfs/incfs.cpp20
-rw-r--r--incfs/include/incfs.h1
-rw-r--r--incfs/include/incfs_ndk.h6
-rw-r--r--incfs/tests/incfs_test.cpp127
-rw-r--r--incfs/tests/include/IncFsTestBase.h1
5 files changed, 142 insertions, 13 deletions
diff --git a/incfs/incfs.cpp b/incfs/incfs.cpp
index 490b907..842e381 100644
--- a/incfs/incfs.cpp
+++ b/incfs/incfs.cpp
@@ -252,14 +252,15 @@ bool IncFs_IsEnabled() {
static Features readIncFsFeatures() {
init().enabledAndReady();
+ int res = Features::none | Features::mappingFilesProgressFixed;
+
static const char kSysfsFeaturesDir[] = "/sys/fs/" INCFS_NAME "/features";
const auto dir = path::openDir(kSysfsFeaturesDir);
if (!dir) {
PLOG(ERROR) << "IncFs_Features: failed to open features dir, assuming v1/none.";
- return Features::none;
+ return Features(res);
}
- int res = Features::none;
while (auto entry = ::readdir(dir.get())) {
if (entry->d_type != DT_REG) {
continue;
@@ -1555,7 +1556,7 @@ IncFsErrorCode IncFs_IsFullyLoadedByPath(const IncFsControl* control, const char
if (features() & Features::v2) {
const auto id = getId(::getxattr, path);
if (id == kIncFsInvalidFileId) {
- return -errno;
+ return -ENOTSUP;
}
return isFullyLoadedV2(root, id);
}
@@ -1692,7 +1693,20 @@ IncFsErrorCode IncFs_GetUidReadTimeouts(const IncFsControl* control,
return 0;
}
+// Trying to detect if this is a mapped file.
+// Not the best way as it might return true for other system files.
+// TODO: remove after IncFS returns ENOTSUP for such files.
+static bool isMapped(int fd) {
+ char buffer[kIncFsFileIdStringLength];
+ const auto res = ::fgetxattr(fd, kIdAttrName, buffer, sizeof(buffer));
+ return res != sizeof(buffer);
+}
+
static IncFsErrorCode getFileBlockCount(int fd, IncFsBlockCounts* blockCount) {
+ if (isMapped(fd)) {
+ return -ENOTSUP;
+ }
+
incfs_get_block_count_args args = {};
auto res = ::ioctl(fd, INCFS_IOC_GET_BLOCK_COUNT, &args);
if (res < 0) {
diff --git a/incfs/include/incfs.h b/incfs/include/incfs.h
index 76619c2..5dfe060 100644
--- a/incfs/include/incfs.h
+++ b/incfs/include/incfs.h
@@ -41,6 +41,7 @@ enum Features {
none = INCFS_FEATURE_NONE,
core = INCFS_FEATURE_CORE,
v2 = INCFS_FEATURE_V2,
+ mappingFilesProgressFixed = INCFS_FEATURE_MAPPING_FILES_PROGRESS_FIXED,
};
enum class HashAlgorithm {
diff --git a/incfs/include/incfs_ndk.h b/incfs/include/incfs_ndk.h
index 2a538bc..4862f39 100644
--- a/incfs/include/incfs_ndk.h
+++ b/incfs/include/incfs_ndk.h
@@ -43,8 +43,10 @@ static const int kIncFsFileIdStringLength = sizeof(IncFsFileId) * 2;
typedef enum {
INCFS_FEATURE_NONE = 0,
- INCFS_FEATURE_CORE = 1,
- INCFS_FEATURE_V2 = 2,
+ INCFS_FEATURE_CORE = 1 << 0,
+ INCFS_FEATURE_V2 = 1 << 1,
+ INCFS_FEATURE_MAPPING_FILES_PROGRESS_FIXED = 1 << 2,
+
} IncFsFeatures;
typedef int IncFsErrorCode;
diff --git a/incfs/tests/incfs_test.cpp b/incfs/tests/incfs_test.cpp
index e651f2e..94bbdcd 100644
--- a/incfs/tests/incfs_test.cpp
+++ b/incfs/tests/incfs_test.cpp
@@ -105,25 +105,29 @@ protected:
ASSERT_EQ((int)std::size(blocks), writeBlocks({blocks, std::size(blocks)}));
}
- template <class ReadStruct>
- void testWriteBlockAndPageRead() {
- const auto id = fileId(1);
- ASSERT_TRUE(control_.logs() >= 0);
- ASSERT_EQ(0,
- makeFile(control_, mountPath(test_file_name_), 0555, id,
- {.size = test_file_size_}));
+ void writeBlock(int pageIndex) {
auto fd = openForSpecialOps(control_, fileId(1));
ASSERT_GE(fd.get(), 0);
std::vector<char> data(INCFS_DATA_FILE_BLOCK_SIZE);
auto block = DataBlock{
.fileFd = fd.get(),
- .pageIndex = 0,
+ .pageIndex = pageIndex,
.compression = INCFS_COMPRESSION_KIND_NONE,
.dataSize = (uint32_t)data.size(),
.data = data.data(),
};
ASSERT_EQ(1, writeBlocks({&block, 1}));
+ }
+
+ template <class ReadStruct>
+ void testWriteBlockAndPageRead() {
+ const auto id = fileId(1);
+ ASSERT_TRUE(control_.logs() >= 0);
+ ASSERT_EQ(0,
+ makeFile(control_, mountPath(test_file_name_), 0555, id,
+ {.size = test_file_size_}));
+ writeBlock(/*pageIndex=*/0);
std::thread wait_page_read_thread([&]() {
std::vector<ReadStruct> reads;
@@ -149,6 +153,7 @@ protected:
ASSERT_TRUE(android::base::ReadFully(readFd, buf, sizeof(buf)));
wait_page_read_thread.join();
}
+
template <class PendingRead>
void testWaitForPendingReads() {
const auto id = fileId(1);
@@ -366,6 +371,39 @@ TEST_F(IncFsTest, MakeFile0) {
ASSERT_EQ(0, (int)s.st_size);
}
+TEST_F(IncFsTest, MakeMappedFile) {
+ ASSERT_EQ(0, makeDir(control_, mountPath(test_dir_name_)));
+
+ constexpr auto file_size = INCFS_DATA_FILE_BLOCK_SIZE * 2;
+ constexpr auto mapped_file_offset = file_size / 2;
+ constexpr auto mapped_file_size = file_size / 3;
+
+ const auto file_path = mountPath(test_dir_name_, test_file_name_);
+ ASSERT_FALSE(exists(file_path));
+ ASSERT_EQ(0,
+ makeFile(control_, file_path, 0111, fileId(1),
+ {.size = file_size, .metadata = metadata("md")}));
+ struct stat s = {};
+ ASSERT_EQ(0, stat(file_path.c_str(), &s));
+ ASSERT_EQ(file_size, (int)s.st_size);
+
+ const auto mapped_file_path = mountPath(test_dir_name_, test_mapped_file_name_);
+ ASSERT_FALSE(exists(mapped_file_path));
+ ASSERT_EQ(0,
+ makeMappedFile(control_, mapped_file_path, 0111,
+ {.sourceId = fileId(1),
+ .sourceOffset = mapped_file_offset,
+ .size = mapped_file_size}));
+ s = {};
+ ASSERT_EQ(0, stat(mapped_file_path.c_str(), &s));
+ ASSERT_EQ(mapped_file_size, (int)s.st_size);
+
+ // Check fileId for the source file.
+ ASSERT_EQ(fileId(1), getFileId(control_, file_path));
+ // Check that there is no fileId for the mapped file.
+ ASSERT_EQ(kIncFsInvalidFileId, getFileId(control_, mapped_file_path));
+}
+
TEST_F(IncFsTest, GetFileId) {
auto id = fileId(1);
ASSERT_EQ(0,
@@ -1384,3 +1422,76 @@ TEST_F(IncFsGetMetricsTest, MetricsWithReadsDelayedPerUidTimeout) {
EXPECT_EQ(0, (int)incfsMetrics.readsFailedOther);
EXPECT_EQ(0, (int)incfsMetrics.readsFailedTimedOut);
}
+
+inline bool operator==(const BlockCounts& lhs, const BlockCounts& rhs) {
+ return lhs.totalDataBlocks == rhs.totalDataBlocks &&
+ lhs.filledDataBlocks == rhs.filledDataBlocks &&
+ lhs.totalHashBlocks == rhs.totalHashBlocks &&
+ lhs.filledHashBlocks == rhs.filledHashBlocks;
+}
+
+TEST_F(IncFsTest, LoadingProgress) {
+ ASSERT_EQ(0, makeDir(control_, mountPath(test_dir_name_)));
+
+ constexpr auto file_size = INCFS_DATA_FILE_BLOCK_SIZE * 2;
+ constexpr auto mapped_file_offset = file_size / 2;
+ constexpr auto mapped_file_size = file_size / 3;
+
+ const auto file_id = fileId(1);
+
+ const auto file_path = mountPath(test_dir_name_, test_file_name_);
+ ASSERT_FALSE(exists(file_path));
+ ASSERT_EQ(0,
+ makeFile(control_, file_path, 0111, file_id,
+ {.size = file_size, .metadata = metadata("md")}));
+ struct stat s = {};
+ ASSERT_EQ(0, stat(file_path.c_str(), &s));
+ ASSERT_EQ(file_size, (int)s.st_size);
+
+ const auto mapped_file_path = mountPath(test_dir_name_, test_mapped_file_name_);
+ ASSERT_FALSE(exists(mapped_file_path));
+ ASSERT_EQ(0,
+ makeMappedFile(control_, mapped_file_path, 0111,
+ {.sourceId = file_id,
+ .sourceOffset = mapped_file_offset,
+ .size = mapped_file_size}));
+ s = {};
+ ASSERT_EQ(0, stat(mapped_file_path.c_str(), &s));
+ ASSERT_EQ(mapped_file_size, (int)s.st_size);
+
+ // Check fully loaded first.
+ ASSERT_EQ(LoadingState::MissingBlocks, isFullyLoaded(control_, file_path));
+ ASSERT_EQ(LoadingState::MissingBlocks, isFullyLoaded(control_, file_id));
+ ASSERT_EQ((LoadingState)-ENOTSUP, isFullyLoaded(control_, mapped_file_path));
+
+ // Next is loading progress.
+ ASSERT_EQ(BlockCounts{.totalDataBlocks = 2}, *getBlockCount(control_, file_path));
+ ASSERT_EQ(BlockCounts{.totalDataBlocks = 2}, *getBlockCount(control_, file_id));
+ ASSERT_FALSE(getBlockCount(control_, mapped_file_path));
+
+ // Now write a page #0.
+ ASSERT_NO_FATAL_FAILURE(writeBlock(0));
+
+ // Recheck everything.
+ ASSERT_EQ(LoadingState::MissingBlocks, isFullyLoaded(control_, file_path));
+ ASSERT_EQ(LoadingState::MissingBlocks, isFullyLoaded(control_, file_id));
+ ASSERT_EQ((LoadingState)-ENOTSUP, isFullyLoaded(control_, mapped_file_path));
+
+ BlockCounts onePage{.totalDataBlocks = 2, .filledDataBlocks = 1};
+ ASSERT_EQ(onePage, *getBlockCount(control_, file_path));
+ ASSERT_EQ(onePage, *getBlockCount(control_, file_id));
+ ASSERT_FALSE(getBlockCount(control_, mapped_file_path));
+
+ // Now write a page #1.
+ ASSERT_NO_FATAL_FAILURE(writeBlock(1));
+
+ // Check for fully loaded.
+ ASSERT_EQ(LoadingState::Full, isFullyLoaded(control_, file_path));
+ ASSERT_EQ(LoadingState::Full, isFullyLoaded(control_, file_id));
+ ASSERT_EQ((LoadingState)-ENOTSUP, isFullyLoaded(control_, mapped_file_path));
+
+ BlockCounts twoPages{.totalDataBlocks = 2, .filledDataBlocks = 2};
+ ASSERT_EQ(twoPages, *getBlockCount(control_, file_path));
+ ASSERT_EQ(twoPages, *getBlockCount(control_, file_id));
+ ASSERT_FALSE(getBlockCount(control_, mapped_file_path));
+}
diff --git a/incfs/tests/include/IncFsTestBase.h b/incfs/tests/include/IncFsTestBase.h
index 5f8c311..8c61d64 100644
--- a/incfs/tests/include/IncFsTestBase.h
+++ b/incfs/tests/include/IncFsTestBase.h
@@ -117,6 +117,7 @@ protected:
std::string image_dir_path_;
std::optional<TemporaryDir> tmp_dir_for_image_;
inline static const std::string_view test_file_name_ = "test.txt";
+ inline static const std::string_view test_mapped_file_name_ = "mapped.txt";
inline static const std::string_view test_dir_name_ = "test_dir";
std::string metrics_key_;
Control control_;