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

Commit f41c7bbb authored by David Anderson's avatar David Anderson
Browse files

libfiemap: Add helpers to remove images from recovery.

ImageManager can map images in recovery, but not delete them, because
/data is not mounted. libsnapshot handles this by storing extra state
files, but this is complex to manage and inconvenient for
fs_mgr_overlayfs.

Instead, this patch introduces two new calls:

 - DisableImage(), which indicates the image should not be used. This is
   implemented by adding a new DISABLED attribute to
   LpPartitionMetadata. CreateLogicalPartitions ignores this flag, and
   thus recovery/fastbootd can disable the scratch partition and
   communicate that it can be deleted. This cannot be called from binder
   since it is intended for recovery/first-stage init only.

 - RemoveDisabledImages(), which walks the images for a given folder on
   /metadata and deletes any that are disabled. This can be called from
   binder.

Note that there is no metadata version bump for this flag. It's
considered to be included in the flag list for minor version 1, and
currently is not used for the actual super partition.

Bug: 134949511
Test: adb remount, fastboot flash system
Test: fiemap_image_test
Change-Id: Iaeca2d1eddb5637dd9a20202cafd11ae60b4d0e3
parent 43482de3
Loading
Loading
Loading
Loading
+4 −0
Original line number Original line Diff line number Diff line
@@ -151,6 +151,10 @@ bool CreateLogicalPartitions(const LpMetadata& metadata, const std::string& supe
            LINFO << "Skipping zero-length logical partition: " << GetPartitionName(partition);
            LINFO << "Skipping zero-length logical partition: " << GetPartitionName(partition);
            continue;
            continue;
        }
        }
        if (partition.attributes & LP_PARTITION_ATTR_DISABLED) {
            LINFO << "Skipping disabled partition: " << GetPartitionName(partition);
            continue;
        }


        params.partition = &partition;
        params.partition = &partition;


+17 −0
Original line number Original line Diff line number Diff line
@@ -43,6 +43,8 @@ class ImageManagerBinder final : public IImageManager {
                                  std::string* dev) override;
                                  std::string* dev) override;
    bool ZeroFillNewImage(const std::string& name, uint64_t bytes) override;
    bool ZeroFillNewImage(const std::string& name, uint64_t bytes) override;
    bool RemoveAllImages() override;
    bool RemoveAllImages() override;
    bool DisableImage(const std::string& name) override;
    bool RemoveDisabledImages() override;


    std::vector<std::string> GetAllBackingImages() override;
    std::vector<std::string> GetAllBackingImages() override;


@@ -163,6 +165,21 @@ bool ImageManagerBinder::RemoveAllImages() {
    return true;
    return true;
}
}


bool ImageManagerBinder::DisableImage(const std::string&) {
    LOG(ERROR) << __PRETTY_FUNCTION__ << " is not available over binder";
    return false;
}

bool ImageManagerBinder::RemoveDisabledImages() {
    auto status = manager_->removeDisabledImages();
    if (!status.isOk()) {
        LOG(ERROR) << __PRETTY_FUNCTION__
                   << " binder returned: " << status.exceptionMessage().string();
        return false;
    }
    return true;
}

static android::sp<IGsid> AcquireIGsid(const std::chrono::milliseconds& timeout_ms) {
static android::sp<IGsid> AcquireIGsid(const std::chrono::milliseconds& timeout_ms) {
    if (android::base::GetProperty("init.svc.gsid", "") != "running") {
    if (android::base::GetProperty("init.svc.gsid", "") != "running") {
        if (!android::base::SetProperty("ctl.start", "gsid") ||
        if (!android::base::SetProperty("ctl.start", "gsid") ||
+21 −0
Original line number Original line Diff line number Diff line
@@ -632,6 +632,27 @@ bool ImageManager::Validate() {
    return true;
    return true;
}
}


bool ImageManager::DisableImage(const std::string& name) {
    return AddAttributes(metadata_dir_, name, LP_PARTITION_ATTR_DISABLED);
}

bool ImageManager::RemoveDisabledImages() {
    if (!MetadataExists(metadata_dir_)) {
        return true;
    }

    auto metadata = OpenMetadata(metadata_dir_);
    if (!metadata) {
        return false;
    }

    bool ok = true;
    for (const auto& partition : metadata->partitions) {
        ok &= DeleteBackingImage(GetPartitionName(partition));
    }
    return ok;
}

std::unique_ptr<MappedDevice> MappedDevice::Open(IImageManager* manager,
std::unique_ptr<MappedDevice> MappedDevice::Open(IImageManager* manager,
                                                 const std::chrono::milliseconds& timeout_ms,
                                                 const std::chrono::milliseconds& timeout_ms,
                                                 const std::string& name) {
                                                 const std::string& name) {
+8 −0
Original line number Original line Diff line number Diff line
@@ -112,6 +112,14 @@ TEST_F(NativeTest, CreateAndMap) {
    ASSERT_EQ(android::base::GetProperty(PropertyName(), ""), "");
    ASSERT_EQ(android::base::GetProperty(PropertyName(), ""), "");
}
}


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_->RemoveDisabledImages());
    ASSERT_TRUE(!manager_->BackingImageExists(base_name_));
}

// This fixture is for tests against a simulated device environment. Rather
// This fixture is for tests against a simulated device environment. Rather
// than use /data, we create an image and then layer a new filesystem within
// than use /data, we create an image and then layer a new filesystem within
// it. Each test then decides how to mount and create layered images. This
// it. Each test then decides how to mount and create layered images. This
+12 −0
Original line number Original line Diff line number Diff line
@@ -84,6 +84,16 @@ class IImageManager {
    virtual bool MapImageWithDeviceMapper(const IPartitionOpener& opener, const std::string& name,
    virtual bool MapImageWithDeviceMapper(const IPartitionOpener& opener, const std::string& name,
                                          std::string* dev) = 0;
                                          std::string* dev) = 0;


    // Mark an image as disabled. This is useful for marking an image as
    // 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;

    // Remove all images that been marked as disabled.
    virtual bool RemoveDisabledImages() = 0;

    // Get all backing image names.
    // Get all backing image names.
    virtual std::vector<std::string> GetAllBackingImages() = 0;
    virtual std::vector<std::string> GetAllBackingImages() = 0;


@@ -119,6 +129,8 @@ class ImageManager final : public IImageManager {
    bool MapImageWithDeviceMapper(const IPartitionOpener& opener, const std::string& name,
    bool MapImageWithDeviceMapper(const IPartitionOpener& opener, const std::string& name,
                                  std::string* dev) override;
                                  std::string* dev) override;
    bool RemoveAllImages() override;
    bool RemoveAllImages() override;
    bool DisableImage(const std::string& name) override;
    bool RemoveDisabledImages() override;


    std::vector<std::string> GetAllBackingImages();
    std::vector<std::string> GetAllBackingImages();
    // Same as CreateBackingImage, but provides a progress notification.
    // Same as CreateBackingImage, but provides a progress notification.
Loading