Merge "Introduce lock for SELinux process-level changes."
diff --git a/.clang-format b/.clang-format
new file mode 100644
index 0000000..ae4a451
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1,11 @@
+BasedOnStyle: Google
+AccessModifierOffset: -2
+AllowShortFunctionsOnASingleLine: Inline
+ColumnLimit: 100
+CommentPragmas: NOLINT:.*
+DerivePointerAlignment: false
+IndentWidth: 4
+PointerAlignment: Left
+TabWidth: 4
+UseTab: Never
+PenaltyExcessCharacter: 32
diff --git a/Android.mk b/Android.mk
index f1804b6..8cbc1d4 100644
--- a/Android.mk
+++ b/Android.mk
@@ -20,9 +20,9 @@
 	model/EmulatedVolume.cpp \
 	model/ObbVolume.cpp \
 	Utils.cpp \
-	MoveTask.cpp \
-	BenchmarkTask.cpp \
-	TrimTask.cpp \
+	MoveStorage.cpp \
+	Benchmark.cpp \
+	IdleMaint.cpp \
 	KeyBuffer.cpp \
 	Keymaster.cpp \
 	KeyStorage.cpp \
diff --git a/BenchmarkTask.cpp b/Benchmark.cpp
similarity index 81%
rename from BenchmarkTask.cpp
rename to Benchmark.cpp
index d10d792..63b4dd3 100644
--- a/BenchmarkTask.cpp
+++ b/Benchmark.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "BenchmarkTask.h"
+#include "Benchmark.h"
 #include "BenchmarkGen.h"
 #include "VolumeManager.h"
 
@@ -24,6 +24,8 @@
 #include <hardware_legacy/power.h>
 #include <private/android_filesystem_config.h>
 
+#include <thread>
+
 #include <sys/time.h>
 #include <sys/resource.h>
 #include <unistd.h>
