From ec5f63527039024e5534fa4c9b1737675e586fc1 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 29 Jul 2021 13:50:43 -0700 Subject: [PATCH] Set the I/O scheduler of loop devices to 'none' The user interface of Android devices becomes very slow under memory pressure. This is because Android uses the zram driver on top of the loop driver for swapping, because under memory pressure the swap code alternates reads and writes quickly, because mq-deadline is the default scheduler for loop devices and because mq-deadline delays writes by five seconds for such a workload with default settings. Fix this by selecting I/O scheduler 'none' for loop devices. Bug: 194450129 Test: Built Android images, installed these and verified that the I/O scheduler of all loop devices is 'none' instead of 'mq-deadline'. Change-Id: Ia5f606504b663948ab56955cad5a71885a356430 Signed-off-by: Bart Van Assche --- fs_mgr/fs_mgr.cpp | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp index 5484889d3..ec661442b 100644 --- a/fs_mgr/fs_mgr.cpp +++ b/fs_mgr/fs_mgr.cpp @@ -34,11 +34,13 @@ #include #include +#include #include #include #include #include #include +#include #include #include #include @@ -101,6 +103,7 @@ using android::base::GetUintProperty; using android::base::Realpath; using android::base::SetProperty; using android::base::StartsWith; +using android::base::StringPrintf; using android::base::Timer; using android::base::unique_fd; using android::dm::DeviceMapper; @@ -2044,6 +2047,35 @@ int fs_mgr_do_tmpfs_mount(const char *n_name) return 0; } +static bool ConfigureIoScheduler(const std::string& device_path) { + if (!StartsWith(device_path, "/dev/")) { + LERROR << __func__ << ": invalid argument " << device_path; + return false; + } + + const std::string iosched_path = + StringPrintf("/sys/block/%s/queue/scheduler", Basename(device_path).c_str()); + unique_fd iosched_fd(open(iosched_path.c_str(), O_RDWR | O_CLOEXEC)); + if (iosched_fd.get() == -1) { + PERROR << __func__ << ": failed to open " << iosched_path; + return false; + } + + // Kernels before v4.1 only support 'noop'. Kernels [v4.1, v5.0) support + // 'noop' and 'none'. Kernels v5.0 and later only support 'none'. + static constexpr const std::array kNoScheduler = {"none", "noop"}; + + for (const std::string_view& scheduler : kNoScheduler) { + int ret = write(iosched_fd.get(), scheduler.data(), scheduler.size()); + if (ret > 0) { + return true; + } + } + + PERROR << __func__ << ": failed to write to " << iosched_path; + return false; +} + static bool InstallZramDevice(const std::string& device) { if (!android::base::WriteStringToFile(device, ZRAM_BACK_DEV)) { PERROR << "Cannot write " << device << " in: " << ZRAM_BACK_DEV; @@ -2076,6 +2108,8 @@ static bool PrepareZramBackingDevice(off64_t size) { return false; } + ConfigureIoScheduler(loop_device); + // set block size & direct IO unique_fd loop_fd(TEMP_FAILURE_RETRY(open(loop_device.c_str(), O_RDWR | O_CLOEXEC))); if (loop_fd.get() == -1) {