Mount /dev/fuse on /mnt/user/<userid>/<volumeid>
Since system_server cannot mount devices by itself,
add a binder interface to vold that system_server
can call to initiate this mount when required.
BUG: 135341433
Test: manual
Test: atest --test-mapping packages/providers/MediaProvider
Test: ExternalStorageHostTest DownloadProviderTests
Change-Id: If4fd02a1f1a8d921a3f96783d8c73e085c5b7ca1
diff --git a/VolumeManager.cpp b/VolumeManager.cpp
index 44bff5a..2eb1ed5 100644
--- a/VolumeManager.cpp
+++ b/VolumeManager.cpp
@@ -31,6 +31,7 @@
#include <sys/wait.h>
#include <unistd.h>
#include <array>
+#include <thread>
#include <linux/kdev_t.h>
@@ -100,6 +101,22 @@
VolumeManager* VolumeManager::sInstance = NULL;
+static void* symlinkPrimary(void* data) {
+ std::unique_ptr<std::pair<std::string, std::string>> linkInfo(
+ static_cast<std::pair<std::string, std::string>*>(data));
+ std::string* source = &linkInfo->first;
+ std::string* target = &linkInfo->second;
+
+ fs_prepare_dir(source->c_str(), 0755, AID_ROOT, AID_ROOT);
+ fs_prepare_dir(target->c_str(), 0755, AID_ROOT, AID_ROOT);
+ *target = *target + "/primary";
+
+ // Link source to target
+ LOG(DEBUG) << "Linking " << *source << " to " << *target;
+ Symlink(*source, *target);
+ return nullptr;
+}
+
VolumeManager* VolumeManager::Instance() {
if (!sInstance) sInstance = new VolumeManager();
return sInstance;
@@ -365,6 +382,21 @@
}
int VolumeManager::linkPrimary(userid_t userId) {
+ bool isFuse = GetBoolProperty(android::vold::kPropFuse, false);
+
+ if (isFuse) {
+ // Here we have to touch /mnt/user/userid>/<volumeid> which was already mounted as part of
+ // the boot sequence, requiring waiting till a fuse handler is available. If we do this work
+ // in foreground we could hang the caller, i.e. system server, which needs to start the fuse
+ // handler. So do it in the background.
+ std::string source(
+ StringPrintf("/mnt/user/%d/%s/%d", userId, mPrimary->getId().c_str(), userId));
+ std::string target(StringPrintf("/mnt/user/%d/self", userId));
+
+ auto symlinkInfo = new std::pair<std::string, std::string>(source, target);
+ std::thread(symlinkPrimary, symlinkInfo).detach();
+ }
+
std::string source(mPrimary->getPath());
if (mPrimary->isEmulated()) {
source = StringPrintf("%s/%d", source.c_str(), userId);
@@ -431,6 +463,10 @@
}
int VolumeManager::remountUid(uid_t uid, int32_t mountMode) {
+ if (GetBoolProperty(android::vold::kPropFuse, false)) {
+ // TODO(135341433): Implement fuse specific logic.
+ return 0;
+ }
std::string mode;
switch (mountMode) {
case VoldNativeService::REMOUNT_MODE_NONE: