1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "EmulatedVolume.h" 18 #include "Utils.h" 19 20 #include <android-base/stringprintf.h> 21 #include <android-base/logging.h> 22 #include <cutils/fs.h> 23 #include <private/android_filesystem_config.h> 24 #include <utils/Timers.h> 25 26 #include <fcntl.h> 27 #include <stdlib.h> 28 #include <sys/mount.h> 29 #include <sys/stat.h> 30 #include <sys/types.h> 31 #include <sys/sysmacros.h> 32 #include <sys/wait.h> 33 34 using android::base::StringPrintf; 35 36 namespace android { 37 namespace vold { 38 39 static const char* kFusePath = "/system/bin/sdcard"; 40 41 EmulatedVolume::EmulatedVolume(const std::string& rawPath) : 42 VolumeBase(Type::kEmulated), mFusePid(0) { 43 setId("emulated"); 44 mRawPath = rawPath; 45 mLabel = "emulated"; 46 } 47 48 EmulatedVolume::EmulatedVolume(const std::string& rawPath, dev_t device, 49 const std::string& fsUuid) : VolumeBase(Type::kEmulated), mFusePid(0) { 50 setId(StringPrintf("emulated:%u,%u", major(device), minor(device))); 51 mRawPath = rawPath; 52 mLabel = fsUuid; 53 } 54 55 EmulatedVolume::~EmulatedVolume() { 56 } 57 58 status_t EmulatedVolume::doMount() { 59 // We could have migrated storage to an adopted private volume, so always 60 // call primary storage "emulated" to avoid media rescans. 61 std::string label = mLabel; 62 if (getMountFlags() & MountFlags::kPrimary) { 63 label = "emulated"; 64 } 65 66 mFuseDefault = StringPrintf("/mnt/runtime/default/%s", label.c_str()); 67 mFuseRead = StringPrintf("/mnt/runtime/read/%s", label.c_str()); 68 mFuseWrite = StringPrintf("/mnt/runtime/write/%s", label.c_str()); 69 70 setInternalPath(mRawPath); 71 setPath(StringPrintf("/storage/%s", label.c_str())); 72 73 if (fs_prepare_dir(mFuseDefault.c_str(), 0700, AID_ROOT, AID_ROOT) || 74 fs_prepare_dir(mFuseRead.c_str(), 0700, AID_ROOT, AID_ROOT) || 75 fs_prepare_dir(mFuseWrite.c_str(), 0700, AID_ROOT, AID_ROOT)) { 76 PLOG(ERROR) << getId() << " failed to create mount points"; 77 return -errno; 78 } 79 80 dev_t before = GetDevice(mFuseWrite); 81 82 if (!(mFusePid = fork())) { 83 if (execl(kFusePath, kFusePath, 84 "-u", "1023", // AID_MEDIA_RW 85 "-g", "1023", // AID_MEDIA_RW 86 "-m", 87 "-w", 88 "-G", 89 "-i", 90 mRawPath.c_str(), 91 label.c_str(), 92 NULL)) { 93 PLOG(ERROR) << "Failed to exec"; 94 } 95 96 LOG(ERROR) << "FUSE exiting"; 97 _exit(1); 98 } 99 100 if (mFusePid == -1) { 101 PLOG(ERROR) << getId() << " failed to fork"; 102 return -errno; 103 } 104 105 nsecs_t start = systemTime(SYSTEM_TIME_BOOTTIME); 106 while (before == GetDevice(mFuseWrite)) { 107 LOG(VERBOSE) << "Waiting for FUSE to spin up..."; 108 usleep(50000); // 50ms 109 110 nsecs_t now = systemTime(SYSTEM_TIME_BOOTTIME); 111 if (nanoseconds_to_milliseconds(now - start) > 5000) { 112 LOG(WARNING) << "Timed out while waiting for FUSE to spin up"; 113 return -ETIMEDOUT; 114 } 115 } 116 /* sdcardfs will have exited already. FUSE will still be running */ 117 if (TEMP_FAILURE_RETRY(waitpid(mFusePid, nullptr, WNOHANG)) == mFusePid) 118 mFusePid = 0; 119 120 return OK; 121 } 122 123 status_t EmulatedVolume::doUnmount() { 124 // Unmount the storage before we kill the FUSE process. If we kill 125 // the FUSE process first, most file system operations will return 126 // ENOTCONN until the unmount completes. This is an exotic and unusual 127 // error code and might cause broken behaviour in applications. 128 KillProcessesUsingPath(getPath()); 129 ForceUnmount(mFuseDefault); 130 ForceUnmount(mFuseRead); 131 ForceUnmount(mFuseWrite); 132 133 if (mFusePid > 0) { 134 kill(mFusePid, SIGTERM); 135 TEMP_FAILURE_RETRY(waitpid(mFusePid, nullptr, 0)); 136 mFusePid = 0; 137 } 138 139 rmdir(mFuseDefault.c_str()); 140 rmdir(mFuseRead.c_str()); 141 rmdir(mFuseWrite.c_str()); 142 143 mFuseDefault.clear(); 144 mFuseRead.clear(); 145 mFuseWrite.clear(); 146 147 return OK; 148 } 149 150 } // namespace vold 151 } // namespace android 152