am c86ab6f5: Trim both internal and adopted private storage.

* commit 'c86ab6f538bec63638c168d6c843fe7cf73add3b':
  Trim both internal and adopted private storage.
diff --git a/Android.mk b/Android.mk
index 4bab604..1a4f8dd 100644
--- a/Android.mk
+++ b/Android.mk
@@ -17,7 +17,6 @@
 	CheckBattery.cpp \
 	Ext4Crypt.cpp \
 	VoldUtil.c \
-	fstrim.c \
 	cryptfs.c \
 	Disk.cpp \
 	VolumeBase.cpp \
@@ -27,6 +26,7 @@
 	Utils.cpp \
 	MoveTask.cpp \
 	Benchmark.cpp \
+	TrimTask.cpp \
 
 common_c_includes := \
 	system/extras/ext4_utils \
diff --git a/Benchmark.cpp b/Benchmark.cpp
index e329588..7a3af65 100644
--- a/Benchmark.cpp
+++ b/Benchmark.cpp
@@ -22,6 +22,7 @@
 #include <base/file.h>
 #include <base/logging.h>
 #include <cutils/iosched_policy.h>
+#include <private/android_filesystem_config.h>
 
 #include <sys/time.h>
 #include <sys/resource.h>
@@ -33,14 +34,19 @@
 namespace android {
 namespace vold {
 
-static std::string simpleRead(const std::string& path) {
-    std::string tmp;
-    ReadFileToString(path, &tmp);
-    tmp.erase(tmp.find_last_not_of(" \n\r") + 1);
-    return tmp;
+static void notifyResult(const std::string& path, int64_t create_d,
+        int64_t drop_d, int64_t run_d, int64_t destroy_d) {
+    std::string res(path +
+            + " " + BenchmarkIdent()
+            + " " + std::to_string(create_d)
+            + " " + std::to_string(drop_d)
+            + " " + std::to_string(run_d)
+            + " " + std::to_string(destroy_d));
+    VolumeManager::Instance()->getBroadcaster()->sendBroadcast(
+            ResponseCode::BenchmarkResult, res.c_str(), false);
 }
 
-nsecs_t Benchmark(const std::string& path, const std::string& sysPath) {
+static nsecs_t benchmark(const std::string& path) {
     errno = 0;
     int orig_prio = getpriority(PRIO_PROCESS, 0);
     if (errno != 0) {
@@ -82,9 +88,11 @@
     sync();
     nsecs_t create = systemTime(SYSTEM_TIME_BOOTTIME);
 
+    LOG(VERBOSE) << "Before drop_caches";
     if (!WriteStringToFile("3", "/proc/sys/vm/drop_caches")) {
         PLOG(ERROR) << "Failed to drop_caches";
     }
+    LOG(VERBOSE) << "After drop_caches";
     nsecs_t drop = systemTime(SYSTEM_TIME_BOOTTIME);
 
     BenchmarkRun();
@@ -95,6 +103,16 @@
     sync();
     nsecs_t destroy = systemTime(SYSTEM_TIME_BOOTTIME);
 
+    if (chdir(orig_cwd) != 0) {
+        PLOG(ERROR) << "Failed to chdir";
+    }
+    if (android_set_ioprio(0, orig_clazz, orig_ioprio)) {
+        PLOG(ERROR) << "Failed to android_set_ioprio";
+    }
+    if (setpriority(PRIO_PROCESS, 0, orig_prio) != 0) {
+        PLOG(ERROR) << "Failed to setpriority";
+    }
+
     nsecs_t create_d = create - start;
     nsecs_t drop_d = drop - create;
     nsecs_t run_d = run - drop;
@@ -105,39 +123,27 @@
     LOG(INFO) << "run took " << nanoseconds_to_milliseconds(run_d) << "ms";
     LOG(INFO) << "destroy took " << nanoseconds_to_milliseconds(destroy_d) << "ms";
 
-    std::string detail;
-    detail += "id=" + BenchmarkIdent()
-            + ",cr=" + std::to_string(create_d)
-            + ",dr=" + std::to_string(drop_d)
-            + ",ru=" + std::to_string(run_d)
-            + ",de=" + std::to_string(destroy_d)
-            + ",si=" + simpleRead(sysPath + "/size")
-            + ",ve=" + simpleRead(sysPath + "/device/vendor")
-            + ",mo=" + simpleRead(sysPath + "/device/model")
-            + ",csd=" + simpleRead(sysPath + "/device/csd");
+    notifyResult(path, create_d, drop_d, run_d, destroy_d);
 
-    // Scrub CRC and serial number out of CID
-    std::string cid = simpleRead(sysPath + "/device/cid");
-    if (cid.length() == 32) {
-        cid.erase(32, 1);
-        cid.erase(18, 8);
-        detail += ",cid=" + cid;
-    }
-
-    VolumeManager::Instance()->getBroadcaster()->sendBroadcast(
-            ResponseCode::BenchmarkResult, detail.c_str(), false);
-
-    if (chdir(orig_cwd) != 0) {
-        PLOG(ERROR) << "Failed to chdir";
-    }
-    if (android_set_ioprio(0, orig_clazz, orig_ioprio)) {
-        PLOG(ERROR) << "Failed to android_set_ioprio";
-    }
-    if (setpriority(PRIO_PROCESS, 0, orig_prio) != 0) {
-        PLOG(ERROR) << "Failed to setpriority";
-    }
     return run_d;
 }
 
+nsecs_t BenchmarkPrivate(const std::string& path) {
+    std::string benchPath(path);
+    benchPath += "/misc";
+    if (android::vold::PrepareDir(benchPath, 01771, AID_SYSTEM, AID_MISC)) {
+        return -1;
+    }
+    benchPath += "/vold";
+    if (android::vold::PrepareDir(benchPath, 0700, AID_ROOT, AID_ROOT)) {
+        return -1;
+    }
+    benchPath += "/bench";
+    if (android::vold::PrepareDir(benchPath, 0700, AID_ROOT, AID_ROOT)) {
+        return -1;
+    }
+    return benchmark(benchPath);
+}
+
 }  // namespace vold
 }  // namespace android
diff --git a/Benchmark.h b/Benchmark.h
index 02e22d5..13f9009 100644
--- a/Benchmark.h
+++ b/Benchmark.h
@@ -25,7 +25,8 @@
 namespace android {
 namespace vold {
 
-nsecs_t Benchmark(const std::string& path, const std::string& sysPath);
+/* Benchmark a private volume mounted at the given path */
+nsecs_t BenchmarkPrivate(const std::string& path);
 
 }  // namespace vold
 }  // namespace android
diff --git a/CommandListener.cpp b/CommandListener.cpp
index 52a709f..a9a8031 100644
--- a/CommandListener.cpp
+++ b/CommandListener.cpp
@@ -46,8 +46,8 @@
 #include "Devmapper.h"
 #include "Ext4Crypt.h"
 #include "cryptfs.h"
-#include "fstrim.h"
 #include "MoveTask.h"
+#include "TrimTask.h"
 
 #define DUMP_ARGS 0
 
@@ -256,7 +256,7 @@
     } else if (cmd == "benchmark" && argc > 2) {
         // benchmark [volId]
         std::string id(argv[2]);
-        nsecs_t res = vm->benchmarkVolume(id);
+        nsecs_t res = vm->benchmarkPrivate(id);
         return cli->sendMsg(ResponseCode::CommandOkay,
                 android::base::StringPrintf("%" PRId64, res).c_str(), false);
 
@@ -601,32 +601,23 @@
         return 0;
     }
 
-    int rc = 0;
+    VolumeManager *vm = VolumeManager::Instance();
+    std::lock_guard<std::mutex> lock(vm->getLock());
 
-    if (!strcmp(argv[1], "dotrim")) {
-        if (argc != 2) {
-            cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: fstrim dotrim", false);
-            return 0;
-        }
-        dumpArgs(argc, argv, -1);
-        rc = fstrim_filesystems(0);
-    } else if (!strcmp(argv[1], "dodtrim")) {
-        if (argc != 2) {
-            cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: fstrim dodtrim", false);
-            return 0;
-        }
-        dumpArgs(argc, argv, -1);
-        rc = fstrim_filesystems(1);   /* Do Deep Discard trim */
-    } else {
-        dumpArgs(argc, argv, -1);
-        cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown fstrim cmd", false);
+    int flags = 0;
+
+    std::string cmd(argv[1]);
+    if (cmd == "dotrim") {
+        flags = 0;
+    } else if (cmd == "dotrimbench") {
+        flags = android::vold::TrimTask::Flags::kBenchmarkAfter;
+    } else if (cmd == "dodtrim") {
+        flags = android::vold::TrimTask::Flags::kDeepTrim;
+    } else if (cmd == "dodtrimbench") {
+        flags = android::vold::TrimTask::Flags::kDeepTrim
+                | android::vold::TrimTask::Flags::kBenchmarkAfter;
     }
 
-    // Always report that the command succeeded and return the error code.
-    // The caller will check the return value to see what the error was.
-    char msg[255];
-    snprintf(msg, sizeof(msg), "%d", rc);
-    cli->sendMsg(ResponseCode::CommandOkay, msg, false);
-
-    return 0;
+    (new android::vold::TrimTask(flags))->start();
+    return sendGenericOkFail(cli, 0);
 }
diff --git a/Disk.cpp b/Disk.cpp
index df53d07..1e76bee 100644
--- a/Disk.cpp
+++ b/Disk.cpp
@@ -105,6 +105,15 @@
     return nullptr;
 }
 
+void Disk::listVolumes(VolumeBase::Type type, std::list<std::string>& list) {
+    for (auto vol : mVolumes) {
+        if (vol->getType() == type) {
+            list.push_back(vol->getId());
+        }
+        // TODO: consider looking at stacked volumes
+    }
+}
+
 status_t Disk::create() {
     CHECK(!mCreated);
     mCreated = true;
@@ -229,6 +238,7 @@
 
     notifyEvent(ResponseCode::DiskSizeChanged, StringPrintf("%" PRId64, mSize));
     notifyEvent(ResponseCode::DiskLabelChanged, mLabel);
+    notifyEvent(ResponseCode::DiskSysPathChanged, mSysPath);
     return OK;
 }
 
diff --git a/Disk.h b/Disk.h
index 60e4fa9..77ec7df 100644
--- a/Disk.h
+++ b/Disk.h
@@ -18,6 +18,7 @@
 #define ANDROID_VOLD_DISK_H
 
 #include "Utils.h"
+#include "VolumeBase.h"
 
 #include <utils/Errors.h>
 
@@ -64,6 +65,8 @@
 
     std::shared_ptr<VolumeBase> findVolume(const std::string& id);
 
+    void listVolumes(VolumeBase::Type type, std::list<std::string>& list);
+
     status_t create();
     status_t destroy();
 
diff --git a/MoveTask.cpp b/MoveTask.cpp
index e0eec12..10cd549 100644
--- a/MoveTask.cpp
+++ b/MoveTask.cpp
@@ -22,6 +22,7 @@
 #include <base/stringprintf.h>
 #include <base/logging.h>
 #include <private/android_filesystem_config.h>
+#include <hardware_legacy/power.h>
 
 #include <dirent.h>
 #include <sys/wait.h>
@@ -40,6 +41,8 @@
 static const char* kCpPath = "/system/bin/cp";
 static const char* kRmPath = "/system/bin/rm";
 
+static const char* kWakeLock = "MoveTask";
+
 MoveTask::MoveTask(const std::shared_ptr<VolumeBase>& from,
         const std::shared_ptr<VolumeBase>& to) :
         mFrom(from), mTo(to) {
@@ -168,6 +171,8 @@
 }
 
 void MoveTask::run() {
+    acquire_wake_lock(PARTIAL_WAKE_LOCK, kWakeLock);
+
     std::string fromPath;
     std::string toPath;
 
@@ -205,11 +210,13 @@
     }
 
     notifyProgress(kMoveSucceeded);
+    release_wake_lock(kWakeLock);
     return;
 fail:
     bringOnline(mFrom);
     bringOnline(mTo);
     notifyProgress(kMoveFailedInternalError);
+    release_wake_lock(kWakeLock);
     return;
 }
 
