Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 81f13855 authored by Yifan Hong's avatar Yifan Hong
Browse files

init: add umount_all builtin.

umount_all is the cleanup step for mount_all.

In particular, the mount_all builtin creates a verity device,
'postinstall-verity', for the following line:

system /postinstall ... ... slotselect_other,logical,avb_keys=...

cppreopt umounts /postinstall but doesn't destroy the postinstall-verity
device, causing OTA to fail (because it cannot destroy the
system_[other] device). umount_all also destroy the verity device.

Note that mount_all does not map system_[other]; it is mapped by
first stage init. Hence, umount_all doesn't destroy it either. The OTA
client is reponsible for unmapping the device itself.

Bug: 129988285
Test: flash, boot, then check `dmctl list devices`, then OTA

Change-Id: Id3ab65b3860b6ea6cfec310ab13652009c81f415
parent e5c4d62b
Loading
Loading
Loading
Loading
+40 −0
Original line number Diff line number Diff line
@@ -1268,6 +1268,46 @@ int fs_mgr_mount_all(Fstab* fstab, int mount_mode) {
    }
}

int fs_mgr_umount_all(android::fs_mgr::Fstab* fstab) {
    AvbUniquePtr avb_handle(nullptr);
    int ret = FsMgrUmountStatus::SUCCESS;
    for (auto& current_entry : *fstab) {
        if (!IsMountPointMounted(current_entry.mount_point)) {
            continue;
        }

        if (umount(current_entry.mount_point.c_str()) == -1) {
            PERROR << "Failed to umount " << current_entry.mount_point;
            ret |= FsMgrUmountStatus::ERROR_UMOUNT;
            continue;
        }

        if (current_entry.fs_mgr_flags.logical) {
            if (!fs_mgr_update_logical_partition(&current_entry)) {
                LERROR << "Could not get logical partition blk_device, skipping!";
                ret |= FsMgrUmountStatus::ERROR_DEVICE_MAPPER;
                continue;
            }
        }

        if (current_entry.fs_mgr_flags.avb || !current_entry.avb_keys.empty()) {
            if (!AvbHandle::TearDownAvbHashtree(&current_entry, true /* wait */)) {
                LERROR << "Failed to tear down AVB on mount point: " << current_entry.mount_point;
                ret |= FsMgrUmountStatus::ERROR_VERITY;
                continue;
            }
        } else if ((current_entry.fs_mgr_flags.verify)) {
            if (!fs_mgr_teardown_verity(&current_entry, true /* wait */)) {
                LERROR << "Failed to tear down verified partition on mount point: "
                       << current_entry.mount_point;
                ret |= FsMgrUmountStatus::ERROR_VERITY;
                continue;
            }
        }
    }
    return ret;
}

// wrapper to __mount() and expects a fully prepared fstab_rec,
// unlike fs_mgr_do_mount which does more things with avb / verity etc.
int fs_mgr_do_mount_one(const FstabEntry& entry, const std::string& mount_point) {
+8 −1
Original line number Diff line number Diff line
@@ -193,7 +193,7 @@ bool CreateLogicalPartition(const std::string& block_device, uint32_t metadata_s
                                  timeout_ms, path);
}

bool DestroyLogicalPartition(const std::string& name, const std::chrono::milliseconds& timeout_ms) {
bool UnmapDevice(const std::string& name, const std::chrono::milliseconds& timeout_ms) {
    DeviceMapper& dm = DeviceMapper::Instance();
    std::string path;
    if (timeout_ms > std::chrono::milliseconds::zero()) {
@@ -206,6 +206,13 @@ bool DestroyLogicalPartition(const std::string& name, const std::chrono::millise
        LERROR << "Timed out waiting for device path to unlink: " << path;
        return false;
    }
    return true;
}

bool DestroyLogicalPartition(const std::string& name, const std::chrono::milliseconds& timeout_ms) {
    if (!UnmapDevice(name, timeout_ms)) {
        return false;
    }
    LINFO << "Unmapped logical partition " << name;
    return true;
}
+8 −0
Original line number Diff line number Diff line
@@ -103,3 +103,11 @@ int load_verity_state(const android::fs_mgr::FstabEntry& entry, int* mode);

bool fs_mgr_is_ext4(const std::string& blk_device);
bool fs_mgr_is_f2fs(const std::string& blk_device);

bool fs_mgr_teardown_verity(android::fs_mgr::FstabEntry* fstab, bool wait);

namespace android {
namespace fs_mgr {
bool UnmapDevice(const std::string& name, const std::chrono::milliseconds& timeout_ms);
}  // namespace fs_mgr
}  // namespace android
+10 −0
Original line number Diff line number Diff line
@@ -44,6 +44,7 @@
#include "fec/io.h"

#include "fs_mgr.h"
#include "fs_mgr_dm_linear.h"
#include "fs_mgr_priv.h"

// Realistically, this file should be part of the android::fs_mgr namespace;
@@ -882,3 +883,12 @@ out:

    return retval;
}

bool fs_mgr_teardown_verity(FstabEntry* entry, bool wait) {
    const std::string mount_point(basename(entry->mount_point.c_str()));
    if (!android::fs_mgr::UnmapDevice(mount_point, wait ? 1000ms : 0ms)) {
        return false;
    }
    LINFO << "Unmapped verity device " << mount_point;
    return true;
}
+11 −0
Original line number Diff line number Diff line
@@ -93,3 +93,14 @@ int fs_mgr_setup_verity(android::fs_mgr::FstabEntry* fstab, bool wait_for_verity
// specified, the super partition for the corresponding metadata slot will be
// returned. Otherwise, it will use the current slot.
std::string fs_mgr_get_super_partition_name(int slot = -1);

enum FsMgrUmountStatus : int {
    SUCCESS = 0,
    ERROR_UNKNOWN = 1 << 0,
    ERROR_UMOUNT = 1 << 1,
    ERROR_VERITY = 1 << 2,
    ERROR_DEVICE_MAPPER = 1 << 3,
};
// fs_mgr_umount_all() is the reverse of fs_mgr_mount_all. In particular,
// it destroys verity devices from device mapper after the device is unmounted.
int fs_mgr_umount_all(android::fs_mgr::Fstab* fstab);
Loading