liblp: Allow flashing to readonly logical partitions.

By default, logical partitions with the readonly flag are created with a
readonly device. This change allows callers of CreateLogicalPartition
to create writable devices so they can still be flashed.

Bug: 78793464
Test: fastboot flash product_services works with fastbootd
Change-Id: Ia8d2761a3067e3b62815acbf0b6fb7f033072ba2
diff --git a/fs_mgr/fs_mgr_dm_linear.cpp b/fs_mgr/fs_mgr_dm_linear.cpp
index aa68ceb..94c06ba 100644
--- a/fs_mgr/fs_mgr_dm_linear.cpp
+++ b/fs_mgr/fs_mgr_dm_linear.cpp
@@ -80,13 +80,17 @@
 }
 
 static bool CreateLogicalPartition(const std::string& block_device, const LpMetadata& metadata,
-                                   const LpMetadataPartition& partition, std::string* path) {
+                                   const LpMetadataPartition& partition, bool force_writable,
+                                   std::string* path) {
     DeviceMapper& dm = DeviceMapper::Instance();
 
     DmTable table;
     if (!CreateDmTable(block_device, metadata, partition, &table)) {
         return false;
     }
+    if (force_writable) {
+        table.set_readonly(false);
+    }
     std::string name = GetPartitionName(partition);
     if (!dm.CreateDevice(name, table)) {
         return false;
@@ -107,7 +111,7 @@
     }
     for (const auto& partition : metadata->partitions) {
         std::string path;
-        if (!CreateLogicalPartition(block_device, *metadata.get(), partition, &path)) {
+        if (!CreateLogicalPartition(block_device, *metadata.get(), partition, false, &path)) {
             LERROR << "Could not create logical partition: " << GetPartitionName(partition);
             return false;
         }
@@ -116,7 +120,8 @@
 }
 
 bool CreateLogicalPartition(const std::string& block_device, uint32_t metadata_slot,
-                            const std::string& partition_name, std::string* path) {
+                            const std::string& partition_name, bool force_writable,
+                            std::string* path) {
     auto metadata = ReadMetadata(block_device.c_str(), metadata_slot);
     if (!metadata) {
         LOG(ERROR) << "Could not read partition table.";
@@ -124,7 +129,8 @@
     }
     for (const auto& partition : metadata->partitions) {
         if (GetPartitionName(partition) == partition_name) {
-            return CreateLogicalPartition(block_device, *metadata.get(), partition, path);
+            return CreateLogicalPartition(block_device, *metadata.get(), partition, force_writable,
+                                          path);
         }
     }
     LERROR << "Could not find any partition with name: " << partition_name;
diff --git a/fs_mgr/include/fs_mgr_dm_linear.h b/fs_mgr/include/fs_mgr_dm_linear.h
index cac475c..f15c450 100644
--- a/fs_mgr/include/fs_mgr_dm_linear.h
+++ b/fs_mgr/include/fs_mgr_dm_linear.h
@@ -41,9 +41,11 @@
 
 // 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.
+// returned. If |force_writable| is true, the "readonly" flag will be ignored
+// so the partition can be flashed.
 bool CreateLogicalPartition(const std::string& block_device, uint32_t metadata_slot,
-                            const std::string& partition_name, std::string* path);
+                            const std::string& partition_name, bool force_writable,
+                            std::string* path);
 
 // Destroy the block device for a logical partition, by name.
 bool DestroyLogicalPartition(const std::string& name);