Merge "liblp: CreateLogicalPartition with a given mapped name"

This commit is contained in:
Yifan Hong 2019-08-16 17:41:22 +00:00 committed by Gerrit Code Review
commit 1d6d4507a4
4 changed files with 110 additions and 64 deletions

View file

@ -56,8 +56,16 @@ bool OpenLogicalPartition(FastbootDevice* device, const std::string& partition_n
if (!path) {
return false;
}
CreateLogicalPartitionParams params = {
.block_device = *path,
.metadata_slot = slot_number,
.partition_name = partition_name,
.force_writable = true,
.timeout_ms = 5s,
};
std::string dm_path;
if (!CreateLogicalPartition(path->c_str(), slot_number, partition_name, true, 5s, &dm_path)) {
if (!CreateLogicalPartition(params, &dm_path)) {
LOG(ERROR) << "Could not map partition: " << partition_name;
return false;
}

View file

@ -109,26 +109,6 @@ static bool CreateDmTable(const LpMetadata& metadata, const LpMetadataPartition&
return true;
}
static bool CreateLogicalPartition(const LpMetadata& metadata, const LpMetadataPartition& partition,
bool force_writable, const std::chrono::milliseconds& timeout_ms,
const std::string& super_device, std::string* path) {
DeviceMapper& dm = DeviceMapper::Instance();
DmTable table;
if (!CreateDmTable(metadata, partition, super_device, &table)) {
return false;
}
if (force_writable) {
table.set_readonly(false);
}
std::string name = GetPartitionName(partition);
if (!dm.CreateDevice(name, table, path, timeout_ms)) {
return false;
}
LINFO << "Created logical partition " << name << " on device " << *path;
return true;
}
bool CreateLogicalPartitions(const std::string& block_device) {
uint32_t slot = SlotNumberForSlotSuffix(fs_mgr_get_slot_suffix());
auto metadata = ReadMetadata(block_device.c_str(), slot);
@ -145,13 +125,20 @@ std::unique_ptr<LpMetadata> ReadCurrentMetadata(const std::string& block_device)
}
bool CreateLogicalPartitions(const LpMetadata& metadata, const std::string& super_device) {
CreateLogicalPartitionParams params = {
.block_device = super_device,
.metadata = &metadata,
};
for (const auto& partition : metadata.partitions) {
if (!partition.num_extents) {
LINFO << "Skipping zero-length logical partition: " << GetPartitionName(partition);
continue;
}
std::string path;
if (!CreateLogicalPartition(metadata, partition, false, {}, super_device, &path)) {
params.partition = &partition;
std::string ignore_path;
if (!CreateLogicalPartition(params, &ignore_path)) {
LERROR << "Could not create logical partition: " << GetPartitionName(partition);
return false;
}
@ -159,29 +146,58 @@ bool CreateLogicalPartitions(const LpMetadata& metadata, const std::string& supe
return true;
}
bool CreateLogicalPartition(const std::string& block_device, const LpMetadata& metadata,
const std::string& partition_name, bool force_writable,
const std::chrono::milliseconds& timeout_ms, std::string* path) {
for (const auto& partition : metadata.partitions) {
if (GetPartitionName(partition) == partition_name) {
return CreateLogicalPartition(metadata, partition, force_writable, timeout_ms,
block_device, path);
bool CreateLogicalPartition(const CreateLogicalPartitionParams& params, std::string* path) {
const LpMetadata* metadata = params.metadata;
// Read metadata if needed.
std::unique_ptr<LpMetadata> local_metadata;
if (!metadata) {
if (!params.metadata_slot) {
LOG(ERROR) << "Either metadata or a metadata slot must be specified.";
return false;
}
auto slot = *params.metadata_slot;
if (local_metadata = ReadMetadata(params.block_device, slot); !local_metadata) {
LOG(ERROR) << "Could not read partition table for: " << params.block_device;
return false;
}
metadata = local_metadata.get();
}
// Find the partition by name if needed.
const LpMetadataPartition* partition = params.partition;
if (!partition) {
for (const auto& iter : metadata->partitions) {
if (GetPartitionName(iter) == params.partition_name) {
partition = &iter;
break;
}
}
if (!partition) {
LERROR << "Could not find any partition with name: " << params.partition_name;
return false;
}
}
LERROR << "Could not find any partition with name: " << partition_name;
return false;
}
bool CreateLogicalPartition(const std::string& block_device, uint32_t metadata_slot,
const std::string& partition_name, bool force_writable,
const std::chrono::milliseconds& timeout_ms, std::string* path) {
auto metadata = ReadMetadata(block_device.c_str(), metadata_slot);
if (!metadata) {
LOG(ERROR) << "Could not read partition table.";
return true;
DmTable table;
if (!CreateDmTable(*metadata, *partition, params.block_device, &table)) {
return false;
}
return CreateLogicalPartition(block_device, *metadata.get(), partition_name, force_writable,
timeout_ms, path);
if (params.force_writable) {
table.set_readonly(false);
}
std::string device_name = params.device_name;
if (device_name.empty()) {
device_name = GetPartitionName(*partition);
}
DeviceMapper& dm = DeviceMapper::Instance();
if (!dm.CreateDevice(device_name, table, path, params.timeout_ms)) {
return false;
}
LINFO << "Created logical partition " << device_name << " on device " << *path;
return true;
}
bool UnmapDevice(const std::string& name) {

View file

@ -959,9 +959,16 @@ bool fs_mgr_overlayfs_create_scratch(const Fstab& fstab, std::string* scratch_de
}
if (changed || partition_create) {
if (!CreateLogicalPartition(super_device, slot_number, partition_name, true, 10s,
scratch_device))
CreateLogicalPartitionParams params = {
.block_device = super_device,
.metadata_slot = slot_number,
.partition_name = partition_name,
.force_writable = true,
.timeout_ms = 10s,
};
if (!CreateLogicalPartition(params, scratch_device)) {
return false;
}
if (change) *change = true;
}
@ -1182,11 +1189,15 @@ bool fs_mgr_overlayfs_teardown(const char* mount_point, bool* change) {
if ((mount_point != nullptr) && !fs_mgr_overlayfs_already_mounted(kScratchMountPoint, false)) {
auto scratch_device = fs_mgr_overlayfs_scratch_device();
if (scratch_device.empty()) {
auto slot_number = fs_mgr_overlayfs_slot_number();
auto super_device = fs_mgr_overlayfs_super_device(slot_number);
const auto partition_name = android::base::Basename(kScratchMountPoint);
CreateLogicalPartition(super_device, slot_number, partition_name, true, 10s,
&scratch_device);
auto metadata_slot = fs_mgr_overlayfs_slot_number();
CreateLogicalPartitionParams params = {
.block_device = fs_mgr_overlayfs_super_device(metadata_slot),
.metadata_slot = metadata_slot,
.partition_name = android::base::Basename(kScratchMountPoint),
.force_writable = true,
.timeout_ms = 10s,
};
CreateLogicalPartition(params, &scratch_device);
}
mount_scratch = fs_mgr_overlayfs_mount_scratch(scratch_device,
fs_mgr_overlayfs_scratch_mount_type());

View file

@ -29,6 +29,7 @@
#include <chrono>
#include <memory>
#include <optional>
#include <string>
#include <vector>
@ -49,22 +50,32 @@ bool CreateLogicalPartitions(const LpMetadata& metadata, const std::string& bloc
// method for ReadMetadata and CreateLogicalPartitions.
bool CreateLogicalPartitions(const std::string& block_device);
// Create a block device for a single logical partition, given metadata and
// the partition name. On success, a path to the partition's block device is
// returned. If |force_writable| is true, the "readonly" flag will be ignored
// so the partition can be flashed.
//
// If |timeout_ms| is non-zero, then CreateLogicalPartition will block for the
// given amount of time until the path returned in |path| is available.
bool CreateLogicalPartition(const std::string& block_device, uint32_t metadata_slot,
const std::string& partition_name, bool force_writable,
const std::chrono::milliseconds& timeout_ms, std::string* path);
struct CreateLogicalPartitionParams {
// Block device of the super partition.
std::string block_device;
// Same as above, but with a given metadata object. Care should be taken that
// the metadata represents a valid partition layout.
bool CreateLogicalPartition(const std::string& block_device, const LpMetadata& metadata,
const std::string& partition_name, bool force_writable,
const std::chrono::milliseconds& timeout_ms, std::string* path);
// If |metadata| is null, the slot will be read using |metadata_slot|.
const LpMetadata* metadata = nullptr;
std::optional<uint32_t> metadata_slot;
// If |partition| is not set, it will be found via |partition_name|.
const LpMetadataPartition* partition = nullptr;
std::string partition_name;
// Force the device to be read-write even if it was specified as readonly
// in the metadata.
bool force_writable = false;
// If |timeout_ms| is non-zero, then CreateLogicalPartition will block for
// the given amount of time until the path returned in |path| is available.
std::chrono::milliseconds timeout_ms = {};
// If this is non-empty, it will override the device mapper name (by
// default the partition name will be used).
std::string device_name;
};
bool CreateLogicalPartition(const CreateLogicalPartitionParams& params, std::string* path);
// Destroy the block device for a logical partition, by name. If |timeout_ms|
// is non-zero, then this will block until the device path has been unlinked.