support f2fs device aliasing feature

We can hold the storage space of one of f2fs multi-device for data
partition, while allowing the space to be used by another purpose.
f2fs will create a sequential and pinned file as a placeholder and it
can be deallocated and returned back to data partition after it is done
with using it. We can create the file, as we define the device with
"exp_alias:" tag in the fstab.

Bug: 336319772
Test: add a device with "exp_alias" tag in fstab
Change-Id: If55730cedd21ec5a40137d2eb723a97df498c9cb
Signed-off-by: Daeho Jeong <daehojeong@google.com>
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index fbd990b..fc105d6 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -1603,7 +1603,8 @@
                                    attempted_entry.fs_type,
                                    attempted_entry.fs_mgr_flags.is_zoned ? "true" : "false",
                                    std::to_string(attempted_entry.length),
-                                   android::base::Join(attempted_entry.user_devices, ' ')},
+                                   android::base::Join(attempted_entry.user_devices, ' '),
+                                   android::base::Join(attempted_entry.device_aliased, ' ')},
                                   nullptr)) {
                         LERROR << "Encryption failed";
                         set_type_property(encryptable);
@@ -1655,7 +1656,8 @@
                                formattable_entry->fs_type,
                                formattable_entry->fs_mgr_flags.is_zoned ? "true" : "false",
                                std::to_string(formattable_entry->length),
-                               android::base::Join(formattable_entry->user_devices, ' ')},
+                               android::base::Join(formattable_entry->user_devices, ' '),
+                               android::base::Join(formattable_entry->device_aliased, ' ')},
                               nullptr)) {
                     LERROR << "Encryption failed";
                 } else {
diff --git a/fs_mgr/fs_mgr_format.cpp b/fs_mgr/fs_mgr_format.cpp
index 0dde1d3..57e35a2 100644
--- a/fs_mgr/fs_mgr_format.cpp
+++ b/fs_mgr/fs_mgr_format.cpp
@@ -32,6 +32,7 @@
 #include <selinux/android.h>
 #include <selinux/label.h>
 #include <selinux/selinux.h>
+#include <filesystem>
 #include <string>
 
 #include "fs_mgr_priv.h"
@@ -126,7 +127,8 @@
 
 static int format_f2fs(const std::string& fs_blkdev, uint64_t dev_sz, bool needs_projid,
                        bool needs_casefold, bool fs_compress, bool is_zoned,
-                       const std::vector<std::string>& user_devices) {
+                       const std::vector<std::string>& user_devices,
+                       const std::vector<int>& device_aliased) {
     if (!dev_sz) {
         int rc = get_dev_sz(fs_blkdev, &dev_sz);
         if (rc) {
@@ -164,9 +166,15 @@
     if (is_zoned) {
         args.push_back("-m");
     }
-    for (auto& device : user_devices) {
+    for (size_t i = 0; i < user_devices.size(); i++) {
+        std::string device_name = user_devices[i];
+
         args.push_back("-c");
-        args.push_back(device.c_str());
+        if (device_aliased[i]) {
+            std::filesystem::path path = device_name;
+            device_name += "@" + path.filename().string();
+        }
+        args.push_back(device_name.c_str());
     }
 
     if (user_devices.empty()) {
@@ -191,7 +199,7 @@
     if (entry.fs_type == "f2fs") {
         return format_f2fs(entry.blk_device, entry.length, needs_projid, needs_casefold,
                            entry.fs_mgr_flags.fs_compress, entry.fs_mgr_flags.is_zoned,
-                           entry.user_devices);
+                           entry.user_devices, entry.device_aliased);
     } else if (entry.fs_type == "ext4") {
         return format_ext4(entry.blk_device, entry.mount_point, needs_projid,
                            entry.fs_mgr_flags.ext_meta_csum);
diff --git a/fs_mgr/libfstab/fstab.cpp b/fs_mgr/libfstab/fstab.cpp
index d344b2d..6e4cae1 100644
--- a/fs_mgr/libfstab/fstab.cpp
+++ b/fs_mgr/libfstab/fstab.cpp
@@ -173,6 +173,7 @@
         entry->fs_mgr_flags.is_zoned = true;
     }
     entry->user_devices.push_back(param[1]);
+    entry->device_aliased.push_back(param[0] == "exp_alias" ? 1 : 0);
 }
 
 bool ParseFsMgrFlags(const std::string& flags, FstabEntry* entry) {
diff --git a/fs_mgr/libfstab/include/fstab/fstab.h b/fs_mgr/libfstab/include/fstab/fstab.h
index 21fe017..070dd91 100644
--- a/fs_mgr/libfstab/include/fstab/fstab.h
+++ b/fs_mgr/libfstab/include/fstab/fstab.h
@@ -33,6 +33,7 @@
 struct FstabEntry {
     std::string blk_device;
     std::vector<std::string> user_devices;
+    std::vector<int> device_aliased;
     std::string logical_partition_name;
     std::string mount_point;
     std::string fs_type;