Merge "Support for striped in libdm" into main
diff --git a/fs_mgr/libdm/dm_target.cpp b/fs_mgr/libdm/dm_target.cpp
index 90d91a0..1f6bd1a 100644
--- a/fs_mgr/libdm/dm_target.cpp
+++ b/fs_mgr/libdm/dm_target.cpp
@@ -61,6 +61,10 @@
     return block_device_ + " " + std::to_string(physical_sector_);
 }
 
+std::string DmTargetStripe::GetParameterString() const {
+    return "2 " + std::to_string(chunksize) + " " + block_device0_ + " 0 " + block_device1_ + " 0";
+}
+
 DmTargetVerity::DmTargetVerity(uint64_t start, uint64_t length, uint32_t version,
                                const std::string& block_device, const std::string& hash_device,
                                uint32_t data_block_size, uint32_t hash_block_size,
diff --git a/fs_mgr/libdm/dm_test.cpp b/fs_mgr/libdm/dm_test.cpp
index a0129c2..d043be6 100644
--- a/fs_mgr/libdm/dm_test.cpp
+++ b/fs_mgr/libdm/dm_test.cpp
@@ -181,6 +181,13 @@
     ASSERT_EQ(dm.GetState(dev.name()), DmDeviceState::ACTIVE);
 }
 
+TEST_F(DmTest, StripeArgs) {
+    DmTargetStripe target(0, 4096, 1024, "/dev/loop0", "/dev/loop1");
+    ASSERT_EQ(target.name(), "striped");
+    ASSERT_TRUE(target.Valid());
+    ASSERT_EQ(target.GetParameterString(), "2 1024 /dev/loop0 0 /dev/loop1 0");
+}
+
 TEST_F(DmTest, DmVerityArgsAvb2) {
     std::string device = "/dev/block/platform/soc/1da4000.ufshc/by-name/vendor_a";
     std::string algorithm = "sha1";
diff --git a/fs_mgr/libdm/include/libdm/dm_target.h b/fs_mgr/libdm/include/libdm/dm_target.h
index 09fe200..97f3c13 100644
--- a/fs_mgr/libdm/include/libdm/dm_target.h
+++ b/fs_mgr/libdm/include/libdm/dm_target.h
@@ -116,6 +116,24 @@
     uint64_t physical_sector_;
 };
 
+class DmTargetStripe final : public DmTarget {
+  public:
+    DmTargetStripe(uint64_t start, uint64_t length, uint64_t chunksize,
+                   const std::string& block_device0, const std::string& block_device1)
+        : DmTarget(start, length),
+          chunksize(chunksize),
+          block_device0_(block_device0),
+          block_device1_(block_device1) {}
+
+    std::string name() const override { return "striped"; }
+    std::string GetParameterString() const override;
+
+  private:
+    uint64_t chunksize;
+    std::string block_device0_;
+    std::string block_device1_;
+};
+
 class DmTargetVerity final : public DmTarget {
   public:
     DmTargetVerity(uint64_t start, uint64_t length, uint32_t version,
diff --git a/fs_mgr/tools/dmctl.cpp b/fs_mgr/tools/dmctl.cpp
index 7273087..9dc8c24 100644
--- a/fs_mgr/tools/dmctl.cpp
+++ b/fs_mgr/tools/dmctl.cpp
@@ -115,6 +115,21 @@
             std::string block_device = NextArg();
             return std::make_unique<DmTargetAndroidVerity>(start_sector, num_sectors, keyid,
                                                            block_device);
+        } else if (target_type == "striped") {
+            if (!HasArgs(3)) {
+                std::cerr << "Expected \"striped\" <block_device0> <block_device1> <chunksize>"
+                          << std::endl;
+                return nullptr;
+            }
+            std::string block_device0 = NextArg();
+            std::string block_device1 = NextArg();
+            uint64_t chunk_size;
+            if (!android::base::ParseUint(NextArg(), &chunk_size)) {
+                std::cerr << "Expected start sector, got: " << PreviousArg() << std::endl;
+                return nullptr;
+            }
+            return std::make_unique<DmTargetStripe>(start_sector, num_sectors, chunk_size,
+                                                    block_device0, block_device1);
         } else if (target_type == "bow") {
             if (!HasArgs(1)) {
                 std::cerr << "Expected \"bow\" <block_device>" << std::endl;