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 40bc7d5088f7f7cbd097f99d2f6d015e2c0a73cacbKen Sumrallstatic unsigned long long get_boot_time_ms(void) 41bc7d5088f7f7cbd097f99d2f6d015e2c0a73cacbKen Sumrall{ 42bc7d5088f7f7cbd097f99d2f6d015e2c0a73cacbKen Sumrall struct timespec t; 43bc7d5088f7f7cbd097f99d2f6d015e2c0a73cacbKen Sumrall unsigned long long time_ms; 44bc7d5088f7f7cbd097f99d2f6d015e2c0a73cacbKen Sumrall 45bc7d5088f7f7cbd097f99d2f6d015e2c0a73cacbKen Sumrall t.tv_sec = 0; 46bc7d5088f7f7cbd097f99d2f6d015e2c0a73cacbKen Sumrall t.tv_nsec = 0; 47bc7d5088f7f7cbd097f99d2f6d015e2c0a73cacbKen Sumrall clock_gettime(CLOCK_BOOTTIME, &t); 48bc7d5088f7f7cbd097f99d2f6d015e2c0a73cacbKen Sumrall time_ms = (t.tv_sec * 1000LL) + (t.tv_nsec / 1000000); 49bc7d5088f7f7cbd097f99d2f6d015e2c0a73cacbKen Sumrall 50bc7d5088f7f7cbd097f99d2f6d015e2c0a73cacbKen Sumrall return time_ms; 51bc7d5088f7f7cbd097f99d2f6d015e2c0a73cacbKen Sumrall} 52bc7d5088f7f7cbd097f99d2f6d015e2c0a73cacbKen Sumrall 53743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrallstatic void *do_fstrim_filesystems(void *ignored) 54b87937cdea689594a293979b30b13054e7455deeKen Sumrall{ 55b87937cdea689594a293979b30b13054e7455deeKen Sumrall int i; 56b87937cdea689594a293979b30b13054e7455deeKen Sumrall int fd; 57b87937cdea689594a293979b30b13054e7455deeKen Sumrall int ret = 0; 58b87937cdea689594a293979b30b13054e7455deeKen Sumrall struct fstrim_range range = { 0 }; 59b87937cdea689594a293979b30b13054e7455deeKen Sumrall struct stat sb; 60b87937cdea689594a293979b30b13054e7455deeKen Sumrall extern struct fstab *fstab; 61b87937cdea689594a293979b30b13054e7455deeKen Sumrall 62b87937cdea689594a293979b30b13054e7455deeKen Sumrall SLOGI("Starting fstrim work...\n"); 63b87937cdea689594a293979b30b13054e7455deeKen Sumrall 64bc7d5088f7f7cbd097f99d2f6d015e2c0a73cacbKen Sumrall /* Log the start time in the event log */ 65bc7d5088f7f7cbd097f99d2f6d015e2c0a73cacbKen Sumrall LOG_EVENT_LONG(LOG_FSTRIM_START, get_boot_time_ms()); 66bc7d5088f7f7cbd097f99d2f6d015e2c0a73cacbKen Sumrall 67b87937cdea689594a293979b30b13054e7455deeKen Sumrall for (i = 0; i < fstab->num_entries; i++) { 68b87937cdea689594a293979b30b13054e7455deeKen Sumrall /* Skip raw partitions */ 69b87937cdea689594a293979b30b13054e7455deeKen Sumrall if (!strcmp(fstab->recs[i].fs_type, "emmc") || 70b87937cdea689594a293979b30b13054e7455deeKen Sumrall !strcmp(fstab->recs[i].fs_type, "mtd")) { 71b87937cdea689594a293979b30b13054e7455deeKen Sumrall continue; 72b87937cdea689594a293979b30b13054e7455deeKen Sumrall } 73b87937cdea689594a293979b30b13054e7455deeKen Sumrall /* Skip read-only filesystems */ 74b87937cdea689594a293979b30b13054e7455deeKen Sumrall if (fstab->recs[i].flags & MS_RDONLY) { 75b87937cdea689594a293979b30b13054e7455deeKen Sumrall continue; 76b87937cdea689594a293979b30b13054e7455deeKen Sumrall } 77b87937cdea689594a293979b30b13054e7455deeKen Sumrall if (fs_mgr_is_voldmanaged(&fstab->recs[i])) { 78b87937cdea689594a293979b30b13054e7455deeKen Sumrall continue; /* Should we trim fat32 filesystems? */ 79b87937cdea689594a293979b30b13054e7455deeKen Sumrall } 80b87937cdea689594a293979b30b13054e7455deeKen Sumrall 81b87937cdea689594a293979b30b13054e7455deeKen Sumrall if (stat(fstab->recs[i].mount_point, &sb) == -1) { 82b87937cdea689594a293979b30b13054e7455deeKen Sumrall SLOGE("Cannot stat mount point %s\n", fstab->recs[i].mount_point); 83b87937cdea689594a293979b30b13054e7455deeKen Sumrall ret = -1; 84b87937cdea689594a293979b30b13054e7455deeKen Sumrall continue; 85b87937cdea689594a293979b30b13054e7455deeKen Sumrall } 86b87937cdea689594a293979b30b13054e7455deeKen Sumrall if (!S_ISDIR(sb.st_mode)) { 87b87937cdea689594a293979b30b13054e7455deeKen Sumrall SLOGE("%s is not a directory\n", fstab->recs[i].mount_point); 88b87937cdea689594a293979b30b13054e7455deeKen Sumrall ret = -1; 89b87937cdea689594a293979b30b13054e7455deeKen Sumrall continue; 90b87937cdea689594a293979b30b13054e7455deeKen Sumrall } 91b87937cdea689594a293979b30b13054e7455deeKen Sumrall 92b87937cdea689594a293979b30b13054e7455deeKen Sumrall fd = open(fstab->recs[i].mount_point, O_RDONLY); 93b87937cdea689594a293979b30b13054e7455deeKen Sumrall if (fd < 0) { 94b87937cdea689594a293979b30b13054e7455deeKen Sumrall SLOGE("Cannot open %s for FITRIM\n", fstab->recs[i].mount_point); 95b87937cdea689594a293979b30b13054e7455deeKen Sumrall ret = -1; 96b87937cdea689594a293979b30b13054e7455deeKen Sumrall continue; 97b87937cdea689594a293979b30b13054e7455deeKen Sumrall } 98b87937cdea689594a293979b30b13054e7455deeKen Sumrall 99b87937cdea689594a293979b30b13054e7455deeKen Sumrall memset(&range, 0, sizeof(range)); 100b87937cdea689594a293979b30b13054e7455deeKen Sumrall range.len = ULLONG_MAX; 101b87937cdea689594a293979b30b13054e7455deeKen Sumrall SLOGI("Invoking FITRIM ioctl on %s", fstab->recs[i].mount_point); 102b87937cdea689594a293979b30b13054e7455deeKen Sumrall if (ioctl(fd, FITRIM, &range)) { 103b87937cdea689594a293979b30b13054e7455deeKen Sumrall SLOGE("FITRIM ioctl failed on %s", fstab->recs[i].mount_point); 104b87937cdea689594a293979b30b13054e7455deeKen Sumrall ret = -1; 1052c4b563b3dc2c5ea0a9e98fab54fee5f55a1a9f7Ken Sumrall } else { 1062c4b563b3dc2c5ea0a9e98fab54fee5f55a1a9f7Ken Sumrall SLOGI("Trimmed %llu bytes on %s\n", range.len, fstab->recs[i].mount_point); 107b87937cdea689594a293979b30b13054e7455deeKen Sumrall } 108b87937cdea689594a293979b30b13054e7455deeKen Sumrall close(fd); 109b87937cdea689594a293979b30b13054e7455deeKen Sumrall } 110bc7d5088f7f7cbd097f99d2f6d015e2c0a73cacbKen Sumrall 111bc7d5088f7f7cbd097f99d2f6d015e2c0a73cacbKen Sumrall /* Log the finish time in the event log */ 112bc7d5088f7f7cbd097f99d2f6d015e2c0a73cacbKen Sumrall LOG_EVENT_LONG(LOG_FSTRIM_FINISH, get_boot_time_ms()); 113bc7d5088f7f7cbd097f99d2f6d015e2c0a73cacbKen Sumrall 114b87937cdea689594a293979b30b13054e7455deeKen Sumrall SLOGI("Finished fstrim work.\n"); 115b87937cdea689594a293979b30b13054e7455deeKen Sumrall 116e78cd4f33d2b7969f1baca2b274740e1b53b3121Ken Sumrall /* Release the wakelock that let us work */ 117e78cd4f33d2b7969f1baca2b274740e1b53b3121Ken Sumrall release_wake_lock(FSTRIM_WAKELOCK); 118e78cd4f33d2b7969f1baca2b274740e1b53b3121Ken Sumrall 119743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall return (void *)ret; 120b87937cdea689594a293979b30b13054e7455deeKen Sumrall} 121b87937cdea689594a293979b30b13054e7455deeKen Sumrall 122743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrallint fstrim_filesystems(void) 123743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall{ 124743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall pthread_t t; 125743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall int ret; 126743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall 127e78cd4f33d2b7969f1baca2b274740e1b53b3121Ken Sumrall /* Get a wakelock as this may take a while, and we don't want the 128e78cd4f33d2b7969f1baca2b274740e1b53b3121Ken Sumrall * device to sleep on us. 129e78cd4f33d2b7969f1baca2b274740e1b53b3121Ken Sumrall */ 130e78cd4f33d2b7969f1baca2b274740e1b53b3121Ken Sumrall acquire_wake_lock(PARTIAL_WAKE_LOCK, FSTRIM_WAKELOCK); 131e78cd4f33d2b7969f1baca2b274740e1b53b3121Ken Sumrall 132743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall /* Depending on the emmc chip and size, this can take upwards 133743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall * of a few minutes. If done in the same thread as the caller 134743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall * of this function, that would block vold from accepting any 135743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall * commands until the trim is finished. So start another thread 136743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall * to do the work, and return immediately. 137743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall * 138743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall * This function should not be called more than once per day, but 139743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall * even if it is called a second time before the first one finishes, 140743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall * the kernel will "do the right thing" and split the work between 141743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall * the two ioctls invoked in separate threads. 142743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall */ 143743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall ret = pthread_create(&t, NULL, do_fstrim_filesystems, NULL); 144743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall if (ret) { 145743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall SLOGE("Cannot create thread to do fstrim"); 146743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall return ret; 147743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall } 148743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall 149743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall ret = pthread_detach(t); 150743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall if (ret) { 151743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall SLOGE("Cannot detach thread doing fstrim"); 152743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall return ret; 153743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall } 154743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall 155743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall return 0; 156743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall} 157