diff --git a/ResponseCode.h b/ResponseCode.h
index 2d01087..f2c533e 100644
--- a/ResponseCode.h
+++ b/ResponseCode.h
@@ -70,6 +70,7 @@
     static const int DiskSizeChanged = 641;
     static const int DiskLabelChanged = 642;
     static const int DiskScanned = 643;
+    static const int DiskSysPathChanged = 644;
     static const int DiskDestroyed = 649;
 
     static const int VolumeCreated = 650;
@@ -83,6 +84,7 @@
 
     static const int MoveStatus = 660;
     static const int BenchmarkResult = 661;
+    static const int TrimResult = 662;
 
     static int convertFromErrno();
 };
diff --git a/TrimTask.cpp b/TrimTask.cpp
new file mode 100644
index 0000000..1c6eb1f
--- /dev/null
+++ b/TrimTask.cpp
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "TrimTask.h"
+#include "Benchmark.h"
+#include "Utils.h"
+#include "VolumeManager.h"
+#include "ResponseCode.h"
+
+#include <base/stringprintf.h>
+#include <base/logging.h>
+#include <cutils/properties.h>
+#include <fs_mgr.h>
+#include <private/android_filesystem_config.h>
+#include <hardware_legacy/power.h>
+
+#include <dirent.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+
+/* From a would-be kernel header */
+#define FIDTRIM         _IOWR('f', 128, struct fstrim_range)    /* Deep discard trim */
+
+#define BENCHMARK_ENABLED 0
+
+using android::base::StringPrintf;
+
+namespace android {
+namespace vold {
+
+static const char* kWakeLock = "TrimTask";
+
+TrimTask::TrimTask(int flags) : mFlags(flags) {
+    // Collect both fstab and vold volumes
+    addFromFstab();
+
+    VolumeManager* vm = VolumeManager::Instance();
+    std::list<std::string> privateIds;
+    vm->listVolumes(VolumeBase::Type::kPrivate, privateIds);
+    for (auto id : privateIds) {
+        auto vol = vm->findVolume(id);
+        if (vol != nullptr && vol->getState() == VolumeBase::State::kMounted) {
+            mPaths.push_back(vol->getPath());
+        }
+    }
+}
+
+TrimTask::~TrimTask() {
+}
+
+void TrimTask::addFromFstab() {
+    struct fstab *fstab;
+    struct fstab_rec *prev_rec = NULL;
+
+    fstab = fs_mgr_read_fstab(android::vold::DefaultFstabPath().c_str());
+    for (int i = 0; i < fstab->num_entries; i++) {
+        /* Skip raw partitions */
+        if (!strcmp(fstab->recs[i].fs_type, "emmc") ||
+            !strcmp(fstab->recs[i].fs_type, "mtd")) {
+            continue;
+        }
+        /* Skip read-only filesystems */
+        if (fstab->recs[i].flags & MS_RDONLY) {
+            continue;
+        }
+        if (fs_mgr_is_voldmanaged(&fstab->recs[i])) {
+            continue; /* Should we trim fat32 filesystems? */
+        }
+        if (fs_mgr_is_notrim(&fstab->recs[i])) {
+            continue;
+        }
+
+        /* Skip the multi-type partitions, which are required to be following each other.
+         * See fs_mgr.c's mount_with_alternatives().
+         */
+        if (prev_rec && !strcmp(prev_rec->mount_point, fstab->recs[i].mount_point)) {
+            continue;
+        }
+
+        mPaths.push_back(fstab->recs[i].mount_point);
+        prev_rec = &fstab->recs[i];
+    }
+    fs_mgr_free_fstab(fstab);
+}
+
+void TrimTask::start() {
+    mThread = std::thread(&TrimTask::run, this);
+}
+
+static void notifyResult(const std::string& path, int64_t bytes, int64_t delta) {
+    std::string res(path
+            + " " + std::to_string(bytes)
+            + " " + std::to_string(delta));
+    VolumeManager::Instance()->getBroadcaster()->sendBroadcast(
+            ResponseCode::TrimResult, res.c_str(), false);
+}
+
+void TrimTask::run() {
+    acquire_wake_lock(PARTIAL_WAKE_LOCK, kWakeLock);
+
+    for (auto path : mPaths) {
+        LOG(DEBUG) << "Starting trim of " << path;
+
+        int fd = open(path.c_str(), O_RDONLY | O_DIRECTORY | O_CLOEXEC | O_NOFOLLOW);
+        if (fd < 0) {
+            PLOG(WARNING) << "Failed to open " << path;
+            continue;
+        }
+
+        struct fstrim_range range;
+        memset(&range, 0, sizeof(range));
+        range.len = ULLONG_MAX;
+
+        nsecs_t start = systemTime(SYSTEM_TIME_BOOTTIME);
+        if (ioctl(fd, (mFlags & Flags::kDeepTrim) ? FIDTRIM : FITRIM, &range)) {
+            PLOG(WARNING) << "Trim failed on " << path;
+            notifyResult(path, -1, -1);
+        } else {
+            nsecs_t delta = systemTime(SYSTEM_TIME_BOOTTIME) - start;
+            LOG(INFO) << "Trimmed " << range.len << " bytes on " << path
+                    << " in " << nanoseconds_to_milliseconds(delta) << "ms";
+            notifyResult(path, range.len, delta);
+        }
+        close(fd);
+
+        if (mFlags & Flags::kBenchmarkAfter) {
+#if BENCHMARK_ENABLED
+            BenchmarkPrivate(path);
+#else
+            LOG(DEBUG) << "Benchmark disabled";
+#endif
+        }
+    }
+
+    release_wake_lock(kWakeLock);
+}
+
+}  // namespace vold
+}  // namespace android
diff --git a/TrimTask.h b/TrimTask.h
new file mode 100644
index 0000000..57be802
--- /dev/null
+++ b/TrimTask.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_VOLD_TRIM_TASK_H
+#define ANDROID_VOLD_TRIM_TASK_H
+
+#include "Utils.h"
+
+#include <thread>
+#include <list>
+
+namespace android {
+namespace vold {
+
+class TrimTask {
+public:
+    TrimTask(int flags);
+    virtual ~TrimTask();
+
+    enum Flags {
+        kDeepTrim = 1 << 0,
+        kBenchmarkAfter = 1 << 1,
+    };
+
+    void start();
+
+private:
+    int mFlags;
+    std::list<std::string> mPaths;
+    std::thread mThread;
+
+    void addFromFstab();
+    void run();
+
+    DISALLOW_COPY_AND_ASSIGN(TrimTask);
+};
+
+}  // namespace vold
+}  // namespace android
+
+#endif
diff --git a/Utils.cpp b/Utils.cpp
index ec9c906..06222c3 100644
--- a/Utils.cpp
+++ b/Utils.cpp
@@ -22,6 +22,7 @@
 #include <base/logging.h>
 #include <base/stringprintf.h>
 #include <cutils/fs.h>
