fastbootd: Remove all scratch partitions on update-super.
This ensures that the dynamic "scratch" partition is removed when doing a flashall operation. If "scratch" is on /data, disable the partition. Add IsImageDisabled to ImageManager so EnsureScratchMapped can skip mapping it. Also, fix "scratch" not getting unmapped if on /data. Bug: 205987817 Test: adb remount adb sync adb reboot fastboot fastboot flashall --skip-reboot # no errors Test: adb-remount-test.sh Change-Id: I4b9702e1dac15fb663635506fb50a8274e1e10d1
This commit is contained in:
parent
78b86ae297
commit
982c3410c7
7 changed files with 101 additions and 29 deletions
|
@ -186,6 +186,11 @@ int Flash(FastbootDevice* device, const std::string& partition_name) {
|
|||
return result;
|
||||
}
|
||||
|
||||
static void RemoveScratchPartition() {
|
||||
AutoMountMetadata mount_metadata;
|
||||
android::fs_mgr::TeardownAllOverlayForMountPoint();
|
||||
}
|
||||
|
||||
bool UpdateSuper(FastbootDevice* device, const std::string& super_name, bool wipe) {
|
||||
std::vector<char> data = std::move(device->download_data());
|
||||
if (data.empty()) {
|
||||
|
@ -218,7 +223,7 @@ bool UpdateSuper(FastbootDevice* device, const std::string& super_name, bool wip
|
|||
if (!FlashPartitionTable(super_name, *new_metadata.get())) {
|
||||
return device->WriteFail("Unable to flash new partition table");
|
||||
}
|
||||
android::fs_mgr::TeardownAllOverlayForMountPoint();
|
||||
RemoveScratchPartition();
|
||||
sync();
|
||||
return device->WriteOkay("Successfully flashed partition table");
|
||||
}
|
||||
|
@ -262,7 +267,7 @@ bool UpdateSuper(FastbootDevice* device, const std::string& super_name, bool wip
|
|||
if (!UpdateAllPartitionMetadata(device, super_name, *new_metadata.get())) {
|
||||
return device->WriteFail("Unable to write new partition table");
|
||||
}
|
||||
android::fs_mgr::TeardownAllOverlayForMountPoint();
|
||||
RemoveScratchPartition();
|
||||
sync();
|
||||
return device->WriteOkay("Successfully updated partition table");
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
@ -1396,18 +1397,35 @@ bool fs_mgr_overlayfs_setup(const char* backing, const char* mount_point, bool*
|
|||
return ret;
|
||||
}
|
||||
|
||||
struct MapInfo {
|
||||
// If set, partition is owned by ImageManager.
|
||||
std::unique_ptr<IImageManager> images;
|
||||
// If set, and images is null, this is a DAP partition.
|
||||
std::string name;
|
||||
// If set, and images and name are empty, this is a non-dynamic partition.
|
||||
std::string device;
|
||||
|
||||
MapInfo() = default;
|
||||
MapInfo(MapInfo&&) = default;
|
||||
~MapInfo() {
|
||||
if (images) {
|
||||
images->UnmapImageDevice(name);
|
||||
} else if (!name.empty()) {
|
||||
DestroyLogicalPartition(name);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 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();
|
||||
if (!device->empty()) {
|
||||
return true;
|
||||
static std::optional<MapInfo> EnsureScratchMapped() {
|
||||
MapInfo info;
|
||||
info.device = GetBootScratchDevice();
|
||||
if (!info.device.empty()) {
|
||||
return {std::move(info)};
|
||||
}
|
||||
|
||||
if (!fs_mgr_in_recovery()) {
|
||||
errno = EINVAL;
|
||||
return false;
|
||||
return {};
|
||||
}
|
||||
|
||||
auto partition_name = android::base::Basename(kScratchMountPoint);
|
||||
|
@ -1417,11 +1435,15 @@ static bool EnsureScratchMapped(std::string* device, bool* mapped) {
|
|||
// would otherwise always be mapped.
|
||||
auto images = IImageManager::Open("remount", 10s);
|
||||
if (images && images->BackingImageExists(partition_name)) {
|
||||
if (!images->MapImageDevice(partition_name, 10s, device)) {
|
||||
return false;
|
||||
if (images->IsImageDisabled(partition_name)) {
|
||||
return {};
|
||||
}
|
||||
*mapped = true;
|
||||
return true;
|
||||
if (!images->MapImageDevice(partition_name, 10s, &info.device)) {
|
||||
return {};
|
||||
}
|
||||
info.name = partition_name;
|
||||
info.images = std::move(images);
|
||||
return {std::move(info)};
|
||||
}
|
||||
|
||||
// Avoid uart spam by first checking for a scratch partition.
|
||||
|
@ -1429,12 +1451,12 @@ static bool EnsureScratchMapped(std::string* device, bool* mapped) {
|
|||
auto super_device = fs_mgr_overlayfs_super_device(metadata_slot);
|
||||
auto metadata = ReadCurrentMetadata(super_device);
|
||||
if (!metadata) {
|
||||
return false;
|
||||
return {};
|
||||
}
|
||||
|
||||
auto partition = FindPartition(*metadata.get(), partition_name);
|
||||
if (!partition) {
|
||||
return false;
|
||||
return {};
|
||||
}
|
||||
|
||||
CreateLogicalPartitionParams params = {
|
||||
|
@ -1444,11 +1466,11 @@ static bool EnsureScratchMapped(std::string* device, bool* mapped) {
|
|||
.force_writable = true,
|
||||
.timeout_ms = 10s,
|
||||
};
|
||||
if (!CreateLogicalPartition(params, device)) {
|
||||
return false;
|
||||
if (!CreateLogicalPartition(params, &info.device)) {
|
||||
return {};
|
||||
}
|
||||
*mapped = true;
|
||||
return true;
|
||||
info.name = partition_name;
|
||||
return {std::move(info)};
|
||||
}
|
||||
|
||||
// This should only be reachable in recovery, where DSU scratch is not
|
||||
|
@ -1602,26 +1624,35 @@ void TeardownAllOverlayForMountPoint(const std::string& mount_point) {
|
|||
fs_mgr_overlayfs_teardown_one(overlay_mount_point, teardown_dir, ignore_change);
|
||||
}
|
||||
|
||||
// Map scratch device, mount kScratchMountPoint and teardown kScratchMountPoint.
|
||||
bool mapped = false;
|
||||
std::string scratch_device;
|
||||
if (EnsureScratchMapped(&scratch_device, &mapped)) {
|
||||
if (mount_point.empty()) {
|
||||
// Throw away the entire partition.
|
||||
auto partition_name = android::base::Basename(kScratchMountPoint);
|
||||
auto images = IImageManager::Open("remount", 10s);
|
||||
if (images && images->BackingImageExists(partition_name)) {
|
||||
if (images->DisableImage(partition_name)) {
|
||||
LOG(INFO) << "Disabled scratch partition for: " << kScratchMountPoint;
|
||||
} else {
|
||||
LOG(ERROR) << "Unable to disable scratch partition for " << kScratchMountPoint;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (auto info = EnsureScratchMapped(); info.has_value()) {
|
||||
// Map scratch device, mount kScratchMountPoint and teardown kScratchMountPoint.
|
||||
fs_mgr_overlayfs_umount_scratch();
|
||||
if (fs_mgr_overlayfs_mount_scratch(scratch_device, fs_mgr_overlayfs_scratch_mount_type())) {
|
||||
if (fs_mgr_overlayfs_mount_scratch(info->device, fs_mgr_overlayfs_scratch_mount_type())) {
|
||||
bool should_destroy_scratch = false;
|
||||
fs_mgr_overlayfs_teardown_one(kScratchMountPoint, teardown_dir, ignore_change,
|
||||
&should_destroy_scratch);
|
||||
fs_mgr_overlayfs_umount_scratch();
|
||||
if (should_destroy_scratch) {
|
||||
fs_mgr_overlayfs_teardown_scratch(kScratchMountPoint, nullptr);
|
||||
}
|
||||
fs_mgr_overlayfs_umount_scratch();
|
||||
}
|
||||
if (mapped) {
|
||||
DestroyLogicalPartition(android::base::Basename(kScratchMountPoint));
|
||||
}
|
||||
}
|
||||
|
||||
// Teardown DSU overlay if present.
|
||||
std::string scratch_device;
|
||||
if (MapDsuScratchDevice(&scratch_device)) {
|
||||
fs_mgr_overlayfs_umount_scratch();
|
||||
if (fs_mgr_overlayfs_mount_scratch(scratch_device, fs_mgr_overlayfs_scratch_mount_type())) {
|
||||
|
|
|
@ -66,6 +66,7 @@ class ImageManagerBinder final : public IImageManager {
|
|||
bool RemoveDisabledImages() override;
|
||||
bool GetMappedImageDevice(const std::string& name, std::string* device) override;
|
||||
bool MapAllImages(const std::function<bool(std::set<std::string>)>& init) override;
|
||||
bool IsImageDisabled(const std::string& name) override;
|
||||
|
||||
std::vector<std::string> GetAllBackingImages() override;
|
||||
|
||||
|
@ -219,6 +220,17 @@ bool ImageManagerBinder::GetMappedImageDevice(const std::string& name, std::stri
|
|||
return !device->empty();
|
||||
}
|
||||
|
||||
bool ImageManagerBinder::IsImageDisabled(const std::string& name) {
|
||||
bool retval;
|
||||
auto status = manager_->isImageDisabled(name, &retval);
|
||||
if (!status.isOk()) {
|
||||
LOG(ERROR) << __PRETTY_FUNCTION__
|
||||
<< " binder returned: " << status.exceptionMessage().string();
|
||||
return false;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
bool ImageManagerBinder::MapAllImages(const std::function<bool(std::set<std::string>)>&) {
|
||||
LOG(ERROR) << __PRETTY_FUNCTION__ << " not available over binder";
|
||||
return false;
|
||||
|
|
|
@ -854,6 +854,24 @@ bool ImageManager::ValidateImageMaps() {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ImageManager::IsImageDisabled(const std::string& name) {
|
||||
if (!MetadataExists(metadata_dir_)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
auto metadata = OpenMetadata(metadata_dir_);
|
||||
if (!metadata) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto partition = FindPartition(*metadata.get(), name);
|
||||
if (!partition) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return !!(partition->attributes & LP_PARTITION_ATTR_DISABLED);
|
||||
}
|
||||
|
||||
std::unique_ptr<MappedDevice> MappedDevice::Open(IImageManager* manager,
|
||||
const std::chrono::milliseconds& timeout_ms,
|
||||
const std::string& name) {
|
||||
|
|
|
@ -119,6 +119,7 @@ TEST_F(NativeTest, DisableImage) {
|
|||
ASSERT_TRUE(manager_->CreateBackingImage(base_name_, kTestImageSize, false, nullptr));
|
||||
ASSERT_TRUE(manager_->BackingImageExists(base_name_));
|
||||
ASSERT_TRUE(manager_->DisableImage(base_name_));
|
||||
ASSERT_TRUE(manager_->IsImageDisabled(base_name_));
|
||||
ASSERT_TRUE(manager_->RemoveDisabledImages());
|
||||
ASSERT_TRUE(!manager_->BackingImageExists(base_name_));
|
||||
}
|
||||
|
|
|
@ -131,6 +131,9 @@ class IImageManager {
|
|||
virtual bool RemoveAllImages() = 0;
|
||||
|
||||
virtual bool UnmapImageIfExists(const std::string& name);
|
||||
|
||||
// Returns whether DisableImage() was called.
|
||||
virtual bool IsImageDisabled(const std::string& name) = 0;
|
||||
};
|
||||
|
||||
class ImageManager final : public IImageManager {
|
||||
|
@ -162,6 +165,7 @@ class ImageManager final : public IImageManager {
|
|||
bool RemoveDisabledImages() override;
|
||||
bool GetMappedImageDevice(const std::string& name, std::string* device) override;
|
||||
bool MapAllImages(const std::function<bool(std::set<std::string>)>& init) override;
|
||||
bool IsImageDisabled(const std::string& name) override;
|
||||
|
||||
std::vector<std::string> GetAllBackingImages();
|
||||
|
||||
|
|
|
@ -199,6 +199,7 @@ class SnapshotFuzzImageManager : public android::fiemap::IImageManager {
|
|||
bool UnmapImageIfExists(const std::string& name) override {
|
||||
return impl_->UnmapImageIfExists(name);
|
||||
}
|
||||
bool IsImageDisabled(const std::string& name) override { return impl_->IsImageDisabled(name); }
|
||||
|
||||
private:
|
||||
std::unique_ptr<android::fiemap::IImageManager> impl_;
|
||||
|
|
Loading…
Reference in a new issue