fstrim.c revision e78cd4f33d2b7969f1baca2b274740e1b53b3121
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> 25b87937cdea689594a293979b30b13054e7455deeKen Sumrall#include <fs_mgr.h> 26743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall#include <pthread.h> 27b87937cdea689594a293979b30b13054e7455deeKen Sumrall#define LOG_TAG "fstrim" 28b87937cdea689594a293979b30b13054e7455deeKen Sumrall#include "cutils/log.h" 29e78cd4f33d2b7969f1baca2b274740e1b53b3121Ken Sumrall#include "hardware_legacy/power.h" 30e78cd4f33d2b7969f1baca2b274740e1b53b3121Ken Sumrall 31e78cd4f33d2b7969f1baca2b274740e1b53b3121Ken Sumrall#define FSTRIM_WAKELOCK "dofstrim" 32b87937cdea689594a293979b30b13054e7455deeKen Sumrall 33743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrallstatic void *do_fstrim_filesystems(void *ignored) 34b87937cdea689594a293979b30b13054e7455deeKen Sumrall{ 35b87937cdea689594a293979b30b13054e7455deeKen Sumrall int i; 36b87937cdea689594a293979b30b13054e7455deeKen Sumrall int fd; 37b87937cdea689594a293979b30b13054e7455deeKen Sumrall int ret = 0; 38b87937cdea689594a293979b30b13054e7455deeKen Sumrall struct fstrim_range range = { 0 }; 39b87937cdea689594a293979b30b13054e7455deeKen Sumrall struct stat sb; 40b87937cdea689594a293979b30b13054e7455deeKen Sumrall extern struct fstab *fstab; 41b87937cdea689594a293979b30b13054e7455deeKen Sumrall 42b87937cdea689594a293979b30b13054e7455deeKen Sumrall SLOGI("Starting fstrim work...\n"); 43b87937cdea689594a293979b30b13054e7455deeKen Sumrall 44b87937cdea689594a293979b30b13054e7455deeKen Sumrall for (i = 0; i < fstab->num_entries; i++) { 45b87937cdea689594a293979b30b13054e7455deeKen Sumrall /* Skip raw partitions */ 46b87937cdea689594a293979b30b13054e7455deeKen Sumrall if (!strcmp(fstab->recs[i].fs_type, "emmc") || 47b87937cdea689594a293979b30b13054e7455deeKen Sumrall !strcmp(fstab->recs[i].fs_type, "mtd")) { 48b87937cdea689594a293979b30b13054e7455deeKen Sumrall continue; 49b87937cdea689594a293979b30b13054e7455deeKen Sumrall } 50b87937cdea689594a293979b30b13054e7455deeKen Sumrall /* Skip read-only filesystems */ 51b87937cdea689594a293979b30b13054e7455deeKen Sumrall if (fstab->recs[i].flags & MS_RDONLY) { 52b87937cdea689594a293979b30b13054e7455deeKen Sumrall continue; 53b87937cdea689594a293979b30b13054e7455deeKen Sumrall } 54b87937cdea689594a293979b30b13054e7455deeKen Sumrall if (fs_mgr_is_voldmanaged(&fstab->recs[i])) { 55b87937cdea689594a293979b30b13054e7455deeKen Sumrall continue; /* Should we trim fat32 filesystems? */ 56b87937cdea689594a293979b30b13054e7455deeKen Sumrall } 57b87937cdea689594a293979b30b13054e7455deeKen Sumrall 58b87937cdea689594a293979b30b13054e7455deeKen Sumrall if (stat(fstab->recs[i].mount_point, &sb) == -1) { 59b87937cdea689594a293979b30b13054e7455deeKen Sumrall SLOGE("Cannot stat mount point %s\n", fstab->recs[i].mount_point); 60b87937cdea689594a293979b30b13054e7455deeKen Sumrall ret = -1; 61b87937cdea689594a293979b30b13054e7455deeKen Sumrall continue; 62b87937cdea689594a293979b30b13054e7455deeKen Sumrall } 63b87937cdea689594a293979b30b13054e7455deeKen Sumrall if (!S_ISDIR(sb.st_mode)) { 64b87937cdea689594a293979b30b13054e7455deeKen Sumrall SLOGE("%s is not a directory\n", fstab->recs[i].mount_point); 65b87937cdea689594a293979b30b13054e7455deeKen Sumrall ret = -1; 66b87937cdea689594a293979b30b13054e7455deeKen Sumrall continue; 67b87937cdea689594a293979b30b13054e7455deeKen Sumrall } 68b87937cdea689594a293979b30b13054e7455deeKen Sumrall 69b87937cdea689594a293979b30b13054e7455deeKen Sumrall fd = open(fstab->recs[i].mount_point, O_RDONLY); 70b87937cdea689594a293979b30b13054e7455deeKen Sumrall if (fd < 0) { 71b87937cdea689594a293979b30b13054e7455deeKen Sumrall SLOGE("Cannot open %s for FITRIM\n", fstab->recs[i].mount_point); 72b87937cdea689594a293979b30b13054e7455deeKen Sumrall ret = -1; 73b87937cdea689594a293979b30b13054e7455deeKen Sumrall continue; 74b87937cdea689594a293979b30b13054e7455deeKen Sumrall } 75b87937cdea689594a293979b30b13054e7455deeKen Sumrall 76b87937cdea689594a293979b30b13054e7455deeKen Sumrall memset(&range, 0, sizeof(range)); 77b87937cdea689594a293979b30b13054e7455deeKen Sumrall range.len = ULLONG_MAX; 78b87937cdea689594a293979b30b13054e7455deeKen Sumrall SLOGI("Invoking FITRIM ioctl on %s", fstab->recs[i].mount_point); 79b87937cdea689594a293979b30b13054e7455deeKen Sumrall if (ioctl(fd, FITRIM, &range)) { 80b87937cdea689594a293979b30b13054e7455deeKen Sumrall SLOGE("FITRIM ioctl failed on %s", fstab->recs[i].mount_point); 81b87937cdea689594a293979b30b13054e7455deeKen Sumrall ret = -1; 82b87937cdea689594a293979b30b13054e7455deeKen Sumrall } 83b87937cdea689594a293979b30b13054e7455deeKen Sumrall SLOGI("Trimmed %llu bytes on %s\n", range.len, fstab->recs[i].mount_point); 84b87937cdea689594a293979b30b13054e7455deeKen Sumrall close(fd); 85b87937cdea689594a293979b30b13054e7455deeKen Sumrall } 86b87937cdea689594a293979b30b13054e7455deeKen Sumrall SLOGI("Finished fstrim work.\n"); 87b87937cdea689594a293979b30b13054e7455deeKen Sumrall 88e78cd4f33d2b7969f1baca2b274740e1b53b3121Ken Sumrall /* Release the wakelock that let us work */ 89e78cd4f33d2b7969f1baca2b274740e1b53b3121Ken Sumrall release_wake_lock(FSTRIM_WAKELOCK); 90e78cd4f33d2b7969f1baca2b274740e1b53b3121Ken Sumrall 91743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall return (void *)ret; 92b87937cdea689594a293979b30b13054e7455deeKen Sumrall} 93b87937cdea689594a293979b30b13054e7455deeKen Sumrall 94743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrallint fstrim_filesystems(void) 95743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall{ 96743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall pthread_t t; 97743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall int ret; 98743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall 99e78cd4f33d2b7969f1baca2b274740e1b53b3121Ken Sumrall /* Get a wakelock as this may take a while, and we don't want the 100e78cd4f33d2b7969f1baca2b274740e1b53b3121Ken Sumrall * device to sleep on us. 101e78cd4f33d2b7969f1baca2b274740e1b53b3121Ken Sumrall */ 102e78cd4f33d2b7969f1baca2b274740e1b53b3121Ken Sumrall acquire_wake_lock(PARTIAL_WAKE_LOCK, FSTRIM_WAKELOCK); 103e78cd4f33d2b7969f1baca2b274740e1b53b3121Ken Sumrall 104743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall /* Depending on the emmc chip and size, this can take upwards 105743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall * of a few minutes. If done in the same thread as the caller 106743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall * of this function, that would block vold from accepting any 107743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall * commands until the trim is finished. So start another thread 108743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall * to do the work, and return immediately. 109743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall * 110743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall * This function should not be called more than once per day, but 111743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall * even if it is called a second time before the first one finishes, 112743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall * the kernel will "do the right thing" and split the work between 113743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall * the two ioctls invoked in separate threads. 114743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall */ 115743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall ret = pthread_create(&t, NULL, do_fstrim_filesystems, NULL); 116743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall if (ret) { 117743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall SLOGE("Cannot create thread to do fstrim"); 118743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall return ret; 119743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall } 120743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall 121743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall ret = pthread_detach(t); 122743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall if (ret) { 123743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall SLOGE("Cannot detach thread doing fstrim"); 124743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall return ret; 125743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall } 126743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall 127743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall return 0; 128743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall} 129