From c86ab6f538bec63638c168d6c843fe7cf73add3b Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Fri, 26 Jun 2015 14:02:09 -0700 Subject: [PATCH] Trim both internal and adopted private storage. Refactor fstrim code to be encapsulated in unique task object, and give it option of benchmarking when finished. Trimming now includes both storage from fstab and adopted private volumes. Cleaner timing stats are logged for each unique volume. Add wakelock during ongoing async move tasks. Push disk sysfs path to framework so it can parse any SD card registers as desired. Bug: 21831325 Change-Id: I76577685f5cae4929c251ad314ffdaeb5eb1c8bf --- Android.mk | 2 +- Benchmark.cpp | 72 ++++++++++--------- Benchmark.h | 3 +- CommandListener.cpp | 45 +++++------- Disk.cpp | 10 +++ Disk.h | 3 + MoveTask.cpp | 7 ++ ResponseCode.h | 2 + TrimTask.cpp | 155 +++++++++++++++++++++++++++++++++++++++++ TrimTask.h | 54 +++++++++++++++ Utils.cpp | 7 ++ Utils.h | 2 + VolumeManager.cpp | 41 ++++------- VolumeManager.h | 4 +- fstrim.c | 165 -------------------------------------------- fstrim.h | 24 ------- main.cpp | 18 ++--- 17 files changed, 322 insertions(+), 292 deletions(-) create mode 100644 TrimTask.cpp create mode 100644 TrimTask.h delete mode 100644 fstrim.c delete mode 100644 fstrim.h diff --git a/Android.mk b/Android.mk index d403b96..38da8c7 100644 --- a/Android.mk +++ b/Android.mk @@ -17,7 +17,6 @@ common_src_files := \ CheckBattery.cpp \ Ext4Crypt.cpp \ VoldUtil.c \ - fstrim.c \ cryptfs.c \ Disk.cpp \ VolumeBase.cpp \ @@ -27,6 +26,7 @@ common_src_files := \ Utils.cpp \ MoveTask.cpp \ Benchmark.cpp \ + TrimTask.cpp \ common_c_includes := \ system/extras/ext4_utils \ diff --git a/Benchmark.cpp b/Benchmark.cpp index e329588..7a3af65 100644 --- a/Benchmark.cpp +++ b/Benchmark.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -33,14 +34,19 @@ using android::base::WriteStringToFile; namespace android { namespace vold { -static std::string simpleRead(const std::string& path) { - std::string tmp; - ReadFileToString(path, &tmp); - tmp.erase(tmp.find_last_not_of(" \n\r") + 1); - return tmp; +static void notifyResult(const std::string& path, int64_t create_d, + int64_t drop_d, int64_t run_d, int64_t destroy_d) { + std::string res(path + + + " " + BenchmarkIdent() + + " " + std::to_string(create_d) + + " " + std::to_string(drop_d) + + " " + std::to_string(run_d) + + " " + std::to_string(destroy_d)); + VolumeManager::Instance()->getBroadcaster()->sendBroadcast( + ResponseCode::BenchmarkResult, res.c_str(), false); } -nsecs_t Benchmark(const std::string& path, const std::string& sysPath) { +static nsecs_t benchmark(const std::string& path) { errno = 0; int orig_prio = getpriority(PRIO_PROCESS, 0); if (errno != 0) { @@ -82,9 +88,11 @@ nsecs_t Benchmark(const std::string& path, const std::string& sysPath) { sync(); nsecs_t create = systemTime(SYSTEM_TIME_BOOTTIME); + LOG(VERBOSE) << "Before drop_caches"; if (!WriteStringToFile("3", "/proc/sys/vm/drop_caches")) { PLOG(ERROR) << "Failed to drop_caches"; } + LOG(VERBOSE) << "After drop_caches"; nsecs_t drop = systemTime(SYSTEM_TIME_BOOTTIME); BenchmarkRun(); @@ -95,6 +103,16 @@ nsecs_t Benchmark(const std::string& path, const std::string& sysPath) { sync(); nsecs_t destroy = systemTime(SYSTEM_TIME_BOOTTIME); + if (chdir(orig_cwd) != 0) { + PLOG(ERROR) << "Failed to chdir"; + } + if (android_set_ioprio(0, orig_clazz, orig_ioprio)) { + PLOG(ERROR) << "Failed to android_set_ioprio"; + } + if (setpriority(PRIO_PROCESS, 0, orig_prio) != 0) { + PLOG(ERROR) << "Failed to setpriority"; + } + nsecs_t create_d = create - start; nsecs_t drop_d = drop - create; nsecs_t run_d = run - drop; @@ -105,38 +123,26 @@ nsecs_t Benchmark(const std::string& path, const std::string& sysPath) { LOG(INFO) << "run took " << nanoseconds_to_milliseconds(run_d) << "ms"; LOG(INFO) << "destroy took " << nanoseconds_to_milliseconds(destroy_d) << "ms"; - std::string detail; - detail += "id=" + BenchmarkIdent() - + ",cr=" + std::to_string(create_d) - + ",dr=" + std::to_string(drop_d) - + ",ru=" + std::to_string(run_d) - + ",de=" + std::to_string(destroy_d) - + ",si=" + simpleRead(sysPath + "/size") - + ",ve=" + simpleRead(sysPath + "/device/vendor") - + ",mo=" + simpleRead(sysPath + "/device/model") - + ",csd=" + simpleRead(sysPath + "/device/csd"); - - // Scrub CRC and serial number out of CID - std::string cid = simpleRead(sysPath + "/device/cid"); - if (cid.length() == 32) { - cid.erase(32, 1); - cid.erase(18, 8); - detail += ",cid=" + cid; - } + notifyResult(path, create_d, drop_d, run_d, destroy_d); - VolumeManager::Instance()->getBroadcaster()->sendBroadcast( - ResponseCode::BenchmarkResult, detail.c_str(), false); + return run_d; +} - if (chdir(orig_cwd) != 0) { - PLOG(ERROR) << "Failed to chdir"; +nsecs_t BenchmarkPrivate(const std::string& path) { + std::string benchPath(path); + benchPath += "/misc"; + if (android::vold::PrepareDir(benchPath, 01771, AID_SYSTEM, AID_MISC)) { + return -1; } - if (android_set_ioprio(0, orig_clazz, orig_ioprio)) { - PLOG(ERROR) << "Failed to android_set_ioprio"; + benchPath += "/vold"; + if (android::vold::PrepareDir(benchPath, 0700, AID_ROOT, AID_ROOT)) { + return -1; } - if (setpriority(PRIO_PROCESS, 0, orig_prio) != 0) { - PLOG(ERROR) << "Failed to setpriority"; + benchPath += "/bench"; + if (android::vold::PrepareDir(benchPath, 0700, AID_ROOT, AID_ROOT)) { + return -1; } - return run_d; + return benchmark(benchPath); } } // namespace vold diff --git a/Benchmark.h b/Benchmark.h index 02e22d5..13f9009 100644 --- a/Benchmark.h +++ b/Benchmark.h @@ -25,7 +25,8 @@ namespace android { namespace vold { -nsecs_t Benchmark(const std::string& path, const std::string& sysPath); +/* Benchmark a private volume mounted at the given path */ +nsecs_t BenchmarkPrivate(const std::string& path); } // namespace vold } // namespace android diff --git a/CommandListener.cpp b/CommandListener.cpp index 32be05c..36d2950 100644 --- a/CommandListener.cpp +++ b/CommandListener.cpp @@ -45,8 +45,8 @@ #include "Loop.h" #include "Devmapper.h" #include "cryptfs.h" -#include "fstrim.h" #include "MoveTask.h" +#include "TrimTask.h" #define DUMP_ARGS 0 @@ -255,7 +255,7 @@ int CommandListener::VolumeCmd::runCommand(SocketClient *cli, } else if (cmd == "benchmark" && argc > 2) { // benchmark [volId] std::string id(argv[2]); - nsecs_t res = vm->benchmarkVolume(id); + nsecs_t res = vm->benchmarkPrivate(id); return cli->sendMsg(ResponseCode::CommandOkay, android::base::StringPrintf("%" PRId64, res).c_str(), false); @@ -600,32 +600,23 @@ int CommandListener::FstrimCmd::runCommand(SocketClient *cli, return 0; } - int rc = 0; + VolumeManager *vm = VolumeManager::Instance(); + std::lock_guard lock(vm->getLock()); - if (!strcmp(argv[1], "dotrim")) { - if (argc != 2) { - cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: fstrim dotrim", false); - return 0; - } - dumpArgs(argc, argv, -1); - rc = fstrim_filesystems(0); - } else if (!strcmp(argv[1], "dodtrim")) { - if (argc != 2) { - cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: fstrim dodtrim", false); - return 0; - } - dumpArgs(argc, argv, -1); - rc = fstrim_filesystems(1); /* Do Deep Discard trim */ - } else { - dumpArgs(argc, argv, -1); - cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown fstrim cmd", false); - } + int flags = 0; - // Always report that the command succeeded and return the error code. - // The caller will check the return value to see what the error was. - char msg[255]; - snprintf(msg, sizeof(msg), "%d", rc); - cli->sendMsg(ResponseCode::CommandOkay, msg, false); + std::string cmd(argv[1]); + if (cmd == "dotrim") { + flags = 0; + } else if (cmd == "dotrimbench") { + flags = android::vold::TrimTask::Flags::kBenchmarkAfter; + } else if (cmd == "dodtrim") { + flags = android::vold::TrimTask::Flags::kDeepTrim; + } else if (cmd == "dodtrimbench") { + flags = android::vold::TrimTask::Flags::kDeepTrim + | android::vold::TrimTask::Flags::kBenchmarkAfter; + } - return 0; + (new android::vold::TrimTask(flags))->start(); + return sendGenericOkFail(cli, 0); } diff --git a/Disk.cpp b/Disk.cpp index df53d07..1e76bee 100644 --- a/Disk.cpp +++ b/Disk.cpp @@ -105,6 +105,15 @@ std::shared_ptr Disk::findVolume(const std::string& id) { return nullptr; } +void Disk::listVolumes(VolumeBase::Type type, std::list& list) { + for (auto vol : mVolumes) { + if (vol->getType() == type) { + list.push_back(vol->getId()); + } + // TODO: consider looking at stacked volumes + } +} + status_t Disk::create() { CHECK(!mCreated); mCreated = true; @@ -229,6 +238,7 @@ status_t Disk::readMetadata() { notifyEvent(ResponseCode::DiskSizeChanged, StringPrintf("%" PRId64, mSize)); notifyEvent(ResponseCode::DiskLabelChanged, mLabel); + notifyEvent(ResponseCode::DiskSysPathChanged, mSysPath); return OK; } diff --git a/Disk.h b/Disk.h index 60e4fa9..77ec7df 100644 --- a/Disk.h +++ b/Disk.h @@ -18,6 +18,7 @@ #define ANDROID_VOLD_DISK_H #include "Utils.h" +#include "VolumeBase.h" #include @@ -64,6 +65,8 @@ public: std::shared_ptr findVolume(const std::string& id); + void listVolumes(VolumeBase::Type type, std::list& list); + status_t create(); status_t destroy(); diff --git a/MoveTask.cpp b/MoveTask.cpp index e0eec12..10cd549 100644 --- a/MoveTask.cpp +++ b/MoveTask.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -40,6 +41,8 @@ static const int kMoveFailedInternalError = -6; static const char* kCpPath = "/system/bin/cp"; static const char* kRmPath = "/system/bin/rm"; +static const char* kWakeLock = "MoveTask"; + MoveTask::MoveTask(const std::shared_ptr& from, const std::shared_ptr& to) : mFrom(from), mTo(to) { @@ -168,6 +171,8 @@ static void bringOnline(const std::shared_ptr& vol) { } void MoveTask::run() { + acquire_wake_lock(PARTIAL_WAKE_LOCK, kWakeLock); + std::string fromPath; std::string toPath; @@ -205,11 +210,13 @@ void MoveTask::run() { } notifyProgress(kMoveSucceeded); + release_wake_lock(kWakeLock); return; fail: bringOnline(mFrom); bringOnline(mTo); notifyProgress(kMoveFailedInternalError); + release_wake_lock(kWakeLock); return; } diff --git a/ResponseCode.h b/ResponseCode.h index 2d01087..f2c533e 100644 --- a/ResponseCode.h +++ b/ResponseCode.h @@ -70,6 +70,7 @@ public: static const int DiskSizeChanged = 641; static const int DiskLabelChanged = 642; static const int DiskScanned = 643; + static const int DiskSysPathChanged = 644; static const int DiskDestroyed = 649; static const int VolumeCreated = 650; @@ -83,6 +84,7 @@ public: static const int MoveStatus = 660; static const int BenchmarkResult = 661; + static const int TrimResult = 662; static int convertFromErrno(); }; diff --git a/TrimTask.cpp b/TrimTask.cpp new file mode 100644 index 0000000..1c6eb1f --- /dev/null +++ b/TrimTask.cpp @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "TrimTask.h" +#include "Benchmark.h" +#include "Utils.h" +#include "VolumeManager.h" +#include "ResponseCode.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +/* From a would-be kernel header */ +#define FIDTRIM _IOWR('f', 128, struct fstrim_range) /* Deep discard trim */ + +#define BENCHMARK_ENABLED 0 + +using android::base::StringPrintf; + +namespace android { +namespace vold { + +static const char* kWakeLock = "TrimTask"; + +TrimTask::TrimTask(int flags) : mFlags(flags) { + // Collect both fstab and vold volumes + addFromFstab(); + + VolumeManager* vm = VolumeManager::Instance(); + std::list privateIds; + vm->listVolumes(VolumeBase::Type::kPrivate, privateIds); + for (auto id : privateIds) { + auto vol = vm->findVolume(id); + if (vol != nullptr && vol->getState() == VolumeBase::State::kMounted) { + mPaths.push_back(vol->getPath()); + } + } +} + +TrimTask::~TrimTask() { +} + +void TrimTask::addFromFstab() { + struct fstab *fstab; + struct fstab_rec *prev_rec = NULL; + + fstab = fs_mgr_read_fstab(android::vold::DefaultFstabPath().c_str()); + for (int i = 0; i < fstab->num_entries; i++) { + /* Skip raw partitions */ + if (!strcmp(fstab->recs[i].fs_type, "emmc") || + !strcmp(fstab->recs[i].fs_type, "mtd")) { + continue; + } + /* Skip read-only filesystems */ + if (fstab->recs[i].flags & MS_RDONLY) { + continue; + } + if (fs_mgr_is_voldmanaged(&fstab->recs[i])) { + continue; /* Should we trim fat32 filesystems? */ + } + if (fs_mgr_is_notrim(&fstab->recs[i])) { + continue; + } + + /* Skip the multi-type partitions, which are required to be following each other. + * See fs_mgr.c's mount_with_alternatives(). + */ + if (prev_rec && !strcmp(prev_rec->mount_point, fstab->recs[i].mount_point)) { + continue; + } + + mPaths.push_back(fstab->recs[i].mount_point); + prev_rec = &fstab->recs[i]; + } + fs_mgr_free_fstab(fstab); +} + +void TrimTask::start() { + mThread = std::thread(&TrimTask::run, this); +} + +static void notifyResult(const std::string& path, int64_t bytes, int64_t delta) { + std::string res(path + + " " + std::to_string(bytes) + + " " + std::to_string(delta)); + VolumeManager::Instance()->getBroadcaster()->sendBroadcast( + ResponseCode::TrimResult, res.c_str(), false); +} + +void TrimTask::run() { + acquire_wake_lock(PARTIAL_WAKE_LOCK, kWakeLock); + + for (auto path : mPaths) { + LOG(DEBUG) << "Starting trim of " << path; + + int fd = open(path.c_str(), O_RDONLY | O_DIRECTORY | O_CLOEXEC | O_NOFOLLOW); + if (fd < 0) { + PLOG(WARNING) << "Failed to open " << path; + continue; + } + + struct fstrim_range range; + memset(&range, 0, sizeof(range)); + range.len = ULLONG_MAX; + + nsecs_t start = systemTime(SYSTEM_TIME_BOOTTIME); + if (ioctl(fd, (mFlags & Flags::kDeepTrim) ? FIDTRIM : FITRIM, &range)) { + PLOG(WARNING) << "Trim failed on " << path; + notifyResult(path, -1, -1); + } else { + nsecs_t delta = systemTime(SYSTEM_TIME_BOOTTIME) - start; + LOG(INFO) << "Trimmed " << range.len << " bytes on " << path + << " in " << nanoseconds_to_milliseconds(delta) << "ms"; + notifyResult(path, range.len, delta); + } + close(fd); + + if (mFlags & Flags::kBenchmarkAfter) { +#if BENCHMARK_ENABLED + BenchmarkPrivate(path); +#else + LOG(DEBUG) << "Benchmark disabled"; +#endif + } + } + + release_wake_lock(kWakeLock); +} + +} // namespace vold +} // namespace android diff --git a/TrimTask.h b/TrimTask.h new file mode 100644 index 0000000..57be802 --- /dev/null +++ b/TrimTask.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_VOLD_TRIM_TASK_H +#define ANDROID_VOLD_TRIM_TASK_H + +#include "Utils.h" + +#include +#include + +namespace android { +namespace vold { + +class TrimTask { +public: + TrimTask(int flags); + virtual ~TrimTask(); + + enum Flags { + kDeepTrim = 1 << 0, + kBenchmarkAfter = 1 << 1, + }; + + void start(); + +private: + int mFlags; + std::list mPaths; + std::thread mThread; + + void addFromFstab(); + void run(); + + DISALLOW_COPY_AND_ASSIGN(TrimTask); +}; + +} // namespace vold +} // namespace android + +#endif diff --git a/Utils.cpp b/Utils.cpp index ec9c906..06222c3 100644 --- a/Utils.cpp +++ b/Utils.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -532,5 +533,11 @@ dev_t GetDevice(const std::string& path) { } } +std::string DefaultFstabPath() { + char hardware[PROPERTY_VALUE_MAX]; + property_get("ro.hardware", hardware, ""); + return StringPrintf("/fstab.%s", hardware); +} + } // namespace vold } // namespace android diff --git a/Utils.h b/Utils.h index ce0f7c8..f33a379 100644 --- a/Utils.h +++ b/Utils.h @@ -92,6 +92,8 @@ std::string BuildKeyPath(const std::string& partGuid); dev_t GetDevice(const std::string& path); +std::string DefaultFstabPath(); + } // namespace vold } // namespace android diff --git a/VolumeManager.cpp b/VolumeManager.cpp index d1a0b2f..6710b0c 100755 --- a/VolumeManager.cpp +++ b/VolumeManager.cpp @@ -60,7 +60,6 @@ #include "Asec.h" #include "VoldUtil.h" #include "cryptfs.h" -#include "fstrim.h" #define MASS_STORAGE_FILE_PATH "/sys/class/android_usb/android0/f_mass_storage/lun/file" @@ -370,20 +369,23 @@ std::shared_ptr VolumeManager::findVolume(const std:: return nullptr; } -nsecs_t VolumeManager::benchmarkVolume(const std::string& id) { +void VolumeManager::listVolumes(android::vold::VolumeBase::Type type, + std::list& list) { + list.clear(); + for (auto disk : mDisks) { + disk->listVolumes(type, list); + } +} + +nsecs_t VolumeManager::benchmarkPrivate(const std::string& id) { std::string path; - std::string sysPath; - auto vol = findVolume(id); - if (vol != nullptr) { - if (vol->getState() == android::vold::VolumeBase::State::kMounted) { + if (id == "private" || id == "null") { + path = "/data"; + } else { + auto vol = findVolume(id); + if (vol != nullptr && vol->getState() == android::vold::VolumeBase::State::kMounted) { path = vol->getPath(); - auto disk = findDisk(vol->getDiskId()); - if (disk != nullptr) { - sysPath = disk->getSysPath(); - } } - } else { - path = "/data"; } if (path.empty()) { @@ -391,20 +393,7 @@ nsecs_t VolumeManager::benchmarkVolume(const std::string& id) { return -1; } - path += "/misc"; - if (android::vold::PrepareDir(path, 01771, AID_SYSTEM, AID_MISC)) { - return -1; - } - path += "/vold"; - if (android::vold::PrepareDir(path, 0700, AID_ROOT, AID_ROOT)) { - return -1; - } - path += "/bench"; - if (android::vold::PrepareDir(path, 0700, AID_ROOT, AID_ROOT)) { - return -1; - } - - return android::vold::Benchmark(path, sysPath); + return android::vold::BenchmarkPrivate(path); } int VolumeManager::forgetPartition(const std::string& partGuid) { diff --git a/VolumeManager.h b/VolumeManager.h index 6c094fc..fa2237f 100644 --- a/VolumeManager.h +++ b/VolumeManager.h @@ -118,7 +118,9 @@ public: std::shared_ptr findDisk(const std::string& id); std::shared_ptr findVolume(const std::string& id); - nsecs_t benchmarkVolume(const std::string& id); + void listVolumes(android::vold::VolumeBase::Type type, std::list& list); + + nsecs_t benchmarkPrivate(const std::string& id); int forgetPartition(const std::string& partGuid); diff --git a/fstrim.c b/fstrim.c deleted file mode 100644 index 60c9f24..0000000 --- a/fstrim.c +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#define LOG_TAG "fstrim" -#include "cutils/log.h" -#include "hardware_legacy/power.h" - -/* These numbers must match what the MountService specified in - * frameworks/base/services/java/com/android/server/EventLogTags.logtags - */ -#define LOG_FSTRIM_START 2755 -#define LOG_FSTRIM_FINISH 2756 - -#define FSTRIM_WAKELOCK "dofstrim" - -#define UNUSED __attribute__((unused)) - -/* From a would-be kernel header */ -#define FIDTRIM _IOWR('f', 128, struct fstrim_range) /* Deep discard trim */ - -static unsigned long long get_boot_time_ms(void) -{ - struct timespec t; - unsigned long long time_ms; - - t.tv_sec = 0; - t.tv_nsec = 0; - clock_gettime(CLOCK_BOOTTIME, &t); - time_ms = (t.tv_sec * 1000LL) + (t.tv_nsec / 1000000); - - return time_ms; -} - -static void *do_fstrim_filesystems(void *thread_arg) -{ - int i; - int fd; - int ret = 0; - struct fstrim_range range = { 0 }; - extern struct fstab *fstab; - int deep_trim = !!thread_arg; - struct fstab_rec *prev_rec = NULL; - - SLOGI("Starting fstrim work...\n"); - - /* Get a wakelock as this may take a while, and we don't want the - * device to sleep on us. - */ - acquire_wake_lock(PARTIAL_WAKE_LOCK, FSTRIM_WAKELOCK); - - /* Log the start time in the event log */ - LOG_EVENT_LONG(LOG_FSTRIM_START, get_boot_time_ms()); - - for (i = 0; i < fstab->num_entries; i++) { - /* Skip raw partitions */ - if (!strcmp(fstab->recs[i].fs_type, "emmc") || - !strcmp(fstab->recs[i].fs_type, "mtd")) { - continue; - } - /* Skip read-only filesystems */ - if (fstab->recs[i].flags & MS_RDONLY) { - continue; - } - if (fs_mgr_is_voldmanaged(&fstab->recs[i])) { - continue; /* Should we trim fat32 filesystems? */ - } - if (fs_mgr_is_notrim(&fstab->recs[i])) { - continue; - } - - /* Skip the multi-type partitions, which are required to be following each other. - * See fs_mgr.c's mount_with_alternatives(). - */ - if (prev_rec && !strcmp(prev_rec->mount_point, fstab->recs[i].mount_point)) { - continue; - } - - fd = open(fstab->recs[i].mount_point, O_RDONLY | O_DIRECTORY | O_CLOEXEC | O_NOFOLLOW); - if (fd < 0) { - SLOGE("Cannot open %s for FITRIM\n", fstab->recs[i].mount_point); - ret = -1; - continue; - } - - memset(&range, 0, sizeof(range)); - range.len = ULLONG_MAX; - SLOGI("Invoking %s ioctl on %s", deep_trim ? "FIDTRIM" : "FITRIM", fstab->recs[i].mount_point); - - ret = ioctl(fd, deep_trim ? FIDTRIM : FITRIM, &range); - if (ret) { - SLOGE("%s ioctl failed on %s (error %d/%s)", deep_trim ? "FIDTRIM" : "FITRIM", fstab->recs[i].mount_point, errno, strerror(errno)); - ret = -1; - } else { - SLOGI("Trimmed %llu bytes on %s\n", range.len, fstab->recs[i].mount_point); - } - close(fd); - prev_rec = &fstab->recs[i]; - } - - /* Log the finish time in the event log */ - LOG_EVENT_LONG(LOG_FSTRIM_FINISH, get_boot_time_ms()); - - SLOGI("Finished fstrim work.\n"); - - /* Release the wakelock that let us work */ - release_wake_lock(FSTRIM_WAKELOCK); - - return (void *)(uintptr_t)ret; -} - -int fstrim_filesystems(int deep_trim) -{ - pthread_t t; - int ret; - - /* Depending on the emmc chip and size, this can take upwards - * of a few minutes. If done in the same thread as the caller - * of this function, that would block vold from accepting any - * commands until the trim is finished. So start another thread - * to do the work, and return immediately. - * - * This function should not be called more than once per day, but - * even if it is called a second time before the first one finishes, - * the kernel will "do the right thing" and split the work between - * the two ioctls invoked in separate threads. - */ - ret = pthread_create(&t, NULL, do_fstrim_filesystems, (void *)(intptr_t)deep_trim); - if (ret) { - SLOGE("Cannot create thread to do fstrim"); - return ret; - } - - ret = pthread_detach(t); - if (ret) { - SLOGE("Cannot detach thread doing fstrim"); - return ret; - } - - return 0; -} diff --git a/fstrim.h b/fstrim.h deleted file mode 100644 index 185d998..0000000 --- a/fstrim.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifdef __cplusplus -extern "C" { -#endif - int fstrim_filesystems(int deep_trim); -#ifdef __cplusplus -} -#endif - diff --git a/main.cpp b/main.cpp index abdff9f..648f36a 100644 --- a/main.cpp +++ b/main.cpp @@ -208,25 +208,15 @@ static void coldboot(const char *path) { } static int process_config(VolumeManager *vm) { - bool has_adoptable = false; - char hardware[PROPERTY_VALUE_MAX]; - property_get("ro.hardware", hardware, ""); - std::string fstab_filename(StringPrintf("/fstab.%s", hardware)); - -#ifdef DEBUG_FSTAB - if (access(DEBUG_FSTAB, R_OK) == 0) { - LOG(DEBUG) << "Found debug fstab; switching!"; - fstab_filename = DEBUG_FSTAB; - } -#endif - - fstab = fs_mgr_read_fstab(fstab_filename.c_str()); + std::string path(android::vold::DefaultFstabPath()); + fstab = fs_mgr_read_fstab(path.c_str()); if (!fstab) { - PLOG(ERROR) << "Failed to open " << fstab_filename; + PLOG(ERROR) << "Failed to open default fstab " << path; return -1; } /* Loop through entries looking for ones that vold manages */ + bool has_adoptable = false; for (int i = 0; i < fstab->num_entries; i++) { if (fs_mgr_is_voldmanaged(&fstab->recs[i])) { if (fs_mgr_is_nonremovable(&fstab->recs[i])) {