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