From 0267bf0e963ecedd01b9fe604a84fca1385dc456 Mon Sep 17 00:00:00 2001 From: Yo Chiang Date: Wed, 21 Oct 2020 22:25:21 +0800 Subject: [PATCH] Enable overlayFS on DSU system Enable overlayFS (adb remount) within DSU only if the DM device scratch_gsi exists. Under DSU mode the backing scratch device of overlayFS must be scratch_gsi. The scratch_gsi partition must be created by gsid on the host system and initialized during first-stage-init. fs_mgr_overlayfs mustn't create any scratch device for DSU, instead it should just check the existence of the dm node and initialize the scratch partition (if any). Bug: 165925766 Test: (In host) adb shell gsi_tool create-partition --partition system \ --size $(du -b system.img | cut -f1) empty(); + *change = false; + return *partition_exists; + } + // Try a physical partition first. *scratch_device = GetPhysicalScratchDevice(); if (!scratch_device->empty() && fs_mgr_rw_access(*scratch_device)) { @@ -1166,12 +1223,8 @@ bool fs_mgr_overlayfs_setup_scratch(const Fstab& fstab, bool* change) { bool fs_mgr_overlayfs_invalid() { if (fs_mgr_overlayfs_valid() == OverlayfsValidResult::kNotSupported) return true; - // in recovery, fastbootd, or gsi mode, not allowed! - if (fs_mgr_access("/system/bin/recovery")) return true; - auto save_errno = errno; - auto ret = android::gsi::IsGsiRunning(); - errno = save_errno; - return ret; + // in recovery or fastbootd, not allowed! + return fs_mgr_in_recovery(); } } // namespace @@ -1314,6 +1367,8 @@ bool fs_mgr_overlayfs_setup(const char* backing, const char* mount_point, bool* return ret; } +// Note: This function never returns the DSU scratch device in recovery or fastbootd, +// because the DSU scratch is created in the first-stage-mount, which is not run in recovery. static bool EnsureScratchMapped(std::string* device, bool* mapped) { *mapped = false; *device = GetBootScratchDevice(); @@ -1368,6 +1423,42 @@ static void UnmapScratchDevice() { DestroyLogicalPartition(android::base::Basename(kScratchMountPoint)); } +#if !defined __ANDROID_RECOVERY__ +// Provide stubs for non-recovery variant. +static void fs_mgr_overlayfs_teardown_dsu(const char*) {} +#else +// Note: This should only be called from recovery or fastbootd. +static void fs_mgr_overlayfs_teardown_dsu(const char* mount_point) { + std::string dsu_slot; + if (!android::gsi::IsGsiInstalled() || !android::gsi::GetActiveDsu(&dsu_slot) || + dsu_slot.empty()) { + // Nothing to do if no DSU installation present. + return; + } + + auto images = IImageManager::Open("dsu/" + dsu_slot, 10s); + if (!images || !images->BackingImageExists(android::gsi::kDsuScratch)) { + // Nothing to do if DSU scratch device doesn't exist. + return; + } + + std::string scratch_device; + images->UnmapImageDevice(android::gsi::kDsuScratch); + if (!images->MapImageDevice(android::gsi::kDsuScratch, 10s, &scratch_device)) { + return; + } + + fs_mgr_overlayfs_umount_scratch(); + if (fs_mgr_overlayfs_mount_scratch(scratch_device, fs_mgr_overlayfs_scratch_mount_type())) { + fs_mgr_overlayfs_teardown_one(kScratchMountPoint, + mount_point ? fs_mgr_mount_point(mount_point) : "", nullptr); + fs_mgr_overlayfs_umount_scratch(); + } + + images->UnmapImageDevice(android::gsi::kDsuScratch); +} +#endif + // Returns false if teardown not permitted, errno set to last error. // If something is altered, set *change. bool fs_mgr_overlayfs_teardown(const char* mount_point, bool* change) { @@ -1385,9 +1476,20 @@ bool fs_mgr_overlayfs_teardown(const char* mount_point, bool* change) { fs_mgr_overlayfs_scratch_mount_type()); } } + bool should_destroy_scratch = false; for (const auto& overlay_mount_point : kOverlayMountPoints) { ret &= fs_mgr_overlayfs_teardown_one( - overlay_mount_point, mount_point ? fs_mgr_mount_point(mount_point) : "", change); + 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()) { + // Note: Reaching here in recovery or fastbootd means that a scratch device + // is mounted and cleaned up. Such scratch device mustn't be the DSU scratch, + // because EnsureScratchMapped() is not allowed to map the DSU scratch in + // recovery. In other words, it is safe to destroy the scratch device here. + 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 @@ -1408,6 +1510,12 @@ bool fs_mgr_overlayfs_teardown(const char* mount_point, bool* change) { if (unmap) { UnmapScratchDevice(); } + + if (fs_mgr_in_recovery()) { + // Destroy DSU overlay if present. + fs_mgr_overlayfs_teardown_dsu(mount_point); + } + return ret; }