Clear bind mounts for public volumes when clone profile stops
Currently, if clone profile gets removed, we don't clear public volume
bind mounts for this profile. This would make subsequent unmounting and
then mounting the public volume again not possible as unmounting the
public volume after stopping clone profile wouldn't be able to clean up
clone profile bind mounts.
This fix tries to clean up clone profile find mounts for public volumes
as soon as the clone profile gets stopped or removed. Hence, subsequent
unmounting and mounting for the volume would succeed normally.
Test: Manual
Bug: 318335297
Bug: 369519866
Flag: EXEMPT bug fix
Change-Id: I32e14e520d742f4294820c1d9d92c2997a36d91a
diff --git a/VolumeManager.cpp b/VolumeManager.cpp
index 657f051..49a8b2b 100644
--- a/VolumeManager.cpp
+++ b/VolumeManager.cpp
@@ -452,36 +452,41 @@
if (mStartedUsers.find(userId) == mStartedUsers.end()) {
createEmulatedVolumesForUser(userId);
- std::list<std::string> public_vols;
- listVolumes(VolumeBase::Type::kPublic, public_vols);
- for (const std::string& id : public_vols) {
- PublicVolume* pvol = static_cast<PublicVolume*>(findVolume(id).get());
- if (pvol->getState() != VolumeBase::State::kMounted) {
- continue;
- }
- if (pvol->isVisible() == 0) {
- continue;
- }
- userid_t mountUserId = pvol->getMountUserId();
- if (userId == mountUserId) {
- // No need to bind mount for the user that owns the mount
- continue;
- }
- if (mountUserId != VolumeManager::Instance()->getSharedStorageUser(userId)) {
- // No need to bind if the user does not share storage with the mount owner
- continue;
- }
- // Create mount directory for the user as there is a chance that no other Volume is
- // mounted for the user (ex: if the user is just started), so /mnt/user/user_id does
- // not exist yet.
- auto mountDirStatus = android::vold::PrepareMountDirForUser(userId);
- if (mountDirStatus != OK) {
- LOG(ERROR) << "Failed to create Mount Directory for user " << userId;
- }
- auto bindMountStatus = pvol->bindMountForUser(userId);
- if (bindMountStatus != OK) {
- LOG(ERROR) << "Bind Mounting Public Volume: " << pvol << " for user: " << userId
- << "Failed. Error: " << bindMountStatus;
+
+ userid_t sharedStorageUserId = VolumeManager::Instance()->getSharedStorageUser(userId);
+ if (sharedStorageUserId != USER_UNKNOWN) {
+ std::list<std::string> public_vols;
+ listVolumes(VolumeBase::Type::kPublic, public_vols);
+ for (const std::string& id : public_vols) {
+ PublicVolume *pvol = static_cast<PublicVolume *>(findVolume(id).get());
+ if (pvol->getState() != VolumeBase::State::kMounted) {
+ continue;
+ }
+ if (pvol->isVisible() == 0) {
+ continue;
+ }
+ userid_t mountUserId = pvol->getMountUserId();
+ if (userId == mountUserId) {
+ // No need to bind mount for the user that owns the mount
+ continue;
+ }
+
+ if (mountUserId != sharedStorageUserId) {
+ // No need to bind if the user does not share storage with the mount owner
+ continue;
+ }
+ // Create mount directory for the user as there is a chance that no other Volume is
+ // mounted for the user (ex: if the user is just started),
+ // so /mnt/user/user_id does not exist yet.
+ auto mountDirStatus = android::vold::PrepareMountDirForUser(userId);
+ if (mountDirStatus != OK) {
+ LOG(ERROR) << "Failed to create Mount Directory for user " << userId;
+ }
+ auto bindMountStatus = pvol->bindMountForUser(userId);
+ if (bindMountStatus != OK) {
+ LOG(ERROR) << "Bind Mounting Public Volume: " << pvol << " for user: " << userId
+ << "Failed. Error: " << bindMountStatus;
+ }
}
}
}
@@ -497,6 +502,36 @@
if (mStartedUsers.find(userId) != mStartedUsers.end()) {
destroyEmulatedVolumesForUser(userId);
+
+ userid_t sharedStorageUserId = VolumeManager::Instance()->getSharedStorageUser(userId);
+ if (sharedStorageUserId != USER_UNKNOWN) {
+ std::list<std::string> public_vols;
+ listVolumes(VolumeBase::Type::kPublic, public_vols);
+ for (const std::string &id: public_vols) {
+ PublicVolume *pvol = static_cast<PublicVolume *>(findVolume(id).get());
+ if (pvol->getState() != VolumeBase::State::kMounted) {
+ continue;
+ }
+ if (pvol->isVisible() == 0) {
+ continue;
+ }
+ userid_t mountUserId = pvol->getMountUserId();
+ if (userId == mountUserId) {
+ // No need to remove bind mount for the user that owns the mount
+ continue;
+ }
+ if (mountUserId != sharedStorageUserId) {
+ // No need to remove bind mount
+ // if the user does not share storage with the mount owner
+ continue;
+ }
+ LOG(INFO) << "Removing Public Volume Bind Mount for: " << userId;
+ auto mountPath = GetFuseMountPathForUser(userId, pvol->getStableName());
+ android::vold::ForceUnmount(mountPath);
+ rmdir(mountPath.c_str());
+ }
+ }
+
}
mStartedUsers.erase(userId);
diff --git a/model/PublicVolume.cpp b/model/PublicVolume.cpp
index 91b1ca2..747598a 100644
--- a/model/PublicVolume.cpp
+++ b/model/PublicVolume.cpp
@@ -88,6 +88,15 @@
return OK;
}
+std::string PublicVolume::getStableName() {
+ // Use UUID as stable name, if available
+ std::string stableName = getId();
+ if (!mFsUuid.empty()) {
+ stableName = mFsUuid;
+ }
+ return stableName;
+}
+
status_t PublicVolume::doCreate() {
return CreateDeviceNode(mDevPath, mDevice);
}
@@ -115,11 +124,7 @@
return -EIO;
}
- // Use UUID as stable name, if available
- std::string stableName = getId();
- if (!mFsUuid.empty()) {
- stableName = mFsUuid;
- }
+ std::string stableName = getStableName();
mRawPath = StringPrintf("/mnt/media_rw/%s", stableName.c_str());
@@ -286,10 +291,7 @@
status_t PublicVolume::bindMountForUser(userid_t user_id) {
userid_t mountUserId = getMountUserId();
- std::string stableName = getId();
- if (!mFsUuid.empty()) {
- stableName = mFsUuid;
- }
+ std::string stableName = getStableName();
LOG(INFO) << "Bind Mounting Public Volume for user: " << user_id
<< ".Mount owner: " << mountUserId;
@@ -310,11 +312,7 @@
KillProcessesUsingPath(getPath());
if (mFuseMounted) {
- // Use UUID as stable name, if available
- std::string stableName = getId();
- if (!mFsUuid.empty()) {
- stableName = mFsUuid;
- }
+ std::string stableName = getStableName();
// Unmount bind mounts for running users
auto vol_manager = VolumeManager::Instance();
diff --git a/model/PublicVolume.h b/model/PublicVolume.h
index ca553b0..5eff35e 100644
--- a/model/PublicVolume.h
+++ b/model/PublicVolume.h
@@ -43,6 +43,7 @@
virtual ~PublicVolume();
status_t bindMountForUser(userid_t user_id);
+ std::string getStableName();
protected:
status_t doCreate() override;