+#include <cutils/properties.h>
 #include <private/android_filesystem_config.h>
 #include <logwrap/logwrap.h>
 
@@ -532,5 +533,11 @@
     }
 }
 
+std::string DefaultFstabPath() {
+    char hardware[PROPERTY_VALUE_MAX];
+    property_get("ro.hardware", hardware, "");
+    return StringPrintf("/fstab.%s", hardware);
+}
+
 }  // namespace vold
 }  // namespace android
diff --git a/Utils.h b/Utils.h
index ce0f7c8..f33a379 100644
--- a/Utils.h
+++ b/Utils.h
@@ -92,6 +92,8 @@
 
 dev_t GetDevice(const std::string& path);
 
+std::string DefaultFstabPath();
+
 }  // namespace vold
 }  // namespace android
 
diff --git a/VolumeManager.cpp b/VolumeManager.cpp
index d1a0b2f..6710b0c 100755
--- a/VolumeManager.cpp
+++ b/VolumeManager.cpp
@@ -60,7 +60,6 @@
 #include "Asec.h"
 #include "VoldUtil.h"
 #include "cryptfs.h"
-#include "fstrim.h"
 
 #define MASS_STORAGE_FILE_PATH  "/sys/class/android_usb/android0/f_mass_storage/lun/file"
 
