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

Commit 4929df0c authored by David Anderson's avatar David Anderson
Browse files

fs_mgr: Allow using major:minor device strings in CreateLogicalPartition.

IPartitionOpener is useful for writing gtests, however, it can't easily
be used with CreateLogicalPartition. fs_mgr assumes the super partition
name will map to /dev/block/by-name/super whereas in tests we want to
redirect it to a different block device.

This CL makes two changes. First, it adds a new method to IPartitionOpener
to return a "device string" for a device name. The string must either be
an absolute path (for example /dev/block/by-name/super) or a major:minor
sequence, since device-mapper will accept either.

Second, CreateLogicalPartition now accepts an optional IPartitionOpener.
When converting block devices to paths, it uses the opener instead of
automatically prepending /dev/block/by-name.

Bug: 139204329
Test: liblp_test gtest
      libsnapshot_test gtest

Change-Id: Id6b3120cc2ef5c0dd941b29ff96215ad3c8ec848
parent 15aa9540
Loading
Loading
Loading
Loading
+29 −17
Original line number Diff line number Diff line
@@ -52,29 +52,36 @@ using DmTarget = android::dm::DmTarget;
using DmTargetZero = android::dm::DmTargetZero;
using DmTargetLinear = android::dm::DmTargetLinear;

static bool GetPhysicalPartitionDevicePath(const LpMetadata& metadata,
static bool GetPhysicalPartitionDevicePath(const IPartitionOpener& opener,
                                           const LpMetadata& metadata,
                                           const LpMetadataBlockDevice& block_device,
                                           const std::string& super_device,
                                           std::string* result) {
    // Note: device-mapper will not accept symlinks, so we must use realpath
    // here.
    std::string name = GetBlockDevicePartitionName(block_device);
    std::string path = "/dev/block/by-name/" + name;
                                           const std::string& super_device, std::string* result) {
    // If the super device is the source of this block device's metadata,
    // make sure we use the correct super device (and not just "super",
    // which might not exist.)
    std::string name = GetBlockDevicePartitionName(block_device);
    std::string dev_string = opener.GetDeviceString(name);
    if (GetMetadataSuperBlockDevice(metadata) == &block_device) {
        path = super_device;
        dev_string = opener.GetDeviceString(super_device);
    }
    if (!android::base::Realpath(path, result)) {
        PERROR << "realpath: " << path;

    // Note: device-mapper will not accept symlinks, so we must use realpath
    // here. If the device string is a major:minor sequence, we don't need to
    // to call Realpath (it would not work anyway).
    if (android::base::StartsWith(dev_string, "/")) {
        if (!android::base::Realpath(dev_string, result)) {
            PERROR << "realpath: " << dev_string;
            return false;
        }
    } else {
        *result = dev_string;
    }
    return true;
}

static bool CreateDmTable(const LpMetadata& metadata, const LpMetadataPartition& partition,
                          const std::string& super_device, DmTable* table) {
static bool CreateDmTable(const IPartitionOpener& opener, const LpMetadata& metadata,
                          const LpMetadataPartition& partition, const std::string& super_device,
                          DmTable* table) {
    uint64_t sector = 0;
    for (size_t i = 0; i < partition.num_extents; i++) {
        const auto& extent = metadata.extents[partition.first_extent_index + i];
@@ -85,12 +92,13 @@ static bool CreateDmTable(const LpMetadata& metadata, const LpMetadataPartition&
                break;
            case LP_TARGET_TYPE_LINEAR: {
                const auto& block_device = metadata.block_devices[extent.target_source];
                std::string path;
                if (!GetPhysicalPartitionDevicePath(metadata, block_device, super_device, &path)) {
                std::string dev_string;
                if (!GetPhysicalPartitionDevicePath(opener, metadata, block_device, super_device,
                                                    &dev_string)) {
                    LOG(ERROR) << "Unable to complete device-mapper table, unknown block device";
                    return false;
                }
                target = std::make_unique<DmTargetLinear>(sector, extent.num_sectors, path,
                target = std::make_unique<DmTargetLinear>(sector, extent.num_sectors, dev_string,
                                                          extent.target_data);
                break;
            }
@@ -179,8 +187,12 @@ bool CreateLogicalPartition(const CreateLogicalPartitionParams& params, std::str
        }
    }

    PartitionOpener default_opener;
    const IPartitionOpener* opener =
            params.partition_opener ? params.partition_opener : &default_opener;

    DmTable table;
    if (!CreateDmTable(*metadata, *partition, params.block_device, &table)) {
    if (!CreateDmTable(*opener, *metadata, *partition, params.block_device, &table)) {
        return false;
    }
    if (params.force_writable) {
+4 −0
Original line number Diff line number Diff line
@@ -73,6 +73,10 @@ struct CreateLogicalPartitionParams {
    // If this is non-empty, it will override the device mapper name (by
    // default the partition name will be used).
    std::string device_name;

    // If non-null, this will use the specified IPartitionOpener rather than
    // the default one.
    const IPartitionOpener* partition_opener = nullptr;
};

bool CreateLogicalPartition(const CreateLogicalPartitionParams& params, std::string* path);
+6 −0
Original line number Diff line number Diff line
@@ -62,6 +62,11 @@ class IPartitionOpener {
    // Return block device information about the given named physical partition.
    // The name can be an absolute path if the full path is already known.
    virtual bool GetInfo(const std::string& partition_name, BlockDeviceInfo* info) const = 0;

    // Return a path that can be used to pass the block device to device-mapper.
    // This must either result in an absolute path, or a major:minor device
    // sequence.
    virtual std::string GetDeviceString(const std::string& partition_name) const = 0;
};

// Helper class to implement IPartitionOpener. If |partition_name| is not an
@@ -71,6 +76,7 @@ class PartitionOpener : public IPartitionOpener {
    virtual android::base::unique_fd Open(const std::string& partition_name,
                                          int flags) const override;
    virtual bool GetInfo(const std::string& partition_name, BlockDeviceInfo* info) const override;
    virtual std::string GetDeviceString(const std::string& partition_name) const override;
};

}  // namespace fs_mgr
+4 −0
Original line number Diff line number Diff line
@@ -100,5 +100,9 @@ bool PartitionOpener::GetInfo(const std::string& partition_name, BlockDeviceInfo
    return GetBlockDeviceInfo(path, info);
}

std::string PartitionOpener::GetDeviceString(const std::string& partition_name) const {
    return GetPartitionAbsolutePath(partition_name);
}

}  // namespace fs_mgr
}  // namespace android