@@ -36,21 +38,10 @@
 namespace android {
 namespace vold {
 
-static const char* kWakeLock = "BenchmarkTask";
+static const char* kWakeLock = "Benchmark";
 
-BenchmarkTask::BenchmarkTask(const std::string& path,
-        const android::sp<android::os::IVoldTaskListener>& listener) :
-        mPath(path), mListener(listener) {
-}
-
-BenchmarkTask::~BenchmarkTask() {
-}
-
-void BenchmarkTask::start() {
-    mThread = std::thread(&BenchmarkTask::run, this);
-}
-
-static status_t runInternal(const std::string& rootPath, android::os::PersistableBundle& extras) {
+static status_t benchmarkInternal(const std::string& rootPath,
+        android::os::PersistableBundle* extras) {
     auto path = rootPath;
     path += "/misc";
     if (android::vold::PrepareDir(path, 01771, AID_SYSTEM, AID_MISC)) {
@@ -143,23 +134,24 @@
     LOG(INFO) << "run took " << nanoseconds_to_milliseconds(run_d) << "ms";
     LOG(INFO) << "destroy took " << nanoseconds_to_milliseconds(destroy_d) << "ms";
 
-    extras.putString(String16("path"), String16(path.c_str()));
-    extras.putString(String16("ident"), String16(BenchmarkIdent().c_str()));
-    extras.putLong(String16("create"), create_d);
-    extras.putLong(String16("drop"), drop_d);
-    extras.putLong(String16("run"), run_d);
-    extras.putLong(String16("destroy"), destroy_d);
+    extras->putString(String16("path"), String16(path.c_str()));
+    extras->putString(String16("ident"), String16(BenchmarkIdent().c_str()));
+    extras->putLong(String16("create"), create_d);
+    extras->putLong(String16("drop"), drop_d);
+    extras->putLong(String16("run"), run_d);
+    extras->putLong(String16("destroy"), destroy_d);
 
     return 0;
 }
 
-void BenchmarkTask::run() {
+void Benchmark(const std::string& path,
+        const android::sp<android::os::IVoldTaskListener>& listener) {
     acquire_wake_lock(PARTIAL_WAKE_LOCK, kWakeLock);
 
     android::os::PersistableBundle extras;
-    status_t res = runInternal(mPath, extras);
-    if (mListener) {
-        mListener->onFinished(res, extras);
+    status_t res = benchmarkInternal(path, &extras);
+    if (listener) {
+        listener->onFinished(res, extras);
     }
 
     release_wake_lock(kWakeLock);
diff --git a/BenchmarkTask.h b/Benchmark.h
similarity index 61%
rename from BenchmarkTask.h
rename to Benchmark.h
index dfa3922..4f19b01 100644
--- a/BenchmarkTask.h
+++ b/Benchmark.h
@@ -14,35 +14,18 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_VOLD_BENCHMARK_TASK_H
-#define ANDROID_VOLD_BENCHMARK_TASK_H
+#ifndef ANDROID_VOLD_BENCHMARK_H
+#define ANDROID_VOLD_BENCHMARK_H
 
 #include "android/os/IVoldTaskListener.h"
-#include "Utils.h"
 
 #include <string>
-#include <thread>
 
 namespace android {
 namespace vold {
 
-class BenchmarkTask {
-public:
-    BenchmarkTask(const std::string& path,
-            const android::sp<android::os::IVoldTaskListener>& listener);
-    virtual ~BenchmarkTask();
-
-    void start();
-
-private:
-    std::string mPath;
-    android::sp<android::os::IVoldTaskListener> mListener;
-    std::thread mThread;
-
-    void run();
-
-    DISALLOW_COPY_AND_ASSIGN(BenchmarkTask);
-};
+void Benchmark(const std::string& path,
+        const android::sp<android::os::IVoldTaskListener>& listener);
 
 }  // namespace vold
 }  // namespace android
diff --git a/TrimTask.cpp b/IdleMaint.cpp
similarity index 78%
rename from TrimTask.cpp
rename to IdleMaint.cpp
index 2718095..ed6374f 100644
--- a/TrimTask.cpp
+++ b/IdleMaint.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "TrimTask.h"
+#include "IdleMaint.h"
 #include "Utils.h"
 #include "VolumeManager.h"
 
@@ -31,36 +31,26 @@
 #include <sys/wait.h>
 #include <fcntl.h>
 
-/* From a would-be kernel header */
-#define FIDTRIM         _IOWR('f', 128, struct fstrim_range)    /* Deep discard trim */
-
 using android::base::StringPrintf;
 
 namespace android {
 namespace vold {
 
-static const char* kWakeLock = "TrimTask";
+static const char* kWakeLock = "IdleMaint";
 
-TrimTask::TrimTask(int flags, const android::sp<android::os::IVoldTaskListener>& listener) :
-        mFlags(flags), mListener(listener) {
-    // Collect both fstab and vold volumes
-    addFromFstab();
-
+static void addFromVolumeManager(std::list<std::string>* paths) {
     VolumeManager* vm = VolumeManager::Instance();
     std::list<std::string> privateIds;
     vm->listVolumes(VolumeBase::Type::kPrivate, privateIds);
     for (const auto& id : privateIds) {
         auto vol = vm->findVolume(id);
         if (vol != nullptr && vol->getState() == VolumeBase::State::kMounted) {
-            mPaths.push_back(vol->getPath());
+            paths->push_back(vol->getPath());
         }
     }
 }
 
-TrimTask::~TrimTask() {
-}
-
-void TrimTask::addFromFstab() {
+static void addFromFstab(std::list<std::string>* paths) {
     std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)> fstab(fs_mgr_read_fstab_default(),
                                                                fs_mgr_free_fstab);
     struct fstab_rec *prev_rec = NULL;
@@ -89,19 +79,20 @@
             continue;
         }
 
-        mPaths.push_back(fstab->recs[i].mount_point);
+        paths->push_back(fstab->recs[i].mount_point);
         prev_rec = &fstab->recs[i];
     }
 }
 
-void TrimTask::start() {
-    mThread = std::thread(&TrimTask::run, this);
-}
-
-void TrimTask::run() {
+void Trim(const android::sp<android::os::IVoldTaskListener>& listener) {
     acquire_wake_lock(PARTIAL_WAKE_LOCK, kWakeLock);
 
-    for (const auto& path : mPaths) {
+    // Collect both fstab and vold volumes
+    std::list<std::string> paths;
+    addFromFstab(&paths);
+    addFromVolumeManager(&paths);
+
+    for (const auto& path : paths) {
         LOG(DEBUG) << "Starting trim of " << path;
 
         android::os::PersistableBundle extras;
@@ -110,8 +101,8 @@
         int fd = open(path.c_str(), O_RDONLY | O_DIRECTORY | O_CLOEXEC | O_NOFOLLOW);
         if (fd < 0) {
             PLOG(WARNING) << "Failed to open " << path;
-            if (mListener) {
-                mListener->onStatus(-1, extras);
+            if (listener) {
+                listener->onStatus(-1, extras);
             }
             continue;
         }
@@ -121,10 +112,10 @@
         range.len = ULLONG_MAX;
 
         nsecs_t start = systemTime(SYSTEM_TIME_BOOTTIME);
-        if (ioctl(fd, (mFlags & Flags::kDeepTrim) ? FIDTRIM : FITRIM, &range)) {
+        if (ioctl(fd, FITRIM, &range)) {
             PLOG(WARNING) << "Trim failed on " << path;
-            if (mListener) {
-                mListener->onStatus(-1, extras);
+            if (listener) {
+                listener->onStatus(-1, extras);
             }
         } else {
             nsecs_t time = systemTime(SYSTEM_TIME_BOOTTIME) - start;
@@ -132,16 +123,16 @@
                     << " in " << nanoseconds_to_milliseconds(time) << "ms";
             extras.putLong(String16("bytes"), range.len);
             extras.putLong(String16("time"), time);
-            if (mListener) {
-                mListener->onStatus(0, extras);
+            if (listener) {
+                listener->onStatus(0, extras);
             }
         }
         close(fd);
     }
 
-    if (mListener) {
+    if (listener) {
         android::os::PersistableBundle extras;
-        mListener->onFinished(0, extras);
+        listener->onFinished(0, extras);
     }
 
     release_wake_lock(kWakeLock);
diff --git a/IdleMaint.h b/IdleMaint.h
new file mode 100644
index 0000000..38dadfb
--- /dev/null
+++ b/IdleMaint.h
@@ -0,0 +1,30 @@
+/*
+ * 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_IDLE_MAINT_H
+#define ANDROID_VOLD_IDLE_MAINT_H
+
+#include "android/os/IVoldTaskListener.h"
+
+namespace android {
+namespace vold {
+
+void Trim(const android::sp<android::os::IVoldTaskListener>& listener);
+
+}  // namespace vold
+}  // namespace android
+
+#endif
diff --git a/MoveTask.cpp b/MoveStorage.cpp
similarity index 76%
rename from MoveTask.cpp
rename to MoveStorage.cpp
index 4268ed4..4f5ebe8 100644
--- a/MoveTask.cpp
+++ b/MoveStorage.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "MoveTask.h"
+#include "MoveStorage.h"
 #include "Utils.h"
 #include "VolumeManager.h"
 
@@ -23,6 +23,8 @@
 #include <private/android_filesystem_config.h>
 #include <hardware_legacy/power.h>
 
+#include <thread>
+
 #include <dirent.h>
 #include <sys/wait.h>
 
@@ -44,22 +46,11 @@
 
 static const char* kWakeLock = "MoveTask";
 
-MoveTask::MoveTask(const std::shared_ptr<VolumeBase>& from, const std::shared_ptr<VolumeBase>& to,
-        const android::sp<android::os::IVoldTaskListener>& listener) :
-        mFrom(from), mTo(to), mListener(listener) {
-}
-
-MoveTask::~MoveTask() {
-}
-
-void MoveTask::start() {
-    mThread = std::thread(&MoveTask::run, this);
-}
-
-void MoveTask::notifyProgress(int progress) {
-    if (mListener) {
+static void notifyProgress(int progress,
+        const android::sp<android::os::IVoldTaskListener>& listener) {
+    if (listener) {
         android::os::PersistableBundle extras;
-        mListener->onStatus(progress, extras);
+        listener->onStatus(progress, extras);
     }
 }
 
@@ -86,8 +77,9 @@
     return found ? OK : -1;
 }
 
-status_t MoveTask::execRm(const std::string& path, int startProgress, int stepProgress) {
-    notifyProgress(startProgress);
+static status_t execRm(const std::string& path, int startProgress, int stepProgress,
+        const android::sp<android::os::IVoldTaskListener>& listener) {
+    notifyProgress(startProgress, listener);
 
     uint64_t expectedBytes = GetTreeBytes(path);
     uint64_t startFreeBytes = GetFreeBytes(path);
@@ -121,15 +113,15 @@
         sleep(1);
         uint64_t deltaFreeBytes = GetFreeBytes(path) - startFreeBytes;
         notifyProgress(startProgress + CONSTRAIN((int)
-                ((deltaFreeBytes * stepProgress) / expectedBytes), 0, stepProgress));
+                ((deltaFreeBytes * stepProgress) / expectedBytes), 0, stepProgress), listener);
     }
     return -1;
 #endif
 }
 
-status_t MoveTask::execCp(const std::string& fromPath, const std::string& toPath,
-        int startProgress, int stepProgress) {
-    notifyProgress(startProgress);
+static status_t execCp(const std::string& fromPath, const std::string& toPath, int startProgress,
+        int stepProgress, const android::sp<android::os::IVoldTaskListener>& listener) {
+    notifyProgress(startProgress, listener);
 
     uint64_t expectedBytes = GetTreeBytes(fromPath);
     uint64_t startFreeBytes = GetFreeBytes(toPath);
@@ -172,7 +164,7 @@
         sleep(1);
         uint64_t deltaFreeBytes = startFreeBytes - GetFreeBytes(toPath);
         notifyProgress(startProgress + CONSTRAIN((int)
-                ((deltaFreeBytes * stepProgress) / expectedBytes), 0, stepProgress));
+                ((deltaFreeBytes * stepProgress) / expectedBytes), 0, stepProgress), listener);
     }
     return -1;
 #endif
@@ -192,69 +184,80 @@
     vol->create();
 }
 
-void MoveTask::run() {
-    acquire_wake_lock(PARTIAL_WAKE_LOCK, kWakeLock);
-
+static status_t moveStorageInternal(const std::shared_ptr<VolumeBase>& from,
+        const std::shared_ptr<VolumeBase>& to,
+        const android::sp<android::os::IVoldTaskListener>& listener) {
     std::string fromPath;
     std::string toPath;
 
     // TODO: add support for public volumes
-    if (mFrom->getType() != VolumeBase::Type::kEmulated) goto fail;
-    if (mTo->getType() != VolumeBase::Type::kEmulated) goto fail;
+    if (from->getType() != VolumeBase::Type::kEmulated) goto fail;
+    if (to->getType() != VolumeBase::Type::kEmulated) goto fail;
 
     // Step 1: tear down volumes and mount silently without making
     // visible to userspace apps
     {
         std::lock_guard<std::mutex> lock(VolumeManager::Instance()->getLock());
-        bringOffline(mFrom);
-        bringOffline(mTo);
+        bringOffline(from);
+        bringOffline(to);
     }
 
-    fromPath = mFrom->getInternalPath();
-    toPath = mTo->getInternalPath();
+    fromPath = from->getInternalPath();
+    toPath = to->getInternalPath();
 
     // Step 2: clean up any stale data
-    if (execRm(toPath, 10, 10) != OK) {
+    if (execRm(toPath, 10, 10, listener) != OK) {
         goto fail;
     }
 
     // Step 3: perform actual copy
-    if (execCp(fromPath, toPath, 20, 60) != OK) {
+    if (execCp(fromPath, toPath, 20, 60, listener) != OK) {
         goto copy_fail;
     }
 
     // NOTE: MountService watches for this magic value to know
     // that move was successful
-    notifyProgress(82);
+    notifyProgress(82, listener);
     {
         std::lock_guard<std::mutex> lock(VolumeManager::Instance()->getLock());
-        bringOnline(mFrom);
-        bringOnline(mTo);
+        bringOnline(from);
+        bringOnline(to);
     }
 
     // Step 4: clean up old data
-    if (execRm(fromPath, 85, 15) != OK) {
+    if (execRm(fromPath, 85, 15, listener) != OK) {
         goto fail;
     }
 
-    notifyProgress(kMoveSucceeded);
-    release_wake_lock(kWakeLock);
-    return;
+    notifyProgress(kMoveSucceeded, listener);
+    return OK;
 
 copy_fail:
     // if we failed to copy the data we should not leave it laying around
     // in target location. Do not check return value, we can not do any
     // useful anyway.
-    execRm(toPath, 80, 1);
+    execRm(toPath, 80, 1, listener);
 fail:
     {
         std::lock_guard<std::mutex> lock(VolumeManager::Instance()->getLock());
-        bringOnline(mFrom);
-        bringOnline(mTo);
+        bringOnline(from);
+        bringOnline(to);
     }
-    notifyProgress(kMoveFailedInternalError);
+    notifyProgress(kMoveFailedInternalError, listener);
+    return -1;
+}
+
+void MoveStorage(const std::shared_ptr<VolumeBase>& from, const std::shared_ptr<VolumeBase>& to,
+        const android::sp<android::os::IVoldTaskListener>& listener) {
+    acquire_wake_lock(PARTIAL_WAKE_LOCK, kWakeLock);
+
+    android::os::PersistableBundle extras;
+    status_t res = moveStorageInternal(from, to, listener);
+    if (listener) {
+        listener->onFinished(res, extras);
+    }
+
     release_wake_lock(kWakeLock);
-    return;
 }
 
 }  // namespace vold
diff --git a/MoveStorage.h b/MoveStorage.h
new file mode 100644
index 0000000..d271704
--- /dev/null
+++ b/MoveStorage.h
@@ -0,0 +1,32 @@
+/*
+ * 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_MOVE_STORAGE_H
+#define ANDROID_VOLD_MOVE_STORAGE_H
+
+#include "android/os/IVoldTaskListener.h"
+#include "model/VolumeBase.h"
+
+namespace android {
+namespace vold {
+
+void MoveStorage(const std::shared_ptr<VolumeBase>& from, const std::shared_ptr<VolumeBase>& to,
+        const android::sp<android::os::IVoldTaskListener>& listener);
+
+}  // namespace vold
+}  // namespace android
+
+#endif
diff --git a/MoveTask.h b/MoveTask.h
deleted file mode 100644
index 246a24d..0000000
--- a/MoveTask.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * 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_MOVE_TASK_H
-#define ANDROID_VOLD_MOVE_TASK_H
-
-#include "android/os/IVoldTaskListener.h"
-#include "Utils.h"
-#include "model/VolumeBase.h"
-
-#include <thread>
-
-namespace android {
-namespace vold {
-
-class MoveTask {
-public:
-    MoveTask(const std::shared_ptr<VolumeBase>& from, const std::shared_ptr<VolumeBase>& to,
-            const android::sp<android::os::IVoldTaskListener>& listener);
-    virtual ~MoveTask();
-
-    void start();
-
-private:
-    std::shared_ptr<VolumeBase> mFrom;
-    std::shared_ptr<VolumeBase> mTo;
-    android::sp<android::os::IVoldTaskListener> mListener;
-    std::thread mThread;
-
-    void run();
-
-    void notifyProgress(int progress);
-
-    status_t execRm(const std::string& path, int startProgress, int stepProgress);
-    status_t execCp(const std::string& fromPath, const std::string& toPath,
-            int startProgress, int stepProgress);
-
-    DISALLOW_COPY_AND_ASSIGN(MoveTask);
-};
-
-}  // namespace vold
-}  // namespace android
-
-#endif
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
new file mode 100644
index 0000000..c8dbf77
--- /dev/null
+++ b/PREUPLOAD.cfg
@@ -0,0 +1,5 @@
+[Builtin Hooks]
+clang_format = true
+
+[Builtin Hooks Options]
+clang_format = --commit ${PREUPLOAD_COMMIT} --style file --extensions c,h,cc,cpp
diff --git a/TrimTask.h b/TrimTask.h
deleted file mode 100644
index a87728b..0000000
--- a/TrimTask.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * 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 "android/os/IVoldTaskListener.h"
-#include "Utils.h"
-
-#include <thread>
-#include <list>
-
-namespace android {
-namespace vold {
-
-class TrimTask {
-public:
-    explicit TrimTask(int flags, const android::sp<android::os::IVoldTaskListener>& listener);
-    virtual ~TrimTask();
-
-    enum Flags {
-        kDeepTrim = 1 << 0,
-    };
-
-    void start();
-
-private:
-    int mFlags;
-    android::sp<android::os::IVoldTaskListener> mListener;
-    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/VoldNativeService.cpp b/VoldNativeService.cpp
index c82eb92..d8832d3 100644
--- a/VoldNativeService.cpp
+++ b/VoldNativeService.cpp
@@ -18,16 +18,17 @@
 
 #include "VoldNativeService.h"
 #include "VolumeManager.h"
-#include "BenchmarkTask.h"
-#include "MoveTask.h"
+#include "Benchmark.h"
+#include "MoveStorage.h"
 #include "Process.h"
-#include "TrimTask.h"
+#include "IdleMaint.h"
 
 #include "cryptfs.h"
 #include "Ext4Crypt.h"
 #include "MetadataCrypt.h"
 
 #include <fstream>
+#include <thread>
 
 #include <android-base/logging.h>
 #include <android-base/stringprintf.h>
@@ -120,6 +121,10 @@
         return exception(binder::Status::EX_ILLEGAL_ARGUMENT,
                 StringPrintf("Path %s is relative", path.c_str()));
     }
+    if ((path + '/').find("/../") != std::string::npos) {
+        return exception(binder::Status::EX_ILLEGAL_ARGUMENT,
+                StringPrintf("Path %s is shady", path.c_str()));
+    }
     for (const char& c : path) {
         if (c == '\0' || c == '\n') {
             return exception(binder::Status::EX_ILLEGAL_ARGUMENT,
@@ -377,7 +382,9 @@
         return error("Volume " + volId + " missing path");
     }
 
-    (new android::vold::BenchmarkTask(path, listener))->start();
+    std::thread([=]() {
+        android::vold::Benchmark(path, listener);
+    }).detach();
     return ok();
 }
 
@@ -395,7 +402,10 @@
     } else if (toVol == nullptr) {
         return error("Failed to find volume " + toVolId);
     }
-    (new android::vold::MoveTask(fromVol, toVol, listener))->start();
+
+    std::thread([=]() {
+        android::vold::MoveStorage(fromVol, toVol, listener);
+    }).detach();
     return ok();
 }
 
@@ -446,7 +456,9 @@
     ENFORCE_UID(AID_SYSTEM);
     ACQUIRE_LOCK;
 
-    (new android::vold::TrimTask(fstrimFlags, listener))->start();
+    std::thread([=]() {
+        android::vold::Trim(listener);
+    }).detach();
     return ok();
 }
 
@@ -712,6 +724,7 @@
 
 binder::Status VoldNativeService::secdiscard(const std::string& path) {
     ENFORCE_UID(AID_SYSTEM);
+    CHECK_ARGUMENT_PATH(path);
     ACQUIRE_CRYPT_LOCK;
 
     return translateBool(e4crypt_secdiscard(path));
diff --git a/main.cpp b/main.cpp
index cca738e..01a2168 100644
--- a/main.cpp
+++ b/main.cpp
@@ -130,12 +130,9 @@
 
     ATRACE_END();
 
-    // Eventually we'll become the monitoring thread
-    while(1) {
-        pause();
-    }
+    android::IPCThreadState::self()->joinThreadPool();
+    LOG(INFO) << "vold shutting down";
 
-    LOG(ERROR) << "Vold exiting";
     exit(0);
 }