@@ -370,20 +369,23 @@
     return nullptr;
 }
 
-nsecs_t VolumeManager::benchmarkVolume(const std::string& id) {
+void VolumeManager::listVolumes(android::vold::VolumeBase::Type type,
+        std::list<std::string>& list) {
+    list.clear();
+    for (auto disk : mDisks) {
+        disk->listVolumes(type, list);
+    }
+}
+
+nsecs_t VolumeManager::benchmarkPrivate(const std::string& id) {
     std::string path;
-    std::string sysPath;
-    auto vol = findVolume(id);
-    if (vol != nullptr) {
-        if (vol->getState() == android::vold::VolumeBase::State::kMounted) {
-            path = vol->getPath();
-            auto disk = findDisk(vol->getDiskId());
-            if (disk != nullptr) {
-                sysPath = disk->getSysPath();
-            }
-        }
-    } else {
+    if (id == "private" || id == "null") {
         path = "/data";
+    } else {
+        auto vol = findVolume(id);
+        if (vol != nullptr && vol->getState() == android::vold::VolumeBase::State::kMounted) {
+            path = vol->getPath();
+        }
     }
 
     if (path.empty()) {
@@ -391,20 +393,7 @@
         return -1;
     }
 
-    path += "/misc";
-    if (android::vold::PrepareDir(path, 01771, AID_SYSTEM, AID_MISC)) {
-        return -1;
-    }
-    path += "/vold";
-    if (android::vold::PrepareDir(path, 0700, AID_ROOT, AID_ROOT)) {
-        return -1;
-    }
-    path += "/bench";
-    if (android::vold::PrepareDir(path, 0700, AID_ROOT, AID_ROOT)) {
-        return -1;
-    }
-
-    return android::vold::Benchmark(path, sysPath);
+    return android::vold::BenchmarkPrivate(path);
 }
 
 int VolumeManager::forgetPartition(const std::string& partGuid) {
diff --git a/VolumeManager.h b/VolumeManager.h
index 6c094fc..fa2237f 100644
--- a/VolumeManager.h
+++ b/VolumeManager.h
@@ -118,7 +118,9 @@
     std::shared_ptr<android::vold::Disk> findDisk(const std::string& id);
     std::shared_ptr<android::vold::VolumeBase> findVolume(const std::string& id);
 
-    nsecs_t benchmarkVolume(const std::string& id);
+    void listVolumes(android::vold::VolumeBase::Type type, std::list<std::string>& list);
+
+    nsecs_t benchmarkPrivate(const std::string& id);
 
     int forgetPartition(const std::string& partGuid);
 
diff --git a/fstrim.c b/fstrim.c
deleted file mode 100644
index 60c9f24..0000000
--- a/fstrim.c
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <sys/ioctl.h>
-#include <string.h>
-#include <limits.h>
-#include <linux/fs.h>
-#include <time.h>
-#include <fs_mgr.h>
-#include <pthread.h>
-#define LOG_TAG "fstrim"
-#include "cutils/log.h"
-#include "hardware_legacy/power.h"
-
-/* These numbers must match what the MountService specified in
- * frameworks/base/services/java/com/android/server/EventLogTags.logtags
- */
-#define LOG_FSTRIM_START  2755
-#define LOG_FSTRIM_FINISH 2756
-
-#define FSTRIM_WAKELOCK "dofstrim"
-
-#define UNUSED __attribute__((unused))
-
-/* From a would-be kernel header */
-#define FIDTRIM         _IOWR('f', 128, struct fstrim_range)    /* Deep discard trim */
-
-static unsigned long long get_boot_time_ms(void)
-{
-    struct timespec t;
-    unsigned long long time_ms;
-
-    t.tv_sec = 0;
-    t.tv_nsec = 0;
-    clock_gettime(CLOCK_BOOTTIME, &t);
-    time_ms = (t.tv_sec * 1000LL) + (t.tv_nsec / 1000000);
-
-    return time_ms;
-}
-
-static void *do_fstrim_filesystems(void *thread_arg)
-{
-    int i;
-    int fd;
-    int ret = 0;
-    struct fstrim_range range = { 0 };
-    extern struct fstab *fstab;
-    int deep_trim = !!thread_arg;
-    struct fstab_rec *prev_rec = NULL;
-
-    SLOGI("Starting fstrim work...\n");
-
-    /* Get a wakelock as this may take a while, and we don't want the
-     * device to sleep on us.
-     */
-    acquire_wake_lock(PARTIAL_WAKE_LOCK, FSTRIM_WAKELOCK);
-
-    /* Log the start time in the event log */
-    LOG_EVENT_LONG(LOG_FSTRIM_START, get_boot_time_ms());
-
-    for (i = 0; i < fstab->num_entries; i++) {
-        /* Skip raw partitions */
-        if (!strcmp(fstab->recs[i].fs_type, "emmc") ||
-            !strcmp(fstab->recs[i].fs_type, "mtd")) {
-            continue;
-        }
-        /* Skip read-only filesystems */
-        if (fstab->recs[i].flags & MS_RDONLY) {
-            continue;
-        }
-        if (fs_mgr_is_voldmanaged(&fstab->recs[i])) {
-            continue; /* Should we trim fat32 filesystems? */
-        }
-        if (fs_mgr_is_notrim(&fstab->recs[i])) {
-            continue;
-        }
-
-        /* Skip the multi-type partitions, which are required to be following each other.
-         * See fs_mgr.c's mount_with_alternatives().
-         */
-        if (prev_rec && !strcmp(prev_rec->mount_point, fstab->recs[i].mount_point)) {
-            continue;
-        }
-
-        fd = open(fstab->recs[i].mount_point, O_RDONLY | O_DIRECTORY | O_CLOEXEC | O_NOFOLLOW);
-        if (fd < 0) {
-            SLOGE("Cannot open %s for FITRIM\n", fstab->recs[i].mount_point);
-            ret = -1;
-            continue;
-        }
-
-        memset(&range, 0, sizeof(range));
-        range.len = ULLONG_MAX;
-        SLOGI("Invoking %s ioctl on %s", deep_trim ? "FIDTRIM" : "FITRIM", fstab->recs[i].mount_point);
-
-        ret = ioctl(fd, deep_trim ? FIDTRIM : FITRIM, &range);
-        if (ret) {
-            SLOGE("%s ioctl failed on %s (error %d/%s)", deep_trim ? "FIDTRIM" : "FITRIM", fstab->recs[i].mount_point, errno, strerror(errno));
-            ret = -1;
-        } else {
-            SLOGI("Trimmed %llu bytes on %s\n", range.len, fstab->recs[i].mount_point);
-        }
-        close(fd);
-        prev_rec = &fstab->recs[i];
-    }
-
-    /* Log the finish time in the event log */
-    LOG_EVENT_LONG(LOG_FSTRIM_FINISH, get_boot_time_ms());
-
-    SLOGI("Finished fstrim work.\n");
-
-    /* Release the wakelock that let us work */
-    release_wake_lock(FSTRIM_WAKELOCK);
-
-    return (void *)(uintptr_t)ret;
-}
-
-int fstrim_filesystems(int deep_trim)
-{
-    pthread_t t;
-    int ret;
-
-    /* Depending on the emmc chip and size, this can take upwards
-     * of a few minutes.  If done in the same thread as the caller
-     * of this function, that would block vold from accepting any
-     * commands until the trim is finished.  So start another thread
-     * to do the work, and return immediately.
-     *
-     * This function should not be called more than once per day, but
-     * even if it is called a second time before the first one finishes,
-     * the kernel will "do the right thing" and split the work between
-     * the two ioctls invoked in separate threads.
-     */
-    ret = pthread_create(&t, NULL, do_fstrim_filesystems, (void *)(intptr_t)deep_trim);
-    if (ret) {
-        SLOGE("Cannot create thread to do fstrim");
-        return ret;
-    }
-
-    ret = pthread_detach(t);
-    if (ret) {
-        SLOGE("Cannot detach thread doing fstrim");
-        return ret;
-    }
-
-    return 0;
-}
diff --git a/fstrim.h b/fstrim.h
deleted file mode 100644
index 185d998..0000000
--- a/fstrim.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-    int fstrim_filesystems(int deep_trim);
-#ifdef __cplusplus
-}
-#endif
-
diff --git a/main.cpp b/main.cpp
index abdff9f..648f36a 100644
--- a/main.cpp
+++ b/main.cpp
@@ -208,25 +208,15 @@
 }
 
 static int process_config(VolumeManager *vm) {
-    bool has_adoptable = false;
-    char hardware[PROPERTY_VALUE_MAX];
-    property_get("ro.hardware", hardware, "");
-    std::string fstab_filename(StringPrintf("/fstab.%s", hardware));
-
-#ifdef DEBUG_FSTAB
-    if (access(DEBUG_FSTAB, R_OK) == 0) {
-        LOG(DEBUG) << "Found debug fstab; switching!";
-        fstab_filename = DEBUG_FSTAB;
-    }
-#endif
-
-    fstab = fs_mgr_read_fstab(fstab_filename.c_str());
+    std::string path(android::vold::DefaultFstabPath());
+    fstab = fs_mgr_read_fstab(path.c_str());
     if (!fstab) {
-        PLOG(ERROR) << "Failed to open " << fstab_filename;
+        PLOG(ERROR) << "Failed to open default fstab " << path;
         return -1;
     }
 
     /* Loop through entries looking for ones that vold manages */
+    bool has_adoptable = false;
     for (int i = 0; i < fstab->num_entries; i++) {
         if (fs_mgr_is_voldmanaged(&fstab->recs[i])) {
             if (fs_mgr_is_nonremovable(&fstab->recs[i])) {