diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2021-09-20 22:44:00 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2021-09-20 22:44:00 +0000 |
commit | 611286b39576d28919839078fa53e1813120160d (patch) | |
tree | 7664caf564aa324a52b94d5de25335f279188b1e | |
parent | 012f638b12fede33417e7ae4c99059958fbb41c7 (diff) | |
parent | 777df0107f858402794214dd6a7dec4dd36334c9 (diff) | |
download | incremental_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.cpp | 20 | ||||
-rw-r--r-- | incfs/include/incfs.h | 1 | ||||
-rw-r--r-- | incfs/include/incfs_ndk.h | 6 | ||||
-rw-r--r-- | incfs/tests/incfs_test.cpp | 127 | ||||
-rw-r--r-- | incfs/tests/include/IncFsTestBase.h | 1 |
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_; |