recovery_utils: add support for unmounting entire volumes

When wiping /system, the partition isn't actually mounted at /system
or / - it's mounted at /mnt/system. This breaks 'format system' from
recovery if the partition has been mounted.

This patch adds an ensure_volume_unmounted function that finds all
mounts of a given device and unmounts them, meaning the device
can be safely formatted.

Change-Id: Id4f727f845308a89e865f1ba60dc284f5ebc66e1
This commit is contained in:
Simon Shields 2019-10-02 00:21:45 +10:00 committed by zlewchan
parent cc8755d97b
commit e8ccb88add
3 changed files with 31 additions and 1 deletions

View file

@ -48,7 +48,11 @@ static bool EraseVolume(const char* volume, RecoveryUI* ui, std::string_view new
ui->Print("Formatting %s...\n", volume);
ensure_path_unmounted(volume);
Volume* vol = volume_for_mount_point(volume);
if (ensure_volume_unmounted(vol->blk_device) == -1) {
PLOG(ERROR) << "Failed to unmount volume!";
return false;
}
int result = format_volume(volume, "", new_fstype);

View file

@ -39,6 +39,10 @@ int ensure_path_mounted_at(const std::string& path, const std::string& mount_poi
// success (volume is unmounted);
int ensure_path_unmounted(const std::string& path);
// Make sure that the volume at 'blk_device' is unmounted.
// Returns 0 on success.
int ensure_volume_unmounted(const std::string& blk_device);
// Reformat the given volume (must be the mount point only, eg
// "/cache"), no paths permitted. Attempts to unmount the volume if
// it is mounted.

View file

@ -24,6 +24,7 @@
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/mount.h>
#include <iostream>
#include <string>
@ -89,6 +90,27 @@ int ensure_path_unmounted(const std::string& path) {
return android::fs_mgr::EnsurePathUnmounted(&fstab, path) ? 0 : -1;
}
int ensure_volume_unmounted(const std::string& blk_device) {
android::fs_mgr::Fstab mounted_fstab;
if (!android::fs_mgr::ReadFstabFromFile("/proc/mounts", &mounted_fstab)) {
LOG(ERROR) << "Failed to read /proc/mounts";
return -1;
}
/* find any entries with the volume */
for (auto& entry : mounted_fstab) {
if (entry.blk_device == blk_device) {
int result = umount(entry.mount_point.c_str());
if (result == -1) {
LOG(ERROR) << "Failed to unmount " << blk_device << " from " << entry.mount_point << ": "
<< errno;
return -1;
}
}
}
return 0;
}
static int exec_cmd(const std::vector<std::string>& args) {
CHECK(!args.empty());
auto argv = StringVectorToNullTerminatedArray(args);