Merge "remount: Remove errno interaction from fs_mgr_overlayfs_teardown."
This commit is contained in:
commit
eec8932c35
5 changed files with 135 additions and 92 deletions
|
|
@ -481,30 +481,35 @@ bool fs_mgr_overlayfs_has_logical(const Fstab& fstab) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void fs_mgr_overlayfs_umount_scratch() {
|
// Returns true if immediate unmount succeeded and the scratch mount point was
|
||||||
// Lazy umount will allow us to move on and possibly later
|
// removed.
|
||||||
// establish a new fresh mount without requiring a reboot should
|
bool fs_mgr_overlayfs_umount_scratch() {
|
||||||
// the developer wish to restart. Old references should melt
|
if (umount(kScratchMountPoint.c_str()) != 0) {
|
||||||
// away or have no data. Main goal is to shut the door on the
|
return false;
|
||||||
// current overrides with an expectation of a subsequent reboot,
|
}
|
||||||
// thus any errors here are ignored.
|
if (rmdir(kScratchMountPoint.c_str()) != 0 && errno != ENOENT) {
|
||||||
umount2(kScratchMountPoint.c_str(), MNT_DETACH);
|
PLOG(ERROR) << "rmdir " << kScratchMountPoint;
|
||||||
LINFO << "umount(" << kScratchMountPoint << ")";
|
}
|
||||||
rmdir(kScratchMountPoint.c_str());
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool fs_mgr_overlayfs_teardown_scratch(const std::string& overlay, bool* change) {
|
OverlayfsTeardownResult fs_mgr_overlayfs_teardown_scratch(const std::string& overlay,
|
||||||
|
bool* change) {
|
||||||
// umount and delete kScratchMountPoint storage if we have logical partitions
|
// umount and delete kScratchMountPoint storage if we have logical partitions
|
||||||
if (overlay != kScratchMountPoint) return true;
|
if (overlay != kScratchMountPoint) {
|
||||||
|
return OverlayfsTeardownResult::Ok;
|
||||||
|
}
|
||||||
|
|
||||||
// Validation check.
|
// Validation check.
|
||||||
if (fs_mgr_is_dsu_running()) {
|
if (fs_mgr_is_dsu_running()) {
|
||||||
LERROR << "Destroying DSU scratch is not allowed.";
|
LERROR << "Destroying DSU scratch is not allowed.";
|
||||||
return false;
|
return OverlayfsTeardownResult::Error;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto save_errno = errno;
|
auto save_errno = errno;
|
||||||
if (fs_mgr_overlayfs_already_mounted(kScratchMountPoint, false)) {
|
|
||||||
|
bool was_mounted = fs_mgr_overlayfs_already_mounted(kScratchMountPoint, false);
|
||||||
|
if (was_mounted) {
|
||||||
fs_mgr_overlayfs_umount_scratch();
|
fs_mgr_overlayfs_umount_scratch();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -512,42 +517,58 @@ bool fs_mgr_overlayfs_teardown_scratch(const std::string& overlay, bool* change)
|
||||||
|
|
||||||
auto images = IImageManager::Open("remount", 10s);
|
auto images = IImageManager::Open("remount", 10s);
|
||||||
if (images && images->BackingImageExists(partition_name)) {
|
if (images && images->BackingImageExists(partition_name)) {
|
||||||
#if defined __ANDROID_RECOVERY__
|
|
||||||
if (!images->DisableImage(partition_name)) {
|
if (!images->DisableImage(partition_name)) {
|
||||||
return false;
|
return OverlayfsTeardownResult::Error;
|
||||||
}
|
}
|
||||||
#else
|
if (was_mounted) {
|
||||||
if (!images->UnmapImageIfExists(partition_name) ||
|
// If overlayfs was mounted, don't bother trying to unmap since
|
||||||
!images->DeleteBackingImage(partition_name)) {
|
// it'll fail and create error spam.
|
||||||
return false;
|
return OverlayfsTeardownResult::Busy;
|
||||||
}
|
}
|
||||||
#endif
|
if (!images->UnmapImageIfExists(partition_name)) {
|
||||||
|
return OverlayfsTeardownResult::Busy;
|
||||||
|
}
|
||||||
|
if (!images->DeleteBackingImage(partition_name)) {
|
||||||
|
return OverlayfsTeardownResult::Busy;
|
||||||
|
}
|
||||||
|
|
||||||
|
// No need to check super partition, if we knew we had a scratch device
|
||||||
|
// in /data.
|
||||||
|
return OverlayfsTeardownResult::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto slot_number = fs_mgr_overlayfs_slot_number();
|
auto slot_number = fs_mgr_overlayfs_slot_number();
|
||||||
auto super_device = fs_mgr_overlayfs_super_device(slot_number);
|
auto super_device = fs_mgr_overlayfs_super_device(slot_number);
|
||||||
if (!fs_mgr_rw_access(super_device)) return true;
|
if (!fs_mgr_rw_access(super_device)) {
|
||||||
|
return OverlayfsTeardownResult::Ok;
|
||||||
|
}
|
||||||
|
|
||||||
auto builder = MetadataBuilder::New(super_device, slot_number);
|
auto builder = MetadataBuilder::New(super_device, slot_number);
|
||||||
if (!builder) {
|
if (!builder) {
|
||||||
errno = save_errno;
|
errno = save_errno;
|
||||||
return true;
|
return OverlayfsTeardownResult::Ok;
|
||||||
}
|
}
|
||||||
if (builder->FindPartition(partition_name) == nullptr) {
|
if (builder->FindPartition(partition_name) == nullptr) {
|
||||||
errno = save_errno;
|
errno = save_errno;
|
||||||
return true;
|
return OverlayfsTeardownResult::Ok;
|
||||||
}
|
}
|
||||||
builder->RemovePartition(partition_name);
|
builder->RemovePartition(partition_name);
|
||||||
auto metadata = builder->Export();
|
auto metadata = builder->Export();
|
||||||
if (metadata && UpdatePartitionTable(super_device, *metadata.get(), slot_number)) {
|
if (metadata && UpdatePartitionTable(super_device, *metadata.get(), slot_number)) {
|
||||||
if (change) *change = true;
|
if (change) *change = true;
|
||||||
if (!DestroyLogicalPartition(partition_name)) return false;
|
if (!DestroyLogicalPartition(partition_name)) {
|
||||||
|
return OverlayfsTeardownResult::Error;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
LERROR << "delete partition " << overlay;
|
LERROR << "delete partition " << overlay;
|
||||||
return false;
|
return OverlayfsTeardownResult::Error;
|
||||||
}
|
}
|
||||||
errno = save_errno;
|
errno = save_errno;
|
||||||
return true;
|
|
||||||
|
if (was_mounted) {
|
||||||
|
return OverlayfsTeardownResult::Busy;
|
||||||
|
}
|
||||||
|
return OverlayfsTeardownResult::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool fs_mgr_overlayfs_teardown_one(const std::string& overlay, const std::string& mount_point,
|
bool fs_mgr_overlayfs_teardown_one(const std::string& overlay, const std::string& mount_point,
|
||||||
|
|
@ -869,17 +890,6 @@ bool fs_mgr_overlayfs_mount_scratch(const std::string& device_path, const std::s
|
||||||
entry.flags = MS_NOATIME | MS_RDONLY;
|
entry.flags = MS_NOATIME | MS_RDONLY;
|
||||||
auto mounted = true;
|
auto mounted = true;
|
||||||
if (!readonly) {
|
if (!readonly) {
|
||||||
if (entry.fs_type == "ext4") {
|
|
||||||
// check if ext4 de-dupe
|
|
||||||
entry.flags |= MS_RDONLY;
|
|
||||||
auto save_errno = errno;
|
|
||||||
mounted = fs_mgr_do_mount_one(entry) == 0;
|
|
||||||
if (mounted) {
|
|
||||||
mounted = !fs_mgr_has_shared_blocks(entry.mount_point, entry.blk_device);
|
|
||||||
fs_mgr_overlayfs_umount_scratch();
|
|
||||||
}
|
|
||||||
errno = save_errno;
|
|
||||||
}
|
|
||||||
entry.flags &= ~MS_RDONLY;
|
entry.flags &= ~MS_RDONLY;
|
||||||
entry.flags |= MS_SYNCHRONOUS;
|
entry.flags |= MS_SYNCHRONOUS;
|
||||||
entry.fs_options = "nodiscard";
|
entry.fs_options = "nodiscard";
|
||||||
|
|
@ -1246,7 +1256,10 @@ bool fs_mgr_overlayfs_setup_scratch(const Fstab& fstab) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// declare it useless, no overrides and no free space
|
// declare it useless, no overrides and no free space
|
||||||
fs_mgr_overlayfs_umount_scratch();
|
if (!fs_mgr_overlayfs_umount_scratch()) {
|
||||||
|
LOG(ERROR) << "Unable to unmount scratch partition";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1548,12 +1561,38 @@ static bool MapDsuScratchDevice(std::string* device) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns false if teardown not permitted, errno set to last error.
|
OverlayfsTeardownResult TeardownMountsAndScratch(const char* mount_point, bool* want_reboot) {
|
||||||
// If something is altered, set *change.
|
bool should_destroy_scratch = false;
|
||||||
bool fs_mgr_overlayfs_teardown(const char* mount_point, bool* change) {
|
auto rv = OverlayfsTeardownResult::Ok;
|
||||||
if (change) *change = false;
|
for (const auto& overlay_mount_point : OverlayMountPoints()) {
|
||||||
auto ret = true;
|
auto ok = fs_mgr_overlayfs_teardown_one(
|
||||||
|
overlay_mount_point, mount_point ? fs_mgr_mount_point(mount_point) : "",
|
||||||
|
want_reboot,
|
||||||
|
overlay_mount_point == kScratchMountPoint ? &should_destroy_scratch : nullptr);
|
||||||
|
if (!ok) {
|
||||||
|
rv = OverlayfsTeardownResult::Error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do not attempt to destroy DSU scratch if within a DSU system,
|
||||||
|
// because DSU scratch partition is managed by gsid.
|
||||||
|
if (should_destroy_scratch && !fs_mgr_is_dsu_running()) {
|
||||||
|
auto rv = fs_mgr_overlayfs_teardown_scratch(kScratchMountPoint, want_reboot);
|
||||||
|
if (rv != OverlayfsTeardownResult::Ok) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// And now that we did what we could, lets inform
|
||||||
|
// caller that there may still be more to do.
|
||||||
|
if (!fs_mgr_boot_completed()) {
|
||||||
|
LOG(ERROR) << "Cannot teardown overlayfs before persistent properties are ready";
|
||||||
|
return OverlayfsTeardownResult::Error;
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns false if teardown not permitted. If something is altered, set *want_reboot.
|
||||||
|
OverlayfsTeardownResult fs_mgr_overlayfs_teardown(const char* mount_point, bool* want_reboot) {
|
||||||
// If scratch exists, but is not mounted, lets gain access to clean
|
// If scratch exists, but is not mounted, lets gain access to clean
|
||||||
// specific override entries.
|
// specific override entries.
|
||||||
auto mount_scratch = false;
|
auto mount_scratch = false;
|
||||||
|
|
@ -1564,34 +1603,15 @@ bool fs_mgr_overlayfs_teardown(const char* mount_point, bool* change) {
|
||||||
fs_mgr_overlayfs_scratch_mount_type());
|
fs_mgr_overlayfs_scratch_mount_type());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bool should_destroy_scratch = false;
|
|
||||||
for (const auto& overlay_mount_point : OverlayMountPoints()) {
|
auto rv = TeardownMountsAndScratch(mount_point, want_reboot);
|
||||||
ret &= fs_mgr_overlayfs_teardown_one(
|
|
||||||
overlay_mount_point, mount_point ? fs_mgr_mount_point(mount_point) : "", change,
|
|
||||||
overlay_mount_point == kScratchMountPoint ? &should_destroy_scratch : nullptr);
|
|
||||||
}
|
|
||||||
// Do not attempt to destroy DSU scratch if within a DSU system,
|
|
||||||
// because DSU scratch partition is managed by gsid.
|
|
||||||
if (should_destroy_scratch && !fs_mgr_is_dsu_running()) {
|
|
||||||
ret &= fs_mgr_overlayfs_teardown_scratch(kScratchMountPoint, change);
|
|
||||||
}
|
|
||||||
if (fs_mgr_overlayfs_valid() == OverlayfsValidResult::kNotSupported) {
|
|
||||||
// After obligatory teardown to make sure everything is clean, but if
|
|
||||||
// we didn't want overlayfs in the first place, we do not want to
|
|
||||||
// waste time on a reboot (or reboot request message).
|
|
||||||
if (change) *change = false;
|
|
||||||
}
|
|
||||||
// And now that we did what we could, lets inform
|
|
||||||
// caller that there may still be more to do.
|
|
||||||
if (!fs_mgr_boot_completed()) {
|
|
||||||
errno = EBUSY;
|
|
||||||
PERROR << "teardown";
|
|
||||||
ret = false;
|
|
||||||
}
|
|
||||||
if (mount_scratch) {
|
if (mount_scratch) {
|
||||||
fs_mgr_overlayfs_umount_scratch();
|
if (!fs_mgr_overlayfs_umount_scratch()) {
|
||||||
|
return OverlayfsTeardownResult::Busy;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool fs_mgr_overlayfs_is_setup() {
|
bool fs_mgr_overlayfs_is_setup() {
|
||||||
|
|
@ -1689,6 +1709,7 @@ void TeardownAllOverlayForMountPoint(const std::string& mount_point) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Note if we just disabled scratch, this mount will fail.
|
||||||
if (auto info = EnsureScratchMapped(); info.has_value()) {
|
if (auto info = EnsureScratchMapped(); info.has_value()) {
|
||||||
// Map scratch device, mount kScratchMountPoint and teardown kScratchMountPoint.
|
// Map scratch device, mount kScratchMountPoint and teardown kScratchMountPoint.
|
||||||
fs_mgr_overlayfs_umount_scratch();
|
fs_mgr_overlayfs_umount_scratch();
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,6 @@ android::fs_mgr::Fstab fs_mgr_overlayfs_candidate_list(const android::fs_mgr::Fs
|
||||||
|
|
||||||
bool fs_mgr_wants_overlayfs(android::fs_mgr::FstabEntry* entry);
|
bool fs_mgr_wants_overlayfs(android::fs_mgr::FstabEntry* entry);
|
||||||
bool fs_mgr_overlayfs_mount_all(android::fs_mgr::Fstab* fstab);
|
bool fs_mgr_overlayfs_mount_all(android::fs_mgr::Fstab* fstab);
|
||||||
bool fs_mgr_overlayfs_teardown(const char* mount_point = nullptr, bool* change = nullptr);
|
|
||||||
bool fs_mgr_overlayfs_is_setup();
|
bool fs_mgr_overlayfs_is_setup();
|
||||||
bool fs_mgr_has_shared_blocks(const std::string& mount_point, const std::string& dev);
|
bool fs_mgr_has_shared_blocks(const std::string& mount_point, const std::string& dev);
|
||||||
bool fs_mgr_overlayfs_already_mounted(const std::string& mount_point, bool overlay_only = true);
|
bool fs_mgr_overlayfs_already_mounted(const std::string& mount_point, bool overlay_only = true);
|
||||||
|
|
@ -42,6 +41,14 @@ std::string fs_mgr_get_context(const std::string& mount_point);
|
||||||
bool fs_mgr_overlayfs_setup(const char* mount_point = nullptr, bool* want_reboot = nullptr,
|
bool fs_mgr_overlayfs_setup(const char* mount_point = nullptr, bool* want_reboot = nullptr,
|
||||||
bool just_disabled_verity = true);
|
bool just_disabled_verity = true);
|
||||||
|
|
||||||
|
enum class OverlayfsTeardownResult {
|
||||||
|
Ok,
|
||||||
|
Busy, // Indicates that overlays are still in use.
|
||||||
|
Error
|
||||||
|
};
|
||||||
|
OverlayfsTeardownResult fs_mgr_overlayfs_teardown(const char* mount_point = nullptr,
|
||||||
|
bool* want_reboot = nullptr);
|
||||||
|
|
||||||
enum class OverlayfsValidResult {
|
enum class OverlayfsValidResult {
|
||||||
kNotSupported = 0,
|
kNotSupported = 0,
|
||||||
kOk,
|
kOk,
|
||||||
|
|
|
||||||
|
|
@ -195,9 +195,14 @@ bool ImageManagerBinder::RemoveAllImages() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ImageManagerBinder::DisableImage(const std::string&) {
|
bool ImageManagerBinder::DisableImage(const std::string& name) {
|
||||||
LOG(ERROR) << __PRETTY_FUNCTION__ << " is not available over binder";
|
auto status = manager_->disableImage(name);
|
||||||
return false;
|
if (!status.isOk()) {
|
||||||
|
LOG(ERROR) << __PRETTY_FUNCTION__
|
||||||
|
<< " binder returned: " << status.exceptionMessage().string();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ImageManagerBinder::RemoveDisabledImages() {
|
bool ImageManagerBinder::RemoveDisabledImages() {
|
||||||
|
|
|
||||||
|
|
@ -112,9 +112,6 @@ class IImageManager {
|
||||||
|
|
||||||
// Mark an image as disabled. This is useful for marking an image as
|
// Mark an image as disabled. This is useful for marking an image as
|
||||||
// will-be-deleted in recovery, since recovery cannot mount /data.
|
// will-be-deleted in recovery, since recovery cannot mount /data.
|
||||||
//
|
|
||||||
// This is not available in binder, since it is intended for recovery.
|
|
||||||
// When binder is available, images can simply be removed.
|
|
||||||
virtual bool DisableImage(const std::string& name) = 0;
|
virtual bool DisableImage(const std::string& name) = 0;
|
||||||
|
|
||||||
// Remove all images that been marked as disabled.
|
// Remove all images that been marked as disabled.
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,33 @@ const bool kAllowDisableVerity = true;
|
||||||
const bool kAllowDisableVerity = false;
|
const bool kAllowDisableVerity = false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static bool SetupOrTeardownOverlayfs(bool enable) {
|
||||||
|
bool want_reboot = false;
|
||||||
|
if (enable) {
|
||||||
|
if (!fs_mgr_overlayfs_setup(nullptr, &want_reboot)) {
|
||||||
|
LOG(ERROR) << "Overlayfs setup failed.";
|
||||||
|
return want_reboot;
|
||||||
|
}
|
||||||
|
if (want_reboot) {
|
||||||
|
printf("enabling overlayfs\n");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
auto rv = fs_mgr_overlayfs_teardown(nullptr, &want_reboot);
|
||||||
|
if (rv == OverlayfsTeardownResult::Error) {
|
||||||
|
LOG(ERROR) << "Overlayfs teardown failed.";
|
||||||
|
return want_reboot;
|
||||||
|
}
|
||||||
|
if (rv == OverlayfsTeardownResult::Busy) {
|
||||||
|
LOG(ERROR) << "Overlayfs is still active until reboot.";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (want_reboot) {
|
||||||
|
printf("disabling overlayfs\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return want_reboot;
|
||||||
|
}
|
||||||
|
|
||||||
/* Helper function to get A/B suffix, if any. If the device isn't
|
/* Helper function to get A/B suffix, if any. If the device isn't
|
||||||
* using A/B the empty string is returned. Otherwise either "_a",
|
* using A/B the empty string is returned. Otherwise either "_a",
|
||||||
* "_b", ... is returned.
|
* "_b", ... is returned.
|
||||||
|
|
@ -79,20 +106,6 @@ bool is_using_avb() {
|
||||||
::exit(1);
|
::exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool overlayfs_setup(bool enable) {
|
|
||||||
auto want_reboot = false;
|
|
||||||
errno = 0;
|
|
||||||
if (enable ? fs_mgr_overlayfs_setup(nullptr, &want_reboot)
|
|
||||||
: fs_mgr_overlayfs_teardown(nullptr, &want_reboot)) {
|
|
||||||
if (want_reboot) {
|
|
||||||
LOG(INFO) << (enable ? "Enabled" : "Disabled") << " overlayfs";
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
LOG(ERROR) << "Failed to " << (enable ? "enable" : "disable") << " overlayfs";
|
|
||||||
}
|
|
||||||
return want_reboot;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct SetVerityStateResult {
|
struct SetVerityStateResult {
|
||||||
bool success = false;
|
bool success = false;
|
||||||
bool want_reboot = false;
|
bool want_reboot = false;
|
||||||
|
|
@ -229,7 +242,7 @@ int main(int argc, char* argv[]) {
|
||||||
// Start a threadpool to service waitForService() callbacks as
|
// Start a threadpool to service waitForService() callbacks as
|
||||||
// fs_mgr_overlayfs_* might call waitForService() to get the image service.
|
// fs_mgr_overlayfs_* might call waitForService() to get the image service.
|
||||||
android::ProcessState::self()->startThreadPool();
|
android::ProcessState::self()->startThreadPool();
|
||||||
want_reboot |= overlayfs_setup(!enable_verity);
|
want_reboot |= SetupOrTeardownOverlayfs(!enable_verity);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (want_reboot) {
|
if (want_reboot) {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue