otautil: 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
diff --git a/install/wipe_data.cpp b/install/wipe_data.cpp
index 765a815..ed67207 100644
--- a/install/wipe_data.cpp
+++ b/install/wipe_data.cpp
@@ -52,7 +52,11 @@
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;
if (is_data && convert_fbe) {
diff --git a/otautil/include/otautil/roots.h b/otautil/include/otautil/roots.h
index 482f3d0..670bcbe 100644
--- a/otautil/include/otautil/roots.h
+++ b/otautil/include/otautil/roots.h
@@ -39,6 +39,10 @@
// 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.
diff --git a/otautil/roots.cpp b/otautil/roots.cpp
index 815d644..c5ca476 100644
--- a/otautil/roots.cpp
+++ b/otautil/roots.cpp
@@ -88,6 +88,27 @@
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);