1c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey/* 2c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey * Copyright (C) 2015 The Android Open Source Project 3c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey * 4c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License"); 5c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey * you may not use this file except in compliance with the License. 6c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey * You may obtain a copy of the License at 7c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey * 8c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey * http://www.apache.org/licenses/LICENSE-2.0 9c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey * 10c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey * Unless required by applicable law or agreed to in writing, software 11c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS, 12c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey * See the License for the specific language governing permissions and 14c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey * limitations under the License. 15c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey */ 16c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey 17c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey#include "TrimTask.h" 18c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey#include "Benchmark.h" 19c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey#include "Utils.h" 20c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey#include "VolumeManager.h" 21c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey#include "ResponseCode.h" 22c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey 237e128fbe212c64492afa98bfd6d7fab6f1956831Elliott Hughes#include <android-base/stringprintf.h> 247e128fbe212c64492afa98bfd6d7fab6f1956831Elliott Hughes#include <android-base/logging.h> 25c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey#include <cutils/properties.h> 26c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey#include <fs_mgr.h> 27c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey#include <private/android_filesystem_config.h> 28c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey#include <hardware_legacy/power.h> 29c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey 30c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey#include <dirent.h> 31c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey#include <sys/mount.h> 32c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey#include <sys/stat.h> 33c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey#include <sys/types.h> 34c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey#include <sys/wait.h> 35c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey#include <fcntl.h> 36c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey 37c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey/* From a would-be kernel header */ 38c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey#define FIDTRIM _IOWR('f', 128, struct fstrim_range) /* Deep discard trim */ 39c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey 401a20a6487faad2869eaec962e4373402aa7461b3Jeff Sharkey#define BENCHMARK_ENABLED 1 41c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey 42c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkeyusing android::base::StringPrintf; 43c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey 44c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkeynamespace android { 45c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkeynamespace vold { 46c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey 47c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkeystatic const char* kWakeLock = "TrimTask"; 48c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey 49c86ab6f538bec63638c168d6c843fe7cf73add3bJeff SharkeyTrimTask::TrimTask(int flags) : mFlags(flags) { 50c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey // Collect both fstab and vold volumes 51c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey addFromFstab(); 52c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey 53c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey VolumeManager* vm = VolumeManager::Instance(); 54c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey std::list<std::string> privateIds; 55c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey vm->listVolumes(VolumeBase::Type::kPrivate, privateIds); 56c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey for (auto id : privateIds) { 57c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey auto vol = vm->findVolume(id); 58c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey if (vol != nullptr && vol->getState() == VolumeBase::State::kMounted) { 59c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey mPaths.push_back(vol->getPath()); 60c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey } 61c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey } 62c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey} 63c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey 64c86ab6f538bec63638c168d6c843fe7cf73add3bJeff SharkeyTrimTask::~TrimTask() { 65c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey} 66c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey 67c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkeyvoid TrimTask::addFromFstab() { 68c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey struct fstab *fstab; 69c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey struct fstab_rec *prev_rec = NULL; 70c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey 71c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey fstab = fs_mgr_read_fstab(android::vold::DefaultFstabPath().c_str()); 72c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey for (int i = 0; i < fstab->num_entries; i++) { 73c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey /* Skip raw partitions */ 74c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey if (!strcmp(fstab->recs[i].fs_type, "emmc") || 75c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey !strcmp(fstab->recs[i].fs_type, "mtd")) { 76c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey continue; 77c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey } 78c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey /* Skip read-only filesystems */ 79c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey if (fstab->recs[i].flags & MS_RDONLY) { 80c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey continue; 81c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey } 82c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey if (fs_mgr_is_voldmanaged(&fstab->recs[i])) { 83c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey continue; /* Should we trim fat32 filesystems? */ 84c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey } 85c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey if (fs_mgr_is_notrim(&fstab->recs[i])) { 86c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey continue; 87c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey } 88c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey 89c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey /* Skip the multi-type partitions, which are required to be following each other. 90c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey * See fs_mgr.c's mount_with_alternatives(). 91c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey */ 92c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey if (prev_rec && !strcmp(prev_rec->mount_point, fstab->recs[i].mount_point)) { 93c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey continue; 94c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey } 95c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey 96c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey mPaths.push_back(fstab->recs[i].mount_point); 97c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey prev_rec = &fstab->recs[i]; 98c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey } 99c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey fs_mgr_free_fstab(fstab); 100c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey} 101c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey 102c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkeyvoid TrimTask::start() { 103c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey mThread = std::thread(&TrimTask::run, this); 104c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey} 105c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey 106c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkeystatic void notifyResult(const std::string& path, int64_t bytes, int64_t delta) { 107c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey std::string res(path 108c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey + " " + std::to_string(bytes) 109c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey + " " + std::to_string(delta)); 110c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey VolumeManager::Instance()->getBroadcaster()->sendBroadcast( 111c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey ResponseCode::TrimResult, res.c_str(), false); 112c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey} 113c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey 114c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkeyvoid TrimTask::run() { 115c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey acquire_wake_lock(PARTIAL_WAKE_LOCK, kWakeLock); 116c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey 117c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey for (auto path : mPaths) { 118c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey LOG(DEBUG) << "Starting trim of " << path; 119c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey 120c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey int fd = open(path.c_str(), O_RDONLY | O_DIRECTORY | O_CLOEXEC | O_NOFOLLOW); 121c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey if (fd < 0) { 122c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey PLOG(WARNING) << "Failed to open " << path; 123c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey continue; 124c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey } 125c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey 126c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey struct fstrim_range range; 127c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey memset(&range, 0, sizeof(range)); 128c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey range.len = ULLONG_MAX; 129c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey 130c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey nsecs_t start = systemTime(SYSTEM_TIME_BOOTTIME); 131c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey if (ioctl(fd, (mFlags & Flags::kDeepTrim) ? FIDTRIM : FITRIM, &range)) { 132c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey PLOG(WARNING) << "Trim failed on " << path; 133c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey notifyResult(path, -1, -1); 134c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey } else { 135c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey nsecs_t delta = systemTime(SYSTEM_TIME_BOOTTIME) - start; 136c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey LOG(INFO) << "Trimmed " << range.len << " bytes on " << path 137c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey << " in " << nanoseconds_to_milliseconds(delta) << "ms"; 138c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey notifyResult(path, range.len, delta); 139c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey } 140c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey close(fd); 141c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey 142c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey if (mFlags & Flags::kBenchmarkAfter) { 143c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey#if BENCHMARK_ENABLED 144c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey BenchmarkPrivate(path); 145c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey#else 146c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey LOG(DEBUG) << "Benchmark disabled"; 147c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey#endif 148c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey } 149c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey } 150c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey 151c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey release_wake_lock(kWakeLock); 152c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey} 153c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey 154c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey} // namespace vold 155c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey} // namespace android 156