1b87937cdea689594a293979b30b13054e7455deeKen Sumrall/* 2b87937cdea689594a293979b30b13054e7455deeKen Sumrall * Copyright (C) 2013 The Android Open Source Project 3b87937cdea689594a293979b30b13054e7455deeKen Sumrall * 4b87937cdea689594a293979b30b13054e7455deeKen Sumrall * Licensed under the Apache License, Version 2.0 (the "License"); 5b87937cdea689594a293979b30b13054e7455deeKen Sumrall * you may not use this file except in compliance with the License. 6b87937cdea689594a293979b30b13054e7455deeKen Sumrall * You may obtain a copy of the License at 7b87937cdea689594a293979b30b13054e7455deeKen Sumrall * 8b87937cdea689594a293979b30b13054e7455deeKen Sumrall * http://www.apache.org/licenses/LICENSE-2.0 9b87937cdea689594a293979b30b13054e7455deeKen Sumrall * 10b87937cdea689594a293979b30b13054e7455deeKen Sumrall * Unless required by applicable law or agreed to in writing, software 11b87937cdea689594a293979b30b13054e7455deeKen Sumrall * distributed under the License is distributed on an "AS IS" BASIS, 12b87937cdea689594a293979b30b13054e7455deeKen Sumrall * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b87937cdea689594a293979b30b13054e7455deeKen Sumrall * See the License for the specific language governing permissions and 14b87937cdea689594a293979b30b13054e7455deeKen Sumrall * limitations under the License. 15b87937cdea689594a293979b30b13054e7455deeKen Sumrall */ 16b87937cdea689594a293979b30b13054e7455deeKen Sumrall 17b87937cdea689594a293979b30b13054e7455deeKen Sumrall#include <sys/types.h> 18b87937cdea689594a293979b30b13054e7455deeKen Sumrall#include <sys/stat.h> 19b87937cdea689594a293979b30b13054e7455deeKen Sumrall#include <fcntl.h> 20b87937cdea689594a293979b30b13054e7455deeKen Sumrall#include <unistd.h> 21b87937cdea689594a293979b30b13054e7455deeKen Sumrall#include <sys/ioctl.h> 22b87937cdea689594a293979b30b13054e7455deeKen Sumrall#include <string.h> 23b87937cdea689594a293979b30b13054e7455deeKen Sumrall#include <limits.h> 24b87937cdea689594a293979b30b13054e7455deeKen Sumrall#include <linux/fs.h> 25bc7d5088f7f7cbd097f99d2f6d015e2c0a73cacbKen Sumrall#include <time.h> 26b87937cdea689594a293979b30b13054e7455deeKen Sumrall#include <fs_mgr.h> 27743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall#include <pthread.h> 28b87937cdea689594a293979b30b13054e7455deeKen Sumrall#define LOG_TAG "fstrim" 29b87937cdea689594a293979b30b13054e7455deeKen Sumrall#include "cutils/log.h" 30e78cd4f33d2b7969f1baca2b274740e1b53b3121Ken Sumrall#include "hardware_legacy/power.h" 31e78cd4f33d2b7969f1baca2b274740e1b53b3121Ken Sumrall 32bc7d5088f7f7cbd097f99d2f6d015e2c0a73cacbKen Sumrall/* These numbers must match what the MountService specified in 33bc7d5088f7f7cbd097f99d2f6d015e2c0a73cacbKen Sumrall * frameworks/base/services/java/com/android/server/EventLogTags.logtags 34bc7d5088f7f7cbd097f99d2f6d015e2c0a73cacbKen Sumrall */ 35bc7d5088f7f7cbd097f99d2f6d015e2c0a73cacbKen Sumrall#define LOG_FSTRIM_START 2755 36bc7d5088f7f7cbd097f99d2f6d015e2c0a73cacbKen Sumrall#define LOG_FSTRIM_FINISH 2756 37bc7d5088f7f7cbd097f99d2f6d015e2c0a73cacbKen Sumrall 38e78cd4f33d2b7969f1baca2b274740e1b53b3121Ken Sumrall#define FSTRIM_WAKELOCK "dofstrim" 39b87937cdea689594a293979b30b13054e7455deeKen Sumrall 403e971277db0d87652af5622c989233e7159ab909Mark Salyzyn#define UNUSED __attribute__((unused)) 413e971277db0d87652af5622c989233e7159ab909Mark Salyzyn 420cd6cfcf3a833153ae420946a1937574dec7fcccJP Abgrall/* From a would-be kernel header */ 430cd6cfcf3a833153ae420946a1937574dec7fcccJP Abgrall#define FIDTRIM _IOWR('f', 128, struct fstrim_range) /* Deep discard trim */ 440cd6cfcf3a833153ae420946a1937574dec7fcccJP Abgrall 45bc7d5088f7f7cbd097f99d2f6d015e2c0a73cacbKen Sumrallstatic unsigned long long get_boot_time_ms(void) 46bc7d5088f7f7cbd097f99d2f6d015e2c0a73cacbKen Sumrall{ 47bc7d5088f7f7cbd097f99d2f6d015e2c0a73cacbKen Sumrall struct timespec t; 48bc7d5088f7f7cbd097f99d2f6d015e2c0a73cacbKen Sumrall unsigned long long time_ms; 49bc7d5088f7f7cbd097f99d2f6d015e2c0a73cacbKen Sumrall 50bc7d5088f7f7cbd097f99d2f6d015e2c0a73cacbKen Sumrall t.tv_sec = 0; 51bc7d5088f7f7cbd097f99d2f6d015e2c0a73cacbKen Sumrall t.tv_nsec = 0; 52bc7d5088f7f7cbd097f99d2f6d015e2c0a73cacbKen Sumrall clock_gettime(CLOCK_BOOTTIME, &t); 53bc7d5088f7f7cbd097f99d2f6d015e2c0a73cacbKen Sumrall time_ms = (t.tv_sec * 1000LL) + (t.tv_nsec / 1000000); 54bc7d5088f7f7cbd097f99d2f6d015e2c0a73cacbKen Sumrall 55bc7d5088f7f7cbd097f99d2f6d015e2c0a73cacbKen Sumrall return time_ms; 56bc7d5088f7f7cbd097f99d2f6d015e2c0a73cacbKen Sumrall} 57bc7d5088f7f7cbd097f99d2f6d015e2c0a73cacbKen Sumrall 58422bdb7e49b39475328f05d765b00f0ef96820b8JP Abgrallstatic void *do_fstrim_filesystems(void *thread_arg) 59b87937cdea689594a293979b30b13054e7455deeKen Sumrall{ 60b87937cdea689594a293979b30b13054e7455deeKen Sumrall int i; 61b87937cdea689594a293979b30b13054e7455deeKen Sumrall int fd; 62b87937cdea689594a293979b30b13054e7455deeKen Sumrall int ret = 0; 63b87937cdea689594a293979b30b13054e7455deeKen Sumrall struct fstrim_range range = { 0 }; 64b87937cdea689594a293979b30b13054e7455deeKen Sumrall struct stat sb; 65b87937cdea689594a293979b30b13054e7455deeKen Sumrall extern struct fstab *fstab; 66422bdb7e49b39475328f05d765b00f0ef96820b8JP Abgrall int deep_trim = !!thread_arg; 67b87937cdea689594a293979b30b13054e7455deeKen Sumrall 68b87937cdea689594a293979b30b13054e7455deeKen Sumrall SLOGI("Starting fstrim work...\n"); 69b87937cdea689594a293979b30b13054e7455deeKen Sumrall 70bc7d5088f7f7cbd097f99d2f6d015e2c0a73cacbKen Sumrall /* Log the start time in the event log */ 71bc7d5088f7f7cbd097f99d2f6d015e2c0a73cacbKen Sumrall LOG_EVENT_LONG(LOG_FSTRIM_START, get_boot_time_ms()); 72bc7d5088f7f7cbd097f99d2f6d015e2c0a73cacbKen Sumrall 73b87937cdea689594a293979b30b13054e7455deeKen Sumrall for (i = 0; i < fstab->num_entries; i++) { 74b87937cdea689594a293979b30b13054e7455deeKen Sumrall /* Skip raw partitions */ 75b87937cdea689594a293979b30b13054e7455deeKen Sumrall if (!strcmp(fstab->recs[i].fs_type, "emmc") || 76b87937cdea689594a293979b30b13054e7455deeKen Sumrall !strcmp(fstab->recs[i].fs_type, "mtd")) { 77b87937cdea689594a293979b30b13054e7455deeKen Sumrall continue; 78b87937cdea689594a293979b30b13054e7455deeKen Sumrall } 79b87937cdea689594a293979b30b13054e7455deeKen Sumrall /* Skip read-only filesystems */ 80b87937cdea689594a293979b30b13054e7455deeKen Sumrall if (fstab->recs[i].flags & MS_RDONLY) { 81b87937cdea689594a293979b30b13054e7455deeKen Sumrall continue; 82b87937cdea689594a293979b30b13054e7455deeKen Sumrall } 83b87937cdea689594a293979b30b13054e7455deeKen Sumrall if (fs_mgr_is_voldmanaged(&fstab->recs[i])) { 84b87937cdea689594a293979b30b13054e7455deeKen Sumrall continue; /* Should we trim fat32 filesystems? */ 85b87937cdea689594a293979b30b13054e7455deeKen Sumrall } 86b87937cdea689594a293979b30b13054e7455deeKen Sumrall 87b87937cdea689594a293979b30b13054e7455deeKen Sumrall if (stat(fstab->recs[i].mount_point, &sb) == -1) { 88b87937cdea689594a293979b30b13054e7455deeKen Sumrall SLOGE("Cannot stat mount point %s\n", fstab->recs[i].mount_point); 89b87937cdea689594a293979b30b13054e7455deeKen Sumrall ret = -1; 90b87937cdea689594a293979b30b13054e7455deeKen Sumrall continue; 91b87937cdea689594a293979b30b13054e7455deeKen Sumrall } 92b87937cdea689594a293979b30b13054e7455deeKen Sumrall if (!S_ISDIR(sb.st_mode)) { 93b87937cdea689594a293979b30b13054e7455deeKen Sumrall SLOGE("%s is not a directory\n", fstab->recs[i].mount_point); 94b87937cdea689594a293979b30b13054e7455deeKen Sumrall ret = -1; 95b87937cdea689594a293979b30b13054e7455deeKen Sumrall continue; 96b87937cdea689594a293979b30b13054e7455deeKen Sumrall } 97b87937cdea689594a293979b30b13054e7455deeKen Sumrall 98b87937cdea689594a293979b30b13054e7455deeKen Sumrall fd = open(fstab->recs[i].mount_point, O_RDONLY); 99b87937cdea689594a293979b30b13054e7455deeKen Sumrall if (fd < 0) { 100b87937cdea689594a293979b30b13054e7455deeKen Sumrall SLOGE("Cannot open %s for FITRIM\n", fstab->recs[i].mount_point); 101b87937cdea689594a293979b30b13054e7455deeKen Sumrall ret = -1; 102b87937cdea689594a293979b30b13054e7455deeKen Sumrall continue; 103b87937cdea689594a293979b30b13054e7455deeKen Sumrall } 104b87937cdea689594a293979b30b13054e7455deeKen Sumrall 105b87937cdea689594a293979b30b13054e7455deeKen Sumrall memset(&range, 0, sizeof(range)); 106b87937cdea689594a293979b30b13054e7455deeKen Sumrall range.len = ULLONG_MAX; 107422bdb7e49b39475328f05d765b00f0ef96820b8JP Abgrall SLOGI("Invoking %s ioctl on %s", deep_trim ? "FIDTRIM" : "FITRIM", fstab->recs[i].mount_point); 1080cd6cfcf3a833153ae420946a1937574dec7fcccJP Abgrall 109422bdb7e49b39475328f05d765b00f0ef96820b8JP Abgrall ret = ioctl(fd, deep_trim ? FIDTRIM : FITRIM, &range); 110422bdb7e49b39475328f05d765b00f0ef96820b8JP Abgrall if (ret) { 11155cdafdf2761733a8d12d9006754a08c8ee6209fJP Abgrall SLOGE("%s ioctl failed on %s (error %d/%s)", deep_trim ? "FIDTRIM" : "FITRIM", fstab->recs[i].mount_point, errno, strerror(errno)); 112b87937cdea689594a293979b30b13054e7455deeKen Sumrall ret = -1; 1132c4b563b3dc2c5ea0a9e98fab54fee5f55a1a9f7Ken Sumrall } else { 1142c4b563b3dc2c5ea0a9e98fab54fee5f55a1a9f7Ken Sumrall SLOGI("Trimmed %llu bytes on %s\n", range.len, fstab->recs[i].mount_point); 115b87937cdea689594a293979b30b13054e7455deeKen Sumrall } 116b87937cdea689594a293979b30b13054e7455deeKen Sumrall close(fd); 117b87937cdea689594a293979b30b13054e7455deeKen Sumrall } 118bc7d5088f7f7cbd097f99d2f6d015e2c0a73cacbKen Sumrall 119bc7d5088f7f7cbd097f99d2f6d015e2c0a73cacbKen Sumrall /* Log the finish time in the event log */ 120bc7d5088f7f7cbd097f99d2f6d015e2c0a73cacbKen Sumrall LOG_EVENT_LONG(LOG_FSTRIM_FINISH, get_boot_time_ms()); 121bc7d5088f7f7cbd097f99d2f6d015e2c0a73cacbKen Sumrall 122b87937cdea689594a293979b30b13054e7455deeKen Sumrall SLOGI("Finished fstrim work.\n"); 123b87937cdea689594a293979b30b13054e7455deeKen Sumrall 124e78cd4f33d2b7969f1baca2b274740e1b53b3121Ken Sumrall /* Release the wakelock that let us work */ 125e78cd4f33d2b7969f1baca2b274740e1b53b3121Ken Sumrall release_wake_lock(FSTRIM_WAKELOCK); 126e78cd4f33d2b7969f1baca2b274740e1b53b3121Ken Sumrall 127346c5b20cbbced7edacf240015c4a89e5b2ca44fColin Cross return (void *)(uintptr_t)ret; 128b87937cdea689594a293979b30b13054e7455deeKen Sumrall} 129b87937cdea689594a293979b30b13054e7455deeKen Sumrall 130422bdb7e49b39475328f05d765b00f0ef96820b8JP Abgrallint fstrim_filesystems(int deep_trim) 131743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall{ 132743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall pthread_t t; 133743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall int ret; 134743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall 135e78cd4f33d2b7969f1baca2b274740e1b53b3121Ken Sumrall /* Get a wakelock as this may take a while, and we don't want the 136e78cd4f33d2b7969f1baca2b274740e1b53b3121Ken Sumrall * device to sleep on us. 137e78cd4f33d2b7969f1baca2b274740e1b53b3121Ken Sumrall */ 138e78cd4f33d2b7969f1baca2b274740e1b53b3121Ken Sumrall acquire_wake_lock(PARTIAL_WAKE_LOCK, FSTRIM_WAKELOCK); 139e78cd4f33d2b7969f1baca2b274740e1b53b3121Ken Sumrall 140743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall /* Depending on the emmc chip and size, this can take upwards 141743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall * of a few minutes. If done in the same thread as the caller 142743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall * of this function, that would block vold from accepting any 143743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall * commands until the trim is finished. So start another thread 144743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall * to do the work, and return immediately. 145743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall * 146743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall * This function should not be called more than once per day, but 147743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall * even if it is called a second time before the first one finishes, 148743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall * the kernel will "do the right thing" and split the work between 149743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall * the two ioctls invoked in separate threads. 150743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall */ 151422bdb7e49b39475328f05d765b00f0ef96820b8JP Abgrall ret = pthread_create(&t, NULL, do_fstrim_filesystems, (void *)(intptr_t)deep_trim); 152743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall if (ret) { 153743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall SLOGE("Cannot create thread to do fstrim"); 154743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall return ret; 155743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall } 156743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall 157743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall ret = pthread_detach(t); 158743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall if (ret) { 159743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall SLOGE("Cannot detach thread doing fstrim"); 160743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall return ret; 161743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall } 162743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall 163743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall return 0; 164743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall} 165