Skip to content

Commit dfdffca

Browse files
committed
Vold: support stacking of storage mounts.
Any stacked mounts must appear in vold.fstab with deepest mount points listed last. When mounting a volume, vold will scan for mounts that prefix the desired mount point, and attempt to mount them first. When unmounting a volume, it will scan for other volumes to which the current mount point is a prefix, and unmount them first. System is also permitted to browse (but not read/write) storage mount points, as otherwise Settings->Storage can not report free/used space due to access failure. Change-Id: Id3fd8f9bab5d31084da0c82a478cf9c3bcd6eda3
1 parent 5e994c4 commit dfdffca

File tree

3 files changed

+70
-1
lines changed

3 files changed

+70
-1
lines changed

Volume.cpp

+30-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <dirent.h>
2020
#include <errno.h>
2121
#include <fcntl.h>
22+
#include <unistd.h>
2223

2324
#include <sys/types.h>
2425
#include <sys/stat.h>
@@ -339,13 +340,41 @@ int Volume::mountVol() {
339340
return -1;
340341
}
341342

343+
if (access(getMountpoint(), F_OK)) {
344+
char *myMountpoint = strdup(getMountpoint());
345+
if (!myMountpoint) {
346+
SLOGE("Allocation failure while mounting %s", devicePath);
347+
return -1;
348+
}
349+
if (*myMountpoint) {
350+
if (mDebug) SLOGD("Mount point prepare for \"%s\"", myMountpoint);
351+
char *slash = myMountpoint;
352+
while (slash) {
353+
slash = strchr(slash + 1, '/');
354+
if (slash)
355+
*slash = 0;
356+
if (mDebug) SLOGD("Check existence of %s", myMountpoint);
357+
if (access(myMountpoint, F_OK)) {
358+
if (mDebug) SLOGD("Create %s", myMountpoint);
359+
if (mkdir(myMountpoint, 0555)) {
360+
SLOGE("Failed to create %s", myMountpoint);
361+
return -1;
362+
}
363+
}
364+
if (slash)
365+
*slash = '/';
366+
}
367+
}
368+
free (myMountpoint);
369+
}
370+
342371
/*
343372
* Mount the device on our internal staging mountpoint so we can
344373
* muck with it before exposing it to non priviledged users.
345374
*/
346375
errno = 0;
347376
if (Fat::doMount(devicePath, "/mnt/secure/staging", false, false, false,
348-
1000, 1015, 0702, true)) {
377+
1000, 1015, 0602, true)) {
349378
SLOGE("%s failed to mount (%s)\n", devicePath, strerror(errno));
350379
continue;
351380
}

Volume.h

+8
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#define _VOLUME_H
1919

2020
#include <utils/List.h>
21+
#include <string.h>
2122

2223
class NetlinkEvent;
2324
class VolumeManager;
@@ -68,6 +69,13 @@ class Volume {
6869

6970
const char *getLabel() { return mLabel; }
7071
const char *getMountpoint() { return mMountpoint; }
72+
bool isPrefixOf(Volume *v) {
73+
const char *myMountpoint = getMountpoint();
74+
const char *oMountpoint = v->getMountpoint();
75+
int myLen = strlen(myMountpoint);
76+
return !strncmp(myMountpoint, oMountpoint, myLen) && (myMountpoint[myLen-1] == '/' || oMountpoint[myLen] == '/');
77+
}
78+
7179
int getState() { return mState; }
7280

7381
virtual int handleBlockEvent(NetlinkEvent *evt);

VolumeManager.cpp

+32
Original file line numberDiff line numberDiff line change
@@ -948,12 +948,28 @@ int VolumeManager::mountObb(const char *img, const char *key, int ownerUid) {
948948

949949
int VolumeManager::mountVolume(const char *label) {
950950
Volume *v = lookupVolume(label);
951+
VolumeCollection::iterator it;
951952

952953
if (!v) {
953954
errno = ENOENT;
954955
return -1;
955956
}
956957

958+
if (mDebug) SLOGD("Mounting %s", v->getMountpoint());
959+
for (it = mVolumes->begin(); it != mVolumes->end(); ++it) {
960+
961+
Volume *cur = *it;
962+
const char *mountpoint = cur->getMountpoint();
963+
if (mDebug) SLOGD("checking mountpoint %s", mountpoint);
964+
if (!strcmp(v->getMountpoint(), mountpoint)) continue;
965+
if (cur->isPrefixOf(v) && cur->getState() != Volume::State_Mounted)
966+
{
967+
int tmp_ret = cur->mountVol();
968+
if (tmp_ret < 0)
969+
return tmp_ret;
970+
}
971+
}
972+
957973
return v->mountVol();
958974
}
959975

@@ -1224,6 +1240,7 @@ int VolumeManager::unshareVolume(const char *label, const char *method) {
12241240

12251241
int VolumeManager::unmountVolume(const char *label, bool force) {
12261242
Volume *v = lookupVolume(label);
1243+
VolumeCollection::iterator it;
12271244

12281245
if (!v) {
12291246
errno = ENOENT;
@@ -1242,6 +1259,21 @@ int VolumeManager::unmountVolume(const char *label, bool force) {
12421259
return -1;
12431260
}
12441261

1262+
if (mDebug) SLOGD("Unmounting %s", v->getMountpoint());
1263+
for (it = --(mVolumes->end()); it != mVolumes->end(); it--) {
1264+
Volume *cur = *it;
1265+
const char *mountpoint = cur->getMountpoint();
1266+
if (mDebug) SLOGD("checking mountpoint %s", mountpoint);
1267+
if (!strcmp(v->getMountpoint(), mountpoint)) continue;
1268+
if (v->isPrefixOf(cur) && cur->getState() == Volume::State_Mounted)
1269+
{
1270+
cleanupAsec(cur, force);
1271+
int tmp_ret = cur->unmountVol(force);
1272+
if (tmp_ret < 0)
1273+
return tmp_ret;
1274+
}
1275+
}
1276+
12451277
cleanupAsec(v, force);
12461278

12471279
return v->unmountVol(force);

0 commit comments

Comments
 (0)