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 <jaegeuk@google.com> Change-Id: I549962e68f8488417d76bcfb283958bc33fd5d7a
This commit is contained in:
parent
ce61fb390a
commit
05ca915431
4 changed files with 109 additions and 0 deletions
|
@ -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)) {
|
||||
|
|
|
@ -255,6 +255,13 @@ void ParseFsMgrFlags(const std::string& flags, FstabEntry* entry) {
|
|||
} else {
|
||||
entry->reserved_size = static_cast<off64_t>(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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue