fstrim.c revision 2c4b563b3dc2c5ea0a9e98fab54fee5f55a1a9f7
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" 29b87937cdea689594a293979b30b13054e7455deeKen Sumrall 30743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrallstatic void *do_fstrim_filesystems(void *ignored) 31b87937cdea689594a293979b30b13054e7455deeKen Sumrall{ 32b87937cdea689594a293979b30b13054e7455deeKen Sumrall int i; 33b87937cdea689594a293979b30b13054e7455deeKen Sumrall int fd; 34b87937cdea689594a293979b30b13054e7455deeKen Sumrall int ret = 0; 35b87937cdea689594a293979b30b13054e7455deeKen Sumrall struct fstrim_range range = { 0 }; 36b87937cdea689594a293979b30b13054e7455deeKen Sumrall struct stat sb; 37b87937cdea689594a293979b30b13054e7455deeKen Sumrall extern struct fstab *fstab; 38b87937cdea689594a293979b30b13054e7455deeKen Sumrall 39b87937cdea689594a293979b30b13054e7455deeKen Sumrall SLOGI("Starting fstrim work...\n"); 40b87937cdea689594a293979b30b13054e7455deeKen Sumrall 41b87937cdea689594a293979b30b13054e7455deeKen Sumrall for (i = 0; i < fstab->num_entries; i++) { 42b87937cdea689594a293979b30b13054e7455deeKen Sumrall /* Skip raw partitions */ 43b87937cdea689594a293979b30b13054e7455deeKen Sumrall if (!strcmp(fstab->recs[i].fs_type, "emmc") || 44b87937cdea689594a293979b30b13054e7455deeKen Sumrall !strcmp(fstab->recs[i].fs_type, "mtd")) { 45b87937cdea689594a293979b30b13054e7455deeKen Sumrall continue; 46b87937cdea689594a293979b30b13054e7455deeKen Sumrall } 47b87937cdea689594a293979b30b13054e7455deeKen Sumrall /* Skip read-only filesystems */ 48b87937cdea689594a293979b30b13054e7455deeKen Sumrall if (fstab->recs[i].flags & MS_RDONLY) { 49b87937cdea689594a293979b30b13054e7455deeKen Sumrall continue; 50b87937cdea689594a293979b30b13054e7455deeKen Sumrall } 51b87937cdea689594a293979b30b13054e7455deeKen Sumrall if (fs_mgr_is_voldmanaged(&fstab->recs[i])) { 52b87937cdea689594a293979b30b13054e7455deeKen Sumrall continue; /* Should we trim fat32 filesystems? */ 53b87937cdea689594a293979b30b13054e7455deeKen Sumrall } 54b87937cdea689594a293979b30b13054e7455deeKen Sumrall 55b87937cdea689594a293979b30b13054e7455deeKen Sumrall if (stat(fstab->recs[i].mount_point, &sb) == -1) { 56b87937cdea689594a293979b30b13054e7455deeKen Sumrall SLOGE("Cannot stat mount point %s\n", fstab->recs[i].mount_point); 57b87937cdea689594a293979b30b13054e7455deeKen Sumrall ret = -1; 58b87937cdea689594a293979b30b13054e7455deeKen Sumrall continue; 59b87937cdea689594a293979b30b13054e7455deeKen Sumrall } 60b87937cdea689594a293979b30b13054e7455deeKen Sumrall if (!S_ISDIR(sb.st_mode)) { 61b87937cdea689594a293979b30b13054e7455deeKen Sumrall SLOGE("%s is not a directory\n", fstab->recs[i].mount_point); 62b87937cdea689594a293979b30b13054e7455deeKen Sumrall ret = -1; 63b87937cdea689594a293979b30b13054e7455deeKen Sumrall continue; 64b87937cdea689594a293979b30b13054e7455deeKen Sumrall } 65b87937cdea689594a293979b30b13054e7455deeKen Sumrall 66b87937cdea689594a293979b30b13054e7455deeKen Sumrall fd = open(fstab->recs[i].mount_point, O_RDONLY); 67b87937cdea689594a293979b30b13054e7455deeKen Sumrall if (fd < 0) { 68b87937cdea689594a293979b30b13054e7455deeKen Sumrall SLOGE("Cannot open %s for FITRIM\n", fstab->recs[i].mount_point); 69b87937cdea689594a293979b30b13054e7455deeKen Sumrall ret = -1; 70b87937cdea689594a293979b30b13054e7455deeKen Sumrall continue; 71b87937cdea689594a293979b30b13054e7455deeKen Sumrall } 72b87937cdea689594a293979b30b13054e7455deeKen Sumrall 73b87937cdea689594a293979b30b13054e7455deeKen Sumrall memset(&range, 0, sizeof(range)); 74b87937cdea689594a293979b30b13054e7455deeKen Sumrall range.len = ULLONG_MAX; 75b87937cdea689594a293979b30b13054e7455deeKen Sumrall SLOGI("Invoking FITRIM ioctl on %s", fstab->recs[i].mount_point); 76b87937cdea689594a293979b30b13054e7455deeKen Sumrall if (ioctl(fd, FITRIM, &range)) { 77b87937cdea689594a293979b30b13054e7455deeKen Sumrall SLOGE("FITRIM ioctl failed on %s", fstab->recs[i].mount_point); 78b87937cdea689594a293979b30b13054e7455deeKen Sumrall ret = -1; 792c4b563b3dc2c5ea0a9e98fab54fee5f55a1a9f7Ken Sumrall } else { 802c4b563b3dc2c5ea0a9e98fab54fee5f55a1a9f7Ken Sumrall SLOGI("Trimmed %llu bytes on %s\n", range.len, fstab->recs[i].mount_point); 81b87937cdea689594a293979b30b13054e7455deeKen Sumrall } 82b87937cdea689594a293979b30b13054e7455deeKen Sumrall close(fd); 83b87937cdea689594a293979b30b13054e7455deeKen Sumrall } 84b87937cdea689594a293979b30b13054e7455deeKen Sumrall SLOGI("Finished fstrim work.\n"); 85b87937cdea689594a293979b30b13054e7455deeKen Sumrall 86743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall return (void *)ret; 87b87937cdea689594a293979b30b13054e7455deeKen Sumrall} 88b87937cdea689594a293979b30b13054e7455deeKen Sumrall 89743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrallint fstrim_filesystems(void) 90743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall{ 91743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall pthread_t t; 92743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall int ret; 93743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall 94743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall /* Depending on the emmc chip and size, this can take upwards 95743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall * of a few minutes. If done in the same thread as the caller 96743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall * of this function, that would block vold from accepting any 97743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall * commands until the trim is finished. So start another thread 98743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall * to do the work, and return immediately. 99743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall * 100743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall * This function should not be called more than once per day, but 101743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall * even if it is called a second time before the first one finishes, 102743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall * the kernel will "do the right thing" and split the work between 103743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall * the two ioctls invoked in separate threads. 104743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall */ 105743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall ret = pthread_create(&t, NULL, do_fstrim_filesystems, NULL); 106743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall if (ret) { 107743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall SLOGE("Cannot create thread to do fstrim"); 108743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall return ret; 109743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall } 110743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall 111743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall ret = pthread_detach(t); 112743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall if (ret) { 113743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall SLOGE("Cannot detach thread doing fstrim"); 114743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall return ret; 115743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall } 116743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall 117743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall return 0; 118743a5ec96cd54bdc06234be15cdde65296357a6aKen Sumrall} 119