From 05ca9154315ae10a8e132ff6bab2e1dc375a9325 Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Fri, 2 Apr 2021 21:28:51 -0700 Subject: [PATCH] fs_mgr: add readahead_size_kb in fstab This patch adds an option, readahead_size_kb in fstab entry option. It supports to set a proper readahead_size per block/dm devices before using them by mount, which is useful for low/high-end devices when addressing memory pressure issue. Bug: 181567573 Signed-off-by: Jaegeuk Kim Change-Id: I549962e68f8488417d76bcfb283958bc33fd5d7a --- fs_mgr/fs_mgr.cpp | 45 ++++++++++++++++++++++++ fs_mgr/fs_mgr_fstab.cpp | 7 ++++ fs_mgr/include_fstab/fstab/fstab.h | 1 + fs_mgr/tests/fs_mgr_test.cpp | 56 ++++++++++++++++++++++++++++++ 4 files changed, 109 insertions(+) diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp index 6952cdf96..bbbb7e8c6 100644 --- a/fs_mgr/fs_mgr.cpp +++ b/fs_mgr/fs_mgr.cpp @@ -647,6 +647,46 @@ bool fs_mgr_is_f2fs(const std::string& blk_device) { return sb == cpu_to_le32(F2FS_SUPER_MAGIC); } +static void SetReadAheadSize(const std::string& entry_block_device, off64_t size_kb) { + std::string block_device; + if (!Realpath(entry_block_device, &block_device)) { + PERROR << "Failed to realpath " << entry_block_device; + return; + } + + static constexpr std::string_view kDevBlockPrefix("/dev/block/"); + if (!android::base::StartsWith(block_device, kDevBlockPrefix)) { + LWARNING << block_device << " is not a block device"; + return; + } + + DeviceMapper& dm = DeviceMapper::Instance(); + while (true) { + std::string block_name = block_device; + if (android::base::StartsWith(block_device, kDevBlockPrefix)) { + block_name = block_device.substr(kDevBlockPrefix.length()); + } + std::string sys_partition = + android::base::StringPrintf("/sys/class/block/%s/partition", block_name.c_str()); + struct stat info; + if (lstat(sys_partition.c_str(), &info) == 0) { + // it has a partition like "sda12". + block_name += "/.."; + } + std::string sys_ra = android::base::StringPrintf("/sys/class/block/%s/queue/read_ahead_kb", + block_name.c_str()); + std::string size = android::base::StringPrintf("%llu", (long long)size_kb); + android::base::WriteStringToFile(size, sys_ra.c_str()); + LINFO << "Set readahead_kb: " << size << " on " << sys_ra; + + auto parent = dm.GetParentBlockDeviceByPath(block_device); + if (!parent) { + return; + } + block_device = *parent; + } +} + // // Prepare the filesystem on the given block device to be mounted. // @@ -667,6 +707,11 @@ static int prepare_fs_for_mount(const std::string& blk_device, const FstabEntry& } mkdir(mount_point.c_str(), 0755); + // Don't need to return error, since it's a salt + if (entry.readahead_size_kb != -1) { + SetReadAheadSize(blk_device, entry.readahead_size_kb); + } + int fs_stat = 0; if (is_extfs(entry.fs_type)) { diff --git a/fs_mgr/fs_mgr_fstab.cpp b/fs_mgr/fs_mgr_fstab.cpp index ad48dd105..42bf35660 100644 --- a/fs_mgr/fs_mgr_fstab.cpp +++ b/fs_mgr/fs_mgr_fstab.cpp @@ -255,6 +255,13 @@ void ParseFsMgrFlags(const std::string& flags, FstabEntry* entry) { } else { entry->reserved_size = static_cast(size); } + } else if (StartsWith(flag, "readahead_size_kb=")) { + int val; + if (ParseInt(arg, &val, 0, 16 * 1024)) { + entry->readahead_size_kb = val; + } else { + LWARNING << "Warning: readahead_size_kb= flag malformed (0 ~ 16MB): " << arg; + } } else if (StartsWith(flag, "eraseblk=")) { // The erase block size flag is followed by an = and the flash erase block size. Get it, // check that it is a power of 2 and at least 4096, and return it. diff --git a/fs_mgr/include_fstab/fstab/fstab.h b/fs_mgr/include_fstab/fstab/fstab.h index 8ecf41bf3..2704e47a6 100644 --- a/fs_mgr/include_fstab/fstab/fstab.h +++ b/fs_mgr/include_fstab/fstab/fstab.h @@ -47,6 +47,7 @@ struct FstabEntry { int max_comp_streams = 0; off64_t zram_size = 0; off64_t reserved_size = 0; + off64_t readahead_size_kb = -1; std::string encryption_options; off64_t erase_blk_size = 0; off64_t logical_blk_size = 0; diff --git a/fs_mgr/tests/fs_mgr_test.cpp b/fs_mgr/tests/fs_mgr_test.cpp index 5887641e3..9adb6bd5a 100644 --- a/fs_mgr/tests/fs_mgr_test.cpp +++ b/fs_mgr/tests/fs_mgr_test.cpp @@ -1097,3 +1097,59 @@ TEST(fs_mgr, UserdataMountedFromDefaultFstab) { ASSERT_NE(nullptr, fs_mgr_get_mounted_entry_for_userdata(&fstab, block_device)) << "/data wasn't mounted from default fstab"; } + +TEST(fs_mgr, ReadFstabFromFile_FsMgrOptions_Readahead_Size_KB) { + TemporaryFile tf; + ASSERT_TRUE(tf.fd != -1); + std::string fstab_contents = R"fs( +source none0 swap defaults readahead_size_kb=blah +source none1 swap defaults readahead_size_kb=128 +source none2 swap defaults readahead_size_kb=5% +source none3 swap defaults readahead_size_kb=5kb +source none4 swap defaults readahead_size_kb=16385 +source none5 swap defaults readahead_size_kb=-128 +source none6 swap defaults readahead_size_kb=0 +)fs"; + ASSERT_TRUE(android::base::WriteStringToFile(fstab_contents, tf.path)); + + Fstab fstab; + EXPECT_TRUE(ReadFstabFromFile(tf.path, &fstab)); + ASSERT_EQ(7U, fstab.size()); + + FstabEntry::FsMgrFlags flags = {}; + + auto entry = fstab.begin(); + EXPECT_EQ("none0", entry->mount_point); + EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags)); + EXPECT_EQ(-1, entry->readahead_size_kb); + entry++; + + EXPECT_EQ("none1", entry->mount_point); + EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags)); + EXPECT_EQ(128, entry->readahead_size_kb); + entry++; + + EXPECT_EQ("none2", entry->mount_point); + EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags)); + EXPECT_EQ(-1, entry->readahead_size_kb); + entry++; + + EXPECT_EQ("none3", entry->mount_point); + EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags)); + EXPECT_EQ(-1, entry->readahead_size_kb); + entry++; + + EXPECT_EQ("none4", entry->mount_point); + EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags)); + EXPECT_EQ(-1, entry->readahead_size_kb); + entry++; + + EXPECT_EQ("none5", entry->mount_point); + EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags)); + EXPECT_EQ(-1, entry->readahead_size_kb); + entry++; + + EXPECT_EQ("none6", entry->mount_point); + EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags)); + EXPECT_EQ(0, entry->readahead_size_kb); +}