xref: /aosp_15_r20/system/vold/model/PublicVolume.cpp (revision f40fafd4c6c2594924d919feffc1a1fd6e3b30f3)
1*f40fafd4SAndroid Build Coastguard Worker /*
2*f40fafd4SAndroid Build Coastguard Worker  * Copyright (C) 2015 The Android Open Source Project
3*f40fafd4SAndroid Build Coastguard Worker  *
4*f40fafd4SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*f40fafd4SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*f40fafd4SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*f40fafd4SAndroid Build Coastguard Worker  *
8*f40fafd4SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*f40fafd4SAndroid Build Coastguard Worker  *
10*f40fafd4SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*f40fafd4SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*f40fafd4SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*f40fafd4SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*f40fafd4SAndroid Build Coastguard Worker  * limitations under the License.
15*f40fafd4SAndroid Build Coastguard Worker  */
16*f40fafd4SAndroid Build Coastguard Worker 
17*f40fafd4SAndroid Build Coastguard Worker #include "PublicVolume.h"
18*f40fafd4SAndroid Build Coastguard Worker 
19*f40fafd4SAndroid Build Coastguard Worker #include "AppFuseUtil.h"
20*f40fafd4SAndroid Build Coastguard Worker #include "Utils.h"
21*f40fafd4SAndroid Build Coastguard Worker #include "VolumeManager.h"
22*f40fafd4SAndroid Build Coastguard Worker #include "fs/Exfat.h"
23*f40fafd4SAndroid Build Coastguard Worker #include "fs/Vfat.h"
24*f40fafd4SAndroid Build Coastguard Worker 
25*f40fafd4SAndroid Build Coastguard Worker #include <android-base/logging.h>
26*f40fafd4SAndroid Build Coastguard Worker #include <android-base/properties.h>
27*f40fafd4SAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
28*f40fafd4SAndroid Build Coastguard Worker #include <cutils/fs.h>
29*f40fafd4SAndroid Build Coastguard Worker #include <private/android_filesystem_config.h>
30*f40fafd4SAndroid Build Coastguard Worker #include <utils/Timers.h>
31*f40fafd4SAndroid Build Coastguard Worker 
32*f40fafd4SAndroid Build Coastguard Worker #include <fcntl.h>
33*f40fafd4SAndroid Build Coastguard Worker #include <stdlib.h>
34*f40fafd4SAndroid Build Coastguard Worker #include <sys/mount.h>
35*f40fafd4SAndroid Build Coastguard Worker #include <sys/stat.h>
36*f40fafd4SAndroid Build Coastguard Worker #include <sys/sysmacros.h>
37*f40fafd4SAndroid Build Coastguard Worker #include <sys/types.h>
38*f40fafd4SAndroid Build Coastguard Worker #include <sys/wait.h>
39*f40fafd4SAndroid Build Coastguard Worker 
40*f40fafd4SAndroid Build Coastguard Worker using android::base::GetBoolProperty;
41*f40fafd4SAndroid Build Coastguard Worker using android::base::StringPrintf;
42*f40fafd4SAndroid Build Coastguard Worker 
43*f40fafd4SAndroid Build Coastguard Worker namespace android {
44*f40fafd4SAndroid Build Coastguard Worker namespace vold {
45*f40fafd4SAndroid Build Coastguard Worker 
46*f40fafd4SAndroid Build Coastguard Worker static const char* kSdcardFsPath = "/system/bin/sdcard";
47*f40fafd4SAndroid Build Coastguard Worker 
48*f40fafd4SAndroid Build Coastguard Worker static const char* kAsecPath = "/mnt/secure/asec";
49*f40fafd4SAndroid Build Coastguard Worker 
PublicVolume(dev_t device)50*f40fafd4SAndroid Build Coastguard Worker PublicVolume::PublicVolume(dev_t device) : VolumeBase(Type::kPublic), mDevice(device) {
51*f40fafd4SAndroid Build Coastguard Worker     setId(StringPrintf("public:%u,%u", major(device), minor(device)));
52*f40fafd4SAndroid Build Coastguard Worker     mDevPath = StringPrintf("/dev/block/vold/%s", getId().c_str());
53*f40fafd4SAndroid Build Coastguard Worker     mFuseMounted = false;
54*f40fafd4SAndroid Build Coastguard Worker     mUseSdcardFs = IsSdcardfsUsed();
55*f40fafd4SAndroid Build Coastguard Worker }
56*f40fafd4SAndroid Build Coastguard Worker 
~PublicVolume()57*f40fafd4SAndroid Build Coastguard Worker PublicVolume::~PublicVolume() {}
58*f40fafd4SAndroid Build Coastguard Worker 
readMetadata()59*f40fafd4SAndroid Build Coastguard Worker status_t PublicVolume::readMetadata() {
60*f40fafd4SAndroid Build Coastguard Worker     status_t res = ReadMetadataUntrusted(mDevPath, &mFsType, &mFsUuid, &mFsLabel);
61*f40fafd4SAndroid Build Coastguard Worker 
62*f40fafd4SAndroid Build Coastguard Worker     auto listener = getListener();
63*f40fafd4SAndroid Build Coastguard Worker     if (listener) listener->onVolumeMetadataChanged(getId(), mFsType, mFsUuid, mFsLabel);
64*f40fafd4SAndroid Build Coastguard Worker 
65*f40fafd4SAndroid Build Coastguard Worker     return res;
66*f40fafd4SAndroid Build Coastguard Worker }
67*f40fafd4SAndroid Build Coastguard Worker 
initAsecStage()68*f40fafd4SAndroid Build Coastguard Worker status_t PublicVolume::initAsecStage() {
69*f40fafd4SAndroid Build Coastguard Worker     std::string legacyPath(mRawPath + "/android_secure");
70*f40fafd4SAndroid Build Coastguard Worker     std::string securePath(mRawPath + "/.android_secure");
71*f40fafd4SAndroid Build Coastguard Worker 
72*f40fafd4SAndroid Build Coastguard Worker     // Recover legacy secure path
73*f40fafd4SAndroid Build Coastguard Worker     if (!access(legacyPath.c_str(), R_OK | X_OK) && access(securePath.c_str(), R_OK | X_OK)) {
74*f40fafd4SAndroid Build Coastguard Worker         if (rename(legacyPath.c_str(), securePath.c_str())) {
75*f40fafd4SAndroid Build Coastguard Worker             PLOG(WARNING) << getId() << " failed to rename legacy ASEC dir";
76*f40fafd4SAndroid Build Coastguard Worker         }
77*f40fafd4SAndroid Build Coastguard Worker     }
78*f40fafd4SAndroid Build Coastguard Worker 
79*f40fafd4SAndroid Build Coastguard Worker     if (TEMP_FAILURE_RETRY(mkdir(securePath.c_str(), 0700))) {
80*f40fafd4SAndroid Build Coastguard Worker         if (errno != EEXIST) {
81*f40fafd4SAndroid Build Coastguard Worker             PLOG(WARNING) << getId() << " creating ASEC stage failed";
82*f40fafd4SAndroid Build Coastguard Worker             return -errno;
83*f40fafd4SAndroid Build Coastguard Worker         }
84*f40fafd4SAndroid Build Coastguard Worker     }
85*f40fafd4SAndroid Build Coastguard Worker 
86*f40fafd4SAndroid Build Coastguard Worker     BindMount(securePath, kAsecPath);
87*f40fafd4SAndroid Build Coastguard Worker 
88*f40fafd4SAndroid Build Coastguard Worker     return OK;
89*f40fafd4SAndroid Build Coastguard Worker }
90*f40fafd4SAndroid Build Coastguard Worker 
doCreate()91*f40fafd4SAndroid Build Coastguard Worker status_t PublicVolume::doCreate() {
92*f40fafd4SAndroid Build Coastguard Worker     return CreateDeviceNode(mDevPath, mDevice);
93*f40fafd4SAndroid Build Coastguard Worker }
94*f40fafd4SAndroid Build Coastguard Worker 
doDestroy()95*f40fafd4SAndroid Build Coastguard Worker status_t PublicVolume::doDestroy() {
96*f40fafd4SAndroid Build Coastguard Worker     return DestroyDeviceNode(mDevPath);
97*f40fafd4SAndroid Build Coastguard Worker }
98*f40fafd4SAndroid Build Coastguard Worker 
doMount()99*f40fafd4SAndroid Build Coastguard Worker status_t PublicVolume::doMount() {
100*f40fafd4SAndroid Build Coastguard Worker     bool isVisible = isVisibleForWrite();
101*f40fafd4SAndroid Build Coastguard Worker     readMetadata();
102*f40fafd4SAndroid Build Coastguard Worker 
103*f40fafd4SAndroid Build Coastguard Worker     if (mFsType == "vfat" && vfat::IsSupported()) {
104*f40fafd4SAndroid Build Coastguard Worker         if (vfat::Check(mDevPath)) {
105*f40fafd4SAndroid Build Coastguard Worker             LOG(ERROR) << getId() << " failed filesystem check";
106*f40fafd4SAndroid Build Coastguard Worker             return -EIO;
107*f40fafd4SAndroid Build Coastguard Worker         }
108*f40fafd4SAndroid Build Coastguard Worker     } else if (mFsType == "exfat" && exfat::IsSupported()) {
109*f40fafd4SAndroid Build Coastguard Worker         if (exfat::Check(mDevPath)) {
110*f40fafd4SAndroid Build Coastguard Worker             LOG(ERROR) << getId() << " failed filesystem check";
111*f40fafd4SAndroid Build Coastguard Worker             return -EIO;
112*f40fafd4SAndroid Build Coastguard Worker         }
113*f40fafd4SAndroid Build Coastguard Worker     } else {
114*f40fafd4SAndroid Build Coastguard Worker         LOG(ERROR) << getId() << " unsupported filesystem " << mFsType;
115*f40fafd4SAndroid Build Coastguard Worker         return -EIO;
116*f40fafd4SAndroid Build Coastguard Worker     }
117*f40fafd4SAndroid Build Coastguard Worker 
118*f40fafd4SAndroid Build Coastguard Worker     // Use UUID as stable name, if available
119*f40fafd4SAndroid Build Coastguard Worker     std::string stableName = getId();
120*f40fafd4SAndroid Build Coastguard Worker     if (!mFsUuid.empty()) {
121*f40fafd4SAndroid Build Coastguard Worker         stableName = mFsUuid;
122*f40fafd4SAndroid Build Coastguard Worker     }
123*f40fafd4SAndroid Build Coastguard Worker 
124*f40fafd4SAndroid Build Coastguard Worker     mRawPath = StringPrintf("/mnt/media_rw/%s", stableName.c_str());
125*f40fafd4SAndroid Build Coastguard Worker 
126*f40fafd4SAndroid Build Coastguard Worker     mSdcardFsDefault = StringPrintf("/mnt/runtime/default/%s", stableName.c_str());
127*f40fafd4SAndroid Build Coastguard Worker     mSdcardFsRead = StringPrintf("/mnt/runtime/read/%s", stableName.c_str());
128*f40fafd4SAndroid Build Coastguard Worker     mSdcardFsWrite = StringPrintf("/mnt/runtime/write/%s", stableName.c_str());
129*f40fafd4SAndroid Build Coastguard Worker     mSdcardFsFull = StringPrintf("/mnt/runtime/full/%s", stableName.c_str());
130*f40fafd4SAndroid Build Coastguard Worker 
131*f40fafd4SAndroid Build Coastguard Worker     setInternalPath(mRawPath);
132*f40fafd4SAndroid Build Coastguard Worker     if (isVisible) {
133*f40fafd4SAndroid Build Coastguard Worker         setPath(StringPrintf("/storage/%s", stableName.c_str()));
134*f40fafd4SAndroid Build Coastguard Worker     } else {
135*f40fafd4SAndroid Build Coastguard Worker         setPath(mRawPath);
136*f40fafd4SAndroid Build Coastguard Worker     }
137*f40fafd4SAndroid Build Coastguard Worker 
138*f40fafd4SAndroid Build Coastguard Worker     if (fs_prepare_dir(mRawPath.c_str(), 0700, AID_ROOT, AID_ROOT)) {
139*f40fafd4SAndroid Build Coastguard Worker         PLOG(ERROR) << getId() << " failed to create mount points";
140*f40fafd4SAndroid Build Coastguard Worker         return -errno;
141*f40fafd4SAndroid Build Coastguard Worker     }
142*f40fafd4SAndroid Build Coastguard Worker 
143*f40fafd4SAndroid Build Coastguard Worker     if (mFsType == "vfat") {
144*f40fafd4SAndroid Build Coastguard Worker         if (vfat::Mount(mDevPath, mRawPath, false, false, false, AID_ROOT,
145*f40fafd4SAndroid Build Coastguard Worker                         (isVisible ? AID_MEDIA_RW : AID_EXTERNAL_STORAGE), 0007, true)) {
146*f40fafd4SAndroid Build Coastguard Worker             PLOG(ERROR) << getId() << " failed to mount " << mDevPath;
147*f40fafd4SAndroid Build Coastguard Worker             return -EIO;
148*f40fafd4SAndroid Build Coastguard Worker         }
149*f40fafd4SAndroid Build Coastguard Worker     } else if (mFsType == "exfat") {
150*f40fafd4SAndroid Build Coastguard Worker         if (exfat::Mount(mDevPath, mRawPath, AID_ROOT,
151*f40fafd4SAndroid Build Coastguard Worker                          (isVisible ? AID_MEDIA_RW : AID_EXTERNAL_STORAGE), 0007)) {
152*f40fafd4SAndroid Build Coastguard Worker             PLOG(ERROR) << getId() << " failed to mount " << mDevPath;
153*f40fafd4SAndroid Build Coastguard Worker             return -EIO;
154*f40fafd4SAndroid Build Coastguard Worker         }
155*f40fafd4SAndroid Build Coastguard Worker     }
156*f40fafd4SAndroid Build Coastguard Worker 
157*f40fafd4SAndroid Build Coastguard Worker     if (getMountFlags() & MountFlags::kPrimary) {
158*f40fafd4SAndroid Build Coastguard Worker         initAsecStage();
159*f40fafd4SAndroid Build Coastguard Worker     }
160*f40fafd4SAndroid Build Coastguard Worker 
161*f40fafd4SAndroid Build Coastguard Worker     if (!isVisible) {
162*f40fafd4SAndroid Build Coastguard Worker         // Not visible to apps, so no need to spin up sdcardfs or FUSE
163*f40fafd4SAndroid Build Coastguard Worker         return OK;
164*f40fafd4SAndroid Build Coastguard Worker     }
165*f40fafd4SAndroid Build Coastguard Worker 
166*f40fafd4SAndroid Build Coastguard Worker     if (mUseSdcardFs) {
167*f40fafd4SAndroid Build Coastguard Worker         if (fs_prepare_dir(mSdcardFsDefault.c_str(), 0700, AID_ROOT, AID_ROOT) ||
168*f40fafd4SAndroid Build Coastguard Worker             fs_prepare_dir(mSdcardFsRead.c_str(), 0700, AID_ROOT, AID_ROOT) ||
169*f40fafd4SAndroid Build Coastguard Worker             fs_prepare_dir(mSdcardFsWrite.c_str(), 0700, AID_ROOT, AID_ROOT) ||
170*f40fafd4SAndroid Build Coastguard Worker             fs_prepare_dir(mSdcardFsFull.c_str(), 0700, AID_ROOT, AID_ROOT)) {
171*f40fafd4SAndroid Build Coastguard Worker             PLOG(ERROR) << getId() << " failed to create sdcardfs mount points";
172*f40fafd4SAndroid Build Coastguard Worker             return -errno;
173*f40fafd4SAndroid Build Coastguard Worker         }
174*f40fafd4SAndroid Build Coastguard Worker 
175*f40fafd4SAndroid Build Coastguard Worker         dev_t before = GetDevice(mSdcardFsFull);
176*f40fafd4SAndroid Build Coastguard Worker 
177*f40fafd4SAndroid Build Coastguard Worker         int sdcardFsPid;
178*f40fafd4SAndroid Build Coastguard Worker         if (!(sdcardFsPid = fork())) {
179*f40fafd4SAndroid Build Coastguard Worker             if (getMountFlags() & MountFlags::kPrimary) {
180*f40fafd4SAndroid Build Coastguard Worker                 // clang-format off
181*f40fafd4SAndroid Build Coastguard Worker                 if (execl(kSdcardFsPath, kSdcardFsPath,
182*f40fafd4SAndroid Build Coastguard Worker                         "-u", "1023", // AID_MEDIA_RW
183*f40fafd4SAndroid Build Coastguard Worker                         "-g", "1023", // AID_MEDIA_RW
184*f40fafd4SAndroid Build Coastguard Worker                         "-U", std::to_string(getMountUserId()).c_str(),
185*f40fafd4SAndroid Build Coastguard Worker                         "-w",
186*f40fafd4SAndroid Build Coastguard Worker                         mRawPath.c_str(),
187*f40fafd4SAndroid Build Coastguard Worker                         stableName.c_str(),
188*f40fafd4SAndroid Build Coastguard Worker                         NULL)) {
189*f40fafd4SAndroid Build Coastguard Worker                     // clang-format on
190*f40fafd4SAndroid Build Coastguard Worker                     PLOG(ERROR) << "Failed to exec";
191*f40fafd4SAndroid Build Coastguard Worker                 }
192*f40fafd4SAndroid Build Coastguard Worker             } else {
193*f40fafd4SAndroid Build Coastguard Worker                 // clang-format off
194*f40fafd4SAndroid Build Coastguard Worker                 if (execl(kSdcardFsPath, kSdcardFsPath,
195*f40fafd4SAndroid Build Coastguard Worker                         "-u", "1023", // AID_MEDIA_RW
196*f40fafd4SAndroid Build Coastguard Worker                         "-g", "1023", // AID_MEDIA_RW
197*f40fafd4SAndroid Build Coastguard Worker                         "-U", std::to_string(getMountUserId()).c_str(),
198*f40fafd4SAndroid Build Coastguard Worker                         mRawPath.c_str(),
199*f40fafd4SAndroid Build Coastguard Worker                         stableName.c_str(),
200*f40fafd4SAndroid Build Coastguard Worker                         NULL)) {
201*f40fafd4SAndroid Build Coastguard Worker                     // clang-format on
202*f40fafd4SAndroid Build Coastguard Worker                     PLOG(ERROR) << "Failed to exec";
203*f40fafd4SAndroid Build Coastguard Worker                 }
204*f40fafd4SAndroid Build Coastguard Worker             }
205*f40fafd4SAndroid Build Coastguard Worker 
206*f40fafd4SAndroid Build Coastguard Worker             LOG(ERROR) << "sdcardfs exiting";
207*f40fafd4SAndroid Build Coastguard Worker             _exit(1);
208*f40fafd4SAndroid Build Coastguard Worker         }
209*f40fafd4SAndroid Build Coastguard Worker 
210*f40fafd4SAndroid Build Coastguard Worker         if (sdcardFsPid == -1) {
211*f40fafd4SAndroid Build Coastguard Worker             PLOG(ERROR) << getId() << " failed to fork";
212*f40fafd4SAndroid Build Coastguard Worker             return -errno;
213*f40fafd4SAndroid Build Coastguard Worker         }
214*f40fafd4SAndroid Build Coastguard Worker 
215*f40fafd4SAndroid Build Coastguard Worker         nsecs_t start = systemTime(SYSTEM_TIME_BOOTTIME);
216*f40fafd4SAndroid Build Coastguard Worker         while (before == GetDevice(mSdcardFsFull)) {
217*f40fafd4SAndroid Build Coastguard Worker             LOG(DEBUG) << "Waiting for sdcardfs to spin up...";
218*f40fafd4SAndroid Build Coastguard Worker             usleep(50000);  // 50ms
219*f40fafd4SAndroid Build Coastguard Worker 
220*f40fafd4SAndroid Build Coastguard Worker             nsecs_t now = systemTime(SYSTEM_TIME_BOOTTIME);
221*f40fafd4SAndroid Build Coastguard Worker             if (nanoseconds_to_milliseconds(now - start) > 5000) {
222*f40fafd4SAndroid Build Coastguard Worker                 LOG(WARNING) << "Timed out while waiting for sdcardfs to spin up";
223*f40fafd4SAndroid Build Coastguard Worker                 return -ETIMEDOUT;
224*f40fafd4SAndroid Build Coastguard Worker             }
225*f40fafd4SAndroid Build Coastguard Worker         }
226*f40fafd4SAndroid Build Coastguard Worker         /* sdcardfs will have exited already. The filesystem will still be running */
227*f40fafd4SAndroid Build Coastguard Worker         TEMP_FAILURE_RETRY(waitpid(sdcardFsPid, nullptr, 0));
228*f40fafd4SAndroid Build Coastguard Worker     }
229*f40fafd4SAndroid Build Coastguard Worker 
230*f40fafd4SAndroid Build Coastguard Worker     // We need to mount FUSE *after* sdcardfs, since the FUSE daemon may depend
231*f40fafd4SAndroid Build Coastguard Worker     // on sdcardfs being up.
232*f40fafd4SAndroid Build Coastguard Worker     LOG(INFO) << "Mounting public fuse volume";
233*f40fafd4SAndroid Build Coastguard Worker     android::base::unique_fd fd;
234*f40fafd4SAndroid Build Coastguard Worker     int user_id = getMountUserId();
235*f40fafd4SAndroid Build Coastguard Worker     int result = MountUserFuse(user_id, getInternalPath(), stableName, &fd);
236*f40fafd4SAndroid Build Coastguard Worker 
237*f40fafd4SAndroid Build Coastguard Worker     if (result != 0) {
238*f40fafd4SAndroid Build Coastguard Worker         LOG(ERROR) << "Failed to mount public fuse volume";
239*f40fafd4SAndroid Build Coastguard Worker         doUnmount();
240*f40fafd4SAndroid Build Coastguard Worker         return -result;
241*f40fafd4SAndroid Build Coastguard Worker     }
242*f40fafd4SAndroid Build Coastguard Worker 
243*f40fafd4SAndroid Build Coastguard Worker     mFuseMounted = true;
244*f40fafd4SAndroid Build Coastguard Worker     auto callback = getMountCallback();
245*f40fafd4SAndroid Build Coastguard Worker     if (callback) {
246*f40fafd4SAndroid Build Coastguard Worker         bool is_ready = false;
247*f40fafd4SAndroid Build Coastguard Worker         callback->onVolumeChecking(std::move(fd), getPath(), getInternalPath(), &is_ready);
248*f40fafd4SAndroid Build Coastguard Worker         if (!is_ready) {
249*f40fafd4SAndroid Build Coastguard Worker             LOG(ERROR) << "Failed to complete public volume mount";
250*f40fafd4SAndroid Build Coastguard Worker             doUnmount();
251*f40fafd4SAndroid Build Coastguard Worker             return -EIO;
252*f40fafd4SAndroid Build Coastguard Worker         }
253*f40fafd4SAndroid Build Coastguard Worker     }
254*f40fafd4SAndroid Build Coastguard Worker 
255*f40fafd4SAndroid Build Coastguard Worker     ConfigureReadAheadForFuse(GetFuseMountPathForUser(user_id, stableName), 256u);
256*f40fafd4SAndroid Build Coastguard Worker 
257*f40fafd4SAndroid Build Coastguard Worker     // See comment in model/EmulatedVolume.cpp
258*f40fafd4SAndroid Build Coastguard Worker     ConfigureMaxDirtyRatioForFuse(GetFuseMountPathForUser(user_id, stableName), 40u);
259*f40fafd4SAndroid Build Coastguard Worker 
260*f40fafd4SAndroid Build Coastguard Worker     auto vol_manager = VolumeManager::Instance();
261*f40fafd4SAndroid Build Coastguard Worker     // Create bind mounts for all running users
262*f40fafd4SAndroid Build Coastguard Worker     for (userid_t started_user : vol_manager->getStartedUsers()) {
263*f40fafd4SAndroid Build Coastguard Worker         userid_t mountUserId = getMountUserId();
264*f40fafd4SAndroid Build Coastguard Worker         if (started_user == mountUserId) {
265*f40fafd4SAndroid Build Coastguard Worker             // No need to bind mount for the user that owns the mount
266*f40fafd4SAndroid Build Coastguard Worker             continue;
267*f40fafd4SAndroid Build Coastguard Worker         }
268*f40fafd4SAndroid Build Coastguard Worker         if (mountUserId != VolumeManager::Instance()->getSharedStorageUser(started_user)) {
269*f40fafd4SAndroid Build Coastguard Worker             // No need to bind if the user does not share storage with the mount owner
270*f40fafd4SAndroid Build Coastguard Worker             continue;
271*f40fafd4SAndroid Build Coastguard Worker         }
272*f40fafd4SAndroid Build Coastguard Worker         // Create mount directory for the user as there is a chance that no other Volume is mounted
273*f40fafd4SAndroid Build Coastguard Worker         // for the user (ex: if the user is just started), so /mnt/user/user_id  does not exist yet.
274*f40fafd4SAndroid Build Coastguard Worker         auto mountDirStatus = PrepareMountDirForUser(started_user);
275*f40fafd4SAndroid Build Coastguard Worker         if (mountDirStatus != OK) {
276*f40fafd4SAndroid Build Coastguard Worker             LOG(ERROR) << "Failed to create Mount Directory for user " << started_user;
277*f40fafd4SAndroid Build Coastguard Worker         }
278*f40fafd4SAndroid Build Coastguard Worker         auto bindMountStatus = bindMountForUser(started_user);
279*f40fafd4SAndroid Build Coastguard Worker         if (bindMountStatus != OK) {
280*f40fafd4SAndroid Build Coastguard Worker             LOG(ERROR) << "Bind Mounting Public Volume: " << stableName
281*f40fafd4SAndroid Build Coastguard Worker                        << " for user: " << started_user << "Failed. Error: " << bindMountStatus;
282*f40fafd4SAndroid Build Coastguard Worker         }
283*f40fafd4SAndroid Build Coastguard Worker     }
284*f40fafd4SAndroid Build Coastguard Worker     return OK;
285*f40fafd4SAndroid Build Coastguard Worker }
286*f40fafd4SAndroid Build Coastguard Worker 
bindMountForUser(userid_t user_id)287*f40fafd4SAndroid Build Coastguard Worker status_t PublicVolume::bindMountForUser(userid_t user_id) {
288*f40fafd4SAndroid Build Coastguard Worker     userid_t mountUserId = getMountUserId();
289*f40fafd4SAndroid Build Coastguard Worker     std::string stableName = getId();
290*f40fafd4SAndroid Build Coastguard Worker     if (!mFsUuid.empty()) {
291*f40fafd4SAndroid Build Coastguard Worker         stableName = mFsUuid;
292*f40fafd4SAndroid Build Coastguard Worker     }
293*f40fafd4SAndroid Build Coastguard Worker 
294*f40fafd4SAndroid Build Coastguard Worker     LOG(INFO) << "Bind Mounting Public Volume for user: " << user_id
295*f40fafd4SAndroid Build Coastguard Worker               << ".Mount owner: " << mountUserId;
296*f40fafd4SAndroid Build Coastguard Worker     auto sourcePath = GetFuseMountPathForUser(mountUserId, stableName);
297*f40fafd4SAndroid Build Coastguard Worker     auto destPath = GetFuseMountPathForUser(user_id, stableName);
298*f40fafd4SAndroid Build Coastguard Worker     PrepareDir(destPath, 0770, AID_ROOT, AID_MEDIA_RW);
299*f40fafd4SAndroid Build Coastguard Worker     auto mountRes = BindMount(sourcePath, destPath);
300*f40fafd4SAndroid Build Coastguard Worker     LOG(INFO) << "Mount status: " << mountRes;
301*f40fafd4SAndroid Build Coastguard Worker 
302*f40fafd4SAndroid Build Coastguard Worker     return mountRes;
303*f40fafd4SAndroid Build Coastguard Worker }
304*f40fafd4SAndroid Build Coastguard Worker 
doUnmount()305*f40fafd4SAndroid Build Coastguard Worker status_t PublicVolume::doUnmount() {
306*f40fafd4SAndroid Build Coastguard Worker     // Unmount the storage before we kill the FUSE process. If we kill
307*f40fafd4SAndroid Build Coastguard Worker     // the FUSE process first, most file system operations will return
308*f40fafd4SAndroid Build Coastguard Worker     // ENOTCONN until the unmount completes. This is an exotic and unusual
309*f40fafd4SAndroid Build Coastguard Worker     // error code and might cause broken behaviour in applications.
310*f40fafd4SAndroid Build Coastguard Worker     KillProcessesUsingPath(getPath());
311*f40fafd4SAndroid Build Coastguard Worker 
312*f40fafd4SAndroid Build Coastguard Worker     if (mFuseMounted) {
313*f40fafd4SAndroid Build Coastguard Worker         // Use UUID as stable name, if available
314*f40fafd4SAndroid Build Coastguard Worker         std::string stableName = getId();
315*f40fafd4SAndroid Build Coastguard Worker         if (!mFsUuid.empty()) {
316*f40fafd4SAndroid Build Coastguard Worker             stableName = mFsUuid;
317*f40fafd4SAndroid Build Coastguard Worker         }
318*f40fafd4SAndroid Build Coastguard Worker 
319*f40fafd4SAndroid Build Coastguard Worker         // Unmount bind mounts for running users
320*f40fafd4SAndroid Build Coastguard Worker         auto vol_manager = VolumeManager::Instance();
321*f40fafd4SAndroid Build Coastguard Worker         int user_id = getMountUserId();
322*f40fafd4SAndroid Build Coastguard Worker         for (int started_user : vol_manager->getStartedUsers()) {
323*f40fafd4SAndroid Build Coastguard Worker             if (started_user == user_id) {
324*f40fafd4SAndroid Build Coastguard Worker                 // No need to remove bind mount for the user that owns the mount
325*f40fafd4SAndroid Build Coastguard Worker                 continue;
326*f40fafd4SAndroid Build Coastguard Worker             }
327*f40fafd4SAndroid Build Coastguard Worker             LOG(INFO) << "Removing Public Volume Bind Mount for: " << started_user;
328*f40fafd4SAndroid Build Coastguard Worker             auto mountPath = GetFuseMountPathForUser(started_user, stableName);
329*f40fafd4SAndroid Build Coastguard Worker             ForceUnmount(mountPath);
330*f40fafd4SAndroid Build Coastguard Worker             rmdir(mountPath.c_str());
331*f40fafd4SAndroid Build Coastguard Worker         }
332*f40fafd4SAndroid Build Coastguard Worker 
333*f40fafd4SAndroid Build Coastguard Worker         if (UnmountUserFuse(getMountUserId(), getInternalPath(), stableName) != OK) {
334*f40fafd4SAndroid Build Coastguard Worker             PLOG(INFO) << "UnmountUserFuse failed on public fuse volume";
335*f40fafd4SAndroid Build Coastguard Worker             return -errno;
336*f40fafd4SAndroid Build Coastguard Worker         }
337*f40fafd4SAndroid Build Coastguard Worker 
338*f40fafd4SAndroid Build Coastguard Worker         mFuseMounted = false;
339*f40fafd4SAndroid Build Coastguard Worker     }
340*f40fafd4SAndroid Build Coastguard Worker 
341*f40fafd4SAndroid Build Coastguard Worker     ForceUnmount(kAsecPath);
342*f40fafd4SAndroid Build Coastguard Worker 
343*f40fafd4SAndroid Build Coastguard Worker     if (mUseSdcardFs) {
344*f40fafd4SAndroid Build Coastguard Worker         ForceUnmount(mSdcardFsDefault);
345*f40fafd4SAndroid Build Coastguard Worker         ForceUnmount(mSdcardFsRead);
346*f40fafd4SAndroid Build Coastguard Worker         ForceUnmount(mSdcardFsWrite);
347*f40fafd4SAndroid Build Coastguard Worker         ForceUnmount(mSdcardFsFull);
348*f40fafd4SAndroid Build Coastguard Worker 
349*f40fafd4SAndroid Build Coastguard Worker         rmdir(mSdcardFsDefault.c_str());
350*f40fafd4SAndroid Build Coastguard Worker         rmdir(mSdcardFsRead.c_str());
351*f40fafd4SAndroid Build Coastguard Worker         rmdir(mSdcardFsWrite.c_str());
352*f40fafd4SAndroid Build Coastguard Worker         rmdir(mSdcardFsFull.c_str());
353*f40fafd4SAndroid Build Coastguard Worker 
354*f40fafd4SAndroid Build Coastguard Worker         mSdcardFsDefault.clear();
355*f40fafd4SAndroid Build Coastguard Worker         mSdcardFsRead.clear();
356*f40fafd4SAndroid Build Coastguard Worker         mSdcardFsWrite.clear();
357*f40fafd4SAndroid Build Coastguard Worker         mSdcardFsFull.clear();
358*f40fafd4SAndroid Build Coastguard Worker     }
359*f40fafd4SAndroid Build Coastguard Worker 
360*f40fafd4SAndroid Build Coastguard Worker     if (ForceUnmount(mRawPath) != 0){
361*f40fafd4SAndroid Build Coastguard Worker         umount2(mRawPath.c_str(),MNT_DETACH);
362*f40fafd4SAndroid Build Coastguard Worker         PLOG(INFO) << "use umount lazy if force unmount fail";
363*f40fafd4SAndroid Build Coastguard Worker     }
364*f40fafd4SAndroid Build Coastguard Worker     if(rmdir(mRawPath.c_str()) != 0) {
365*f40fafd4SAndroid Build Coastguard Worker         PLOG(INFO) << "rmdir mRawPath=" << mRawPath << " fail";
366*f40fafd4SAndroid Build Coastguard Worker         KillProcessesUsingPath(getPath());
367*f40fafd4SAndroid Build Coastguard Worker     }
368*f40fafd4SAndroid Build Coastguard Worker     mRawPath.clear();
369*f40fafd4SAndroid Build Coastguard Worker 
370*f40fafd4SAndroid Build Coastguard Worker     return OK;
371*f40fafd4SAndroid Build Coastguard Worker }
372*f40fafd4SAndroid Build Coastguard Worker 
doFormat(const std::string & fsType)373*f40fafd4SAndroid Build Coastguard Worker status_t PublicVolume::doFormat(const std::string& fsType) {
374*f40fafd4SAndroid Build Coastguard Worker     bool isVfatSup = vfat::IsSupported();
375*f40fafd4SAndroid Build Coastguard Worker     bool isExfatSup = exfat::IsSupported();
376*f40fafd4SAndroid Build Coastguard Worker     status_t res = OK;
377*f40fafd4SAndroid Build Coastguard Worker 
378*f40fafd4SAndroid Build Coastguard Worker     enum { NONE, VFAT, EXFAT } fsPick = NONE;
379*f40fafd4SAndroid Build Coastguard Worker 
380*f40fafd4SAndroid Build Coastguard Worker     // Resolve auto requests
381*f40fafd4SAndroid Build Coastguard Worker     if (fsType == "auto" && isVfatSup && isExfatSup) {
382*f40fafd4SAndroid Build Coastguard Worker         uint64_t size = 0;
383*f40fafd4SAndroid Build Coastguard Worker 
384*f40fafd4SAndroid Build Coastguard Worker         res = GetBlockDevSize(mDevPath, &size);
385*f40fafd4SAndroid Build Coastguard Worker         if (res != OK) {
386*f40fafd4SAndroid Build Coastguard Worker             LOG(ERROR) << "Couldn't get device size " << mDevPath;
387*f40fafd4SAndroid Build Coastguard Worker             return res;
388*f40fafd4SAndroid Build Coastguard Worker         }
389*f40fafd4SAndroid Build Coastguard Worker 
390*f40fafd4SAndroid Build Coastguard Worker         // If both vfat & exfat are supported use exfat for SDXC (>~32GiB) cards
391*f40fafd4SAndroid Build Coastguard Worker         if (size > 32896LL * 1024 * 1024) {
392*f40fafd4SAndroid Build Coastguard Worker             fsPick = EXFAT;
393*f40fafd4SAndroid Build Coastguard Worker         } else {
394*f40fafd4SAndroid Build Coastguard Worker             fsPick = VFAT;
395*f40fafd4SAndroid Build Coastguard Worker         }
396*f40fafd4SAndroid Build Coastguard Worker     } else if (fsType == "auto" && isExfatSup) {
397*f40fafd4SAndroid Build Coastguard Worker         fsPick = EXFAT;
398*f40fafd4SAndroid Build Coastguard Worker     } else if (fsType == "auto" && isVfatSup) {
399*f40fafd4SAndroid Build Coastguard Worker         fsPick = VFAT;
400*f40fafd4SAndroid Build Coastguard Worker     }
401*f40fafd4SAndroid Build Coastguard Worker 
402*f40fafd4SAndroid Build Coastguard Worker     // Resolve explicit requests
403*f40fafd4SAndroid Build Coastguard Worker     if (fsType == "vfat" && isVfatSup) {
404*f40fafd4SAndroid Build Coastguard Worker         fsPick = VFAT;
405*f40fafd4SAndroid Build Coastguard Worker     } else if (fsType == "exfat" && isExfatSup) {
406*f40fafd4SAndroid Build Coastguard Worker         fsPick = EXFAT;
407*f40fafd4SAndroid Build Coastguard Worker     }
408*f40fafd4SAndroid Build Coastguard Worker 
409*f40fafd4SAndroid Build Coastguard Worker     if (WipeBlockDevice(mDevPath) != OK) {
410*f40fafd4SAndroid Build Coastguard Worker         LOG(WARNING) << getId() << " failed to wipe";
411*f40fafd4SAndroid Build Coastguard Worker     }
412*f40fafd4SAndroid Build Coastguard Worker 
413*f40fafd4SAndroid Build Coastguard Worker     if (fsPick == VFAT) {
414*f40fafd4SAndroid Build Coastguard Worker         res = vfat::Format(mDevPath, 0);
415*f40fafd4SAndroid Build Coastguard Worker     } else if (fsPick == EXFAT) {
416*f40fafd4SAndroid Build Coastguard Worker         res = exfat::Format(mDevPath);
417*f40fafd4SAndroid Build Coastguard Worker     } else {
418*f40fafd4SAndroid Build Coastguard Worker         LOG(ERROR) << "Unsupported filesystem " << fsType;
419*f40fafd4SAndroid Build Coastguard Worker         return -EINVAL;
420*f40fafd4SAndroid Build Coastguard Worker     }
421*f40fafd4SAndroid Build Coastguard Worker 
422*f40fafd4SAndroid Build Coastguard Worker     if (res != OK) {
423*f40fafd4SAndroid Build Coastguard Worker         LOG(ERROR) << getId() << " failed to format";
424*f40fafd4SAndroid Build Coastguard Worker         res = -errno;
425*f40fafd4SAndroid Build Coastguard Worker     }
426*f40fafd4SAndroid Build Coastguard Worker 
427*f40fafd4SAndroid Build Coastguard Worker     return res;
428*f40fafd4SAndroid Build Coastguard Worker }
429*f40fafd4SAndroid Build Coastguard Worker 
430*f40fafd4SAndroid Build Coastguard Worker }  // namespace vold
431*f40fafd4SAndroid Build Coastguard Worker }  // namespace android
432