Trim both internal and adopted private storage.

Refactor fstrim code to be encapsulated in unique task object, and
give it option of benchmarking when finished.  Trimming now includes
both storage from fstab and adopted private volumes.  Cleaner timing
stats are logged for each unique volume.

Add wakelock during ongoing async move tasks.  Push disk sysfs path
to framework so it can parse any SD card registers as desired.

Bug: 21831325
Change-Id: I76577685f5cae4929c251ad314ffdaeb5eb1c8bf
diff --git a/Android.mk b/Android.mk
index d403b96..38da8c7 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 32be05c..36d2950 100644
--- a/CommandListener.cpp
+++ b/CommandListener.cpp
@@ -45,8 +45,8 @@
 #include "Loop.h"
 #include "Devmapper.h"
 #include "cryptfs.h"
-#include "fstrim.h"
 #include "MoveTask.h"
+#include "TrimTask.h"
 
 #define DUMP_ARGS 0
 
@@ -255,7 +255,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);
 
@@ -600,32 +600,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])) {