Conditionally use sdcardfs.

In preparation of sdcardfs going away on devices launching with R,
conditionally use it.

Bug: 146419093
Test: cuttlefish with sdcardfs, cuttlefish without sdcardfs but with
FUSE
Change-Id: I2c1d4b428dcb43c3fd274dde84d5088984161993
This commit is contained in:
Martijn Coenen 2020-01-06 09:48:14 +01:00
parent cf5916f3fa
commit 86f21a2211
5 changed files with 114 additions and 85 deletions

View file

@ -1017,9 +1017,6 @@ status_t MountUserFuse(userid_t user_id, const std::string& absolute_lower_path,
std::string pass_through_path( std::string pass_through_path(
StringPrintf("%s/%s", pre_pass_through_path.c_str(), relative_upper_path.c_str())); StringPrintf("%s/%s", pre_pass_through_path.c_str(), relative_upper_path.c_str()));
std::string sdcardfs_path(
StringPrintf("/mnt/runtime/full/%s", relative_upper_path.c_str()));
// Create directories. // Create directories.
auto result = PrepareDir(pre_fuse_path, 0700, AID_ROOT, AID_ROOT); auto result = PrepareDir(pre_fuse_path, 0700, AID_ROOT, AID_ROOT);
if (result != android::OK) { if (result != android::OK) {
@ -1081,8 +1078,16 @@ status_t MountUserFuse(userid_t user_id, const std::string& absolute_lower_path,
return -errno; return -errno;
} }
LOG(INFO) << "Bind mounting " << sdcardfs_path << " to " << pass_through_path; if (IsFilesystemSupported("sdcardfs")) {
return BindMount(sdcardfs_path, pass_through_path); std::string sdcardfs_path(
StringPrintf("/mnt/runtime/full/%s", relative_upper_path.c_str()));
LOG(INFO) << "Bind mounting " << sdcardfs_path << " to " << pass_through_path;
return BindMount(sdcardfs_path, pass_through_path);
} else {
LOG(INFO) << "Bind mounting " << absolute_lower_path << " to " << pass_through_path;
return BindMount(absolute_lower_path, pass_through_path);
}
} }
status_t UnmountUserFuse(userid_t user_id, const std::string& absolute_lower_path, status_t UnmountUserFuse(userid_t user_id, const std::string& absolute_lower_path,

View file

@ -48,6 +48,7 @@ EmulatedVolume::EmulatedVolume(const std::string& rawPath, int userId)
mRawPath = rawPath; mRawPath = rawPath;
mLabel = "emulated"; mLabel = "emulated";
mFuseMounted = false; mFuseMounted = false;
mUseSdcardFs = IsFilesystemSupported("sdcardfs");
} }
EmulatedVolume::EmulatedVolume(const std::string& rawPath, dev_t device, const std::string& fsUuid, EmulatedVolume::EmulatedVolume(const std::string& rawPath, dev_t device, const std::string& fsUuid,
@ -57,6 +58,7 @@ EmulatedVolume::EmulatedVolume(const std::string& rawPath, dev_t device, const s
mRawPath = rawPath; mRawPath = rawPath;
mLabel = fsUuid; mLabel = fsUuid;
mFuseMounted = false; mFuseMounted = false;
mUseSdcardFs = IsFilesystemSupported("sdcardfs");
} }
EmulatedVolume::~EmulatedVolume() {} EmulatedVolume::~EmulatedVolume() {}
@ -71,18 +73,23 @@ std::string EmulatedVolume::getLabel() {
} }
} }
static status_t mountFuseBindMounts(int userId, const std::string& label) { status_t EmulatedVolume::mountFuseBindMounts() {
// TODO(b/134706060) we don't actually want to mount the "write" view by std::string androidSource;
// default, since it gives write access to all OBB dirs. std::string label = getLabel();
std::string androidSource( int userId = getMountUserId();
StringPrintf("/mnt/runtime/default/%s/%d/Android", label.c_str(), userId));
if (mUseSdcardFs) {
androidSource = StringPrintf("/mnt/runtime/default/%s/%d/Android", label.c_str(), userId);
} else {
androidSource = StringPrintf("/%s/%d/Android", mRawPath.c_str(), userId);
}
std::string androidTarget( std::string androidTarget(
StringPrintf("/mnt/user/%d/%s/%d/Android", userId, label.c_str(), userId)); StringPrintf("/mnt/user/%d/%s/%d/Android", userId, label.c_str(), userId));
if (access(androidSource.c_str(), F_OK) != 0) { if (access(androidSource.c_str(), F_OK) != 0) {
// Android path may not exist yet if users has just been created; create it on // Android path may not exist yet if users has just been created; create it on
// the lower fs. // the lower fs.
if (fs_prepare_dir(androidSource.c_str(), 0771, AID_ROOT, AID_ROOT) != 0) { if (fs_prepare_dir(androidSource.c_str(), 0771, AID_MEDIA_RW, AID_MEDIA_RW) != 0) {
PLOG(ERROR) << "Failed to create " << androidSource; PLOG(ERROR) << "Failed to create " << androidSource;
return -errno; return -errno;
} }
@ -97,7 +104,10 @@ static status_t mountFuseBindMounts(int userId, const std::string& label) {
return OK; return OK;
} }
static status_t unmountFuseBindMounts(int userId, const std::string& label) { status_t EmulatedVolume::unmountFuseBindMounts() {
std::string label = getLabel();
int userId = getMountUserId();
std::string androidTarget( std::string androidTarget(
StringPrintf("/mnt/user/%d/%s/%d/Android", userId, label.c_str(), userId)); StringPrintf("/mnt/user/%d/%s/%d/Android", userId, label.c_str(), userId));
@ -137,7 +147,7 @@ status_t EmulatedVolume::doMount() {
// Mount sdcardfs regardless of FUSE, since we need it to bind-mount on top of the // Mount sdcardfs regardless of FUSE, since we need it to bind-mount on top of the
// FUSE volume for various reasons. // FUSE volume for various reasons.
if (getMountUserId() == 0) { if (mUseSdcardFs && getMountUserId() == 0) {
LOG(INFO) << "Executing sdcardfs"; LOG(INFO) << "Executing sdcardfs";
int sdcardFsPid; int sdcardFsPid;
if (!(sdcardFsPid = fork())) { if (!(sdcardFsPid = fork())) {
@ -203,7 +213,7 @@ status_t EmulatedVolume::doMount() {
} }
// Only do the bind-mounts when we know for sure the FUSE daemon can resolve the path. // Only do the bind-mounts when we know for sure the FUSE daemon can resolve the path.
return mountFuseBindMounts(user_id, label); return mountFuseBindMounts();
} }
return OK; return OK;
@ -231,7 +241,7 @@ status_t EmulatedVolume::doUnmount() {
// Ignoring unmount return status because we do want to try to unmount // Ignoring unmount return status because we do want to try to unmount
// the rest cleanly. // the rest cleanly.
unmountFuseBindMounts(userId, label); unmountFuseBindMounts();
if (UnmountUserFuse(userId, getInternalPath(), label) != OK) { if (UnmountUserFuse(userId, getInternalPath(), label) != OK) {
PLOG(INFO) << "UnmountUserFuse failed on emulated fuse volume"; PLOG(INFO) << "UnmountUserFuse failed on emulated fuse volume";
return -errno; return -errno;
@ -239,7 +249,7 @@ status_t EmulatedVolume::doUnmount() {
mFuseMounted = false; mFuseMounted = false;
} }
if (getMountUserId() != 0) { if (getMountUserId() != 0 || !mUseSdcardFs) {
// For sdcardfs, only unmount for user 0, since user 0 will always be running // For sdcardfs, only unmount for user 0, since user 0 will always be running
// and the paths don't change for different users. // and the paths don't change for different users.
return OK; return OK;

View file

@ -46,6 +46,9 @@ class EmulatedVolume : public VolumeBase {
status_t doUnmount() override; status_t doUnmount() override;
private: private:
status_t mountFuseBindMounts();
status_t unmountFuseBindMounts();
std::string getLabel(); std::string getLabel();
std::string mRawPath; std::string mRawPath;
std::string mLabel; std::string mLabel;
@ -58,6 +61,9 @@ class EmulatedVolume : public VolumeBase {
/* Whether we mounted FUSE for this volume */ /* Whether we mounted FUSE for this volume */
bool mFuseMounted; bool mFuseMounted;
/* Whether to use sdcardfs for this volume */
bool mUseSdcardFs;
DISALLOW_COPY_AND_ASSIGN(EmulatedVolume); DISALLOW_COPY_AND_ASSIGN(EmulatedVolume);
}; };

View file

@ -51,6 +51,7 @@ PublicVolume::PublicVolume(dev_t device) : VolumeBase(Type::kPublic), mDevice(de
setId(StringPrintf("public:%u,%u", major(device), minor(device))); setId(StringPrintf("public:%u,%u", major(device), minor(device)));
mDevPath = StringPrintf("/dev/block/vold/%s", getId().c_str()); mDevPath = StringPrintf("/dev/block/vold/%s", getId().c_str());
mFuseMounted = false; mFuseMounted = false;
mUseSdcardFs = IsFilesystemSupported("sdcardfs");
} }
PublicVolume::~PublicVolume() {} PublicVolume::~PublicVolume() {}
@ -161,67 +162,69 @@ status_t PublicVolume::doMount() {
return OK; return OK;
} }
if (fs_prepare_dir(mSdcardFsDefault.c_str(), 0700, AID_ROOT, AID_ROOT) || if (mUseSdcardFs) {
fs_prepare_dir(mSdcardFsRead.c_str(), 0700, AID_ROOT, AID_ROOT) || if (fs_prepare_dir(mSdcardFsDefault.c_str(), 0700, AID_ROOT, AID_ROOT) ||
fs_prepare_dir(mSdcardFsWrite.c_str(), 0700, AID_ROOT, AID_ROOT) || fs_prepare_dir(mSdcardFsRead.c_str(), 0700, AID_ROOT, AID_ROOT) ||
fs_prepare_dir(mSdcardFsFull.c_str(), 0700, AID_ROOT, AID_ROOT)) { fs_prepare_dir(mSdcardFsWrite.c_str(), 0700, AID_ROOT, AID_ROOT) ||
PLOG(ERROR) << getId() << " failed to create sdcardfs mount points"; fs_prepare_dir(mSdcardFsFull.c_str(), 0700, AID_ROOT, AID_ROOT)) {
return -errno; PLOG(ERROR) << getId() << " failed to create sdcardfs mount points";
} return -errno;
dev_t before = GetDevice(mSdcardFsFull);
int sdcardFsPid;
if (!(sdcardFsPid = fork())) {
if (getMountFlags() & MountFlags::kPrimary) {
// clang-format off
if (execl(kSdcardFsPath, kSdcardFsPath,
"-u", "1023", // AID_MEDIA_RW
"-g", "1023", // AID_MEDIA_RW
"-U", std::to_string(getMountUserId()).c_str(),
"-w",
mRawPath.c_str(),
stableName.c_str(),
NULL)) {
// clang-format on
PLOG(ERROR) << "Failed to exec";
}
} else {
// clang-format off
if (execl(kSdcardFsPath, kSdcardFsPath,
"-u", "1023", // AID_MEDIA_RW
"-g", "1023", // AID_MEDIA_RW
"-U", std::to_string(getMountUserId()).c_str(),
mRawPath.c_str(),
stableName.c_str(),
NULL)) {
// clang-format on
PLOG(ERROR) << "Failed to exec";
}
} }
LOG(ERROR) << "sdcardfs exiting"; dev_t before = GetDevice(mSdcardFsFull);
_exit(1);
}
if (sdcardFsPid == -1) { int sdcardFsPid;
PLOG(ERROR) << getId() << " failed to fork"; if (!(sdcardFsPid = fork())) {
return -errno; if (getMountFlags() & MountFlags::kPrimary) {
} // clang-format off
if (execl(kSdcardFsPath, kSdcardFsPath,
"-u", "1023", // AID_MEDIA_RW
"-g", "1023", // AID_MEDIA_RW
"-U", std::to_string(getMountUserId()).c_str(),
"-w",
mRawPath.c_str(),
stableName.c_str(),
NULL)) {
// clang-format on
PLOG(ERROR) << "Failed to exec";
}
} else {
// clang-format off
if (execl(kSdcardFsPath, kSdcardFsPath,
"-u", "1023", // AID_MEDIA_RW
"-g", "1023", // AID_MEDIA_RW
"-U", std::to_string(getMountUserId()).c_str(),
mRawPath.c_str(),
stableName.c_str(),
NULL)) {
// clang-format on
PLOG(ERROR) << "Failed to exec";
}
}
nsecs_t start = systemTime(SYSTEM_TIME_BOOTTIME); LOG(ERROR) << "sdcardfs exiting";
while (before == GetDevice(mSdcardFsFull)) { _exit(1);
LOG(DEBUG) << "Waiting for sdcardfs to spin up...";
usleep(50000); // 50ms
nsecs_t now = systemTime(SYSTEM_TIME_BOOTTIME);
if (nanoseconds_to_milliseconds(now - start) > 5000) {
LOG(WARNING) << "Timed out while waiting for sdcardfs to spin up";
return -ETIMEDOUT;
} }
if (sdcardFsPid == -1) {
PLOG(ERROR) << getId() << " failed to fork";
return -errno;
}
nsecs_t start = systemTime(SYSTEM_TIME_BOOTTIME);
while (before == GetDevice(mSdcardFsFull)) {
LOG(DEBUG) << "Waiting for sdcardfs to spin up...";
usleep(50000); // 50ms
nsecs_t now = systemTime(SYSTEM_TIME_BOOTTIME);
if (nanoseconds_to_milliseconds(now - start) > 5000) {
LOG(WARNING) << "Timed out while waiting for sdcardfs to spin up";
return -ETIMEDOUT;
}
}
/* sdcardfs will have exited already. The filesystem will still be running */
TEMP_FAILURE_RETRY(waitpid(sdcardFsPid, nullptr, 0));
} }
/* sdcardfs will have exited already. The filesystem will still be running */
TEMP_FAILURE_RETRY(waitpid(sdcardFsPid, nullptr, 0));
bool isFuse = base::GetBoolProperty(kPropFuse, false); bool isFuse = base::GetBoolProperty(kPropFuse, false);
if (isFuse) { if (isFuse) {
@ -275,22 +278,24 @@ status_t PublicVolume::doUnmount() {
ForceUnmount(kAsecPath); ForceUnmount(kAsecPath);
ForceUnmount(mSdcardFsDefault); if (mUseSdcardFs) {
ForceUnmount(mSdcardFsRead); ForceUnmount(mSdcardFsDefault);
ForceUnmount(mSdcardFsWrite); ForceUnmount(mSdcardFsRead);
ForceUnmount(mSdcardFsFull); ForceUnmount(mSdcardFsWrite);
ForceUnmount(mSdcardFsFull);
rmdir(mSdcardFsDefault.c_str());
rmdir(mSdcardFsRead.c_str());
rmdir(mSdcardFsWrite.c_str());
rmdir(mSdcardFsFull.c_str());
mSdcardFsDefault.clear();
mSdcardFsRead.clear();
mSdcardFsWrite.clear();
mSdcardFsFull.clear();
}
ForceUnmount(mRawPath); ForceUnmount(mRawPath);
rmdir(mSdcardFsDefault.c_str());
rmdir(mSdcardFsRead.c_str());
rmdir(mSdcardFsWrite.c_str());
rmdir(mSdcardFsFull.c_str());
rmdir(mRawPath.c_str()); rmdir(mRawPath.c_str());
mSdcardFsDefault.clear();
mSdcardFsRead.clear();
mSdcardFsWrite.clear();
mSdcardFsFull.clear();
mRawPath.clear(); mRawPath.clear();
return OK; return OK;

View file

@ -68,6 +68,9 @@ class PublicVolume : public VolumeBase {
/* Whether we mounted FUSE for this volume */ /* Whether we mounted FUSE for this volume */
bool mFuseMounted; bool mFuseMounted;
/* Whether to use sdcardfs for this volume */
bool mUseSdcardFs;
/* Filesystem type */ /* Filesystem type */
std::string mFsType; std::string mFsType;
/* Filesystem UUID */ /* Filesystem UUID */