diff options
-rw-r--r-- | fs_mgr/fs_mgr_fstab.cpp | 171 | ||||
-rw-r--r-- | fs_mgr/tests/fs_mgr_test.cpp | 53 |
2 files changed, 106 insertions, 118 deletions
diff --git a/fs_mgr/fs_mgr_fstab.cpp b/fs_mgr/fs_mgr_fstab.cpp index 98e0f5a40..8c719c868 100644 --- a/fs_mgr/fs_mgr_fstab.cpp +++ b/fs_mgr/fs_mgr_fstab.cpp @@ -502,18 +502,33 @@ std::set<std::string> ExtraBootDevices(const Fstab& fstab) { return boot_devices; } -template <typename Pred> -std::vector<FstabEntry*> GetEntriesByPred(Fstab* fstab, const Pred& pred) { - if (fstab == nullptr) { - return {}; - } - std::vector<FstabEntry*> entries; - for (auto&& entry : *fstab) { - if (pred(entry)) { - entries.push_back(&entry); - } +FstabEntry BuildDsuUserdataFstabEntry() { + constexpr uint32_t kFlags = MS_NOATIME | MS_NOSUID | MS_NODEV; + + FstabEntry userdata = { + .blk_device = "userdata_gsi", + .mount_point = "/data", + .fs_type = "ext4", + .flags = kFlags, + .reserved_size = 128 * 1024 * 1024, + }; + userdata.fs_mgr_flags.wait = true; + userdata.fs_mgr_flags.check = true; + userdata.fs_mgr_flags.logical = true; + userdata.fs_mgr_flags.quota = true; + userdata.fs_mgr_flags.late_mount = true; + userdata.fs_mgr_flags.formattable = true; + return userdata; +} + +bool EraseFstabEntry(Fstab* fstab, const std::string& mount_point) { + auto iter = std::remove_if(fstab->begin(), fstab->end(), + [&](const auto& entry) { return entry.mount_point == mount_point; }); + if (iter != fstab->end()) { + fstab->erase(iter, fstab->end()); + return true; } - return entries; + return false; } } // namespace @@ -576,28 +591,38 @@ bool ParseFstabFromString(const std::string& fstab_str, bool proc_mounts, Fstab* void TransformFstabForDsu(Fstab* fstab, const std::string& dsu_slot, const std::vector<std::string>& dsu_partitions) { static constexpr char kDsuKeysDir[] = "/avb"; + // Convert userdata + // Inherit fstab properties for userdata. + FstabEntry userdata; + if (FstabEntry* entry = GetEntryForMountPoint(fstab, "/data")) { + userdata = *entry; + userdata.blk_device = android::gsi::kDsuUserdata; + userdata.fs_mgr_flags.logical = true; + userdata.fs_mgr_flags.formattable = true; + if (!userdata.metadata_key_dir.empty()) { + userdata.metadata_key_dir = android::gsi::GetDsuMetadataKeyDir(dsu_slot); + } + } else { + userdata = BuildDsuUserdataFstabEntry(); + } + + if (EraseFstabEntry(fstab, "/data")) { + fstab->emplace_back(userdata); + } + + // Convert others for (auto&& partition : dsu_partitions) { if (!EndsWith(partition, gsi::kDsuPostfix)) { continue; } - // scratch is handled by fs_mgr_overlayfs - if (partition == android::gsi::kDsuScratch) { + // userdata has been handled + if (partition == android::gsi::kDsuUserdata) { continue; } - // Convert userdata partition. - if (partition == android::gsi::kDsuUserdata) { - for (auto&& entry : GetEntriesForMountPoint(fstab, "/data")) { - entry->blk_device = android::gsi::kDsuUserdata; - entry->fs_mgr_flags.logical = true; - entry->fs_mgr_flags.formattable = true; - if (!entry->metadata_key_dir.empty()) { - entry->metadata_key_dir = android::gsi::GetDsuMetadataKeyDir(dsu_slot); - } - } + // scratch is handled by fs_mgr_overlayfs + if (partition == android::gsi::kDsuScratch) { continue; } - // Convert RO partitions. - // // dsu_partition_name = corresponding_partition_name + kDsuPostfix // e.g. // system_gsi for system @@ -605,51 +630,45 @@ void TransformFstabForDsu(Fstab* fstab, const std::string& dsu_slot, // vendor_gsi for vendor std::string lp_name = partition.substr(0, partition.length() - strlen(gsi::kDsuPostfix)); std::string mount_point = "/" + lp_name; - - // List of fs_type entries we're lacking, need to synthesis these later. - std::vector<std::string> lack_fs_list = {"ext4", "erofs"}; - - // Only support early mount (first_stage_mount) partitions. - auto pred = [&mount_point](const FstabEntry& entry) { - return entry.fs_mgr_flags.first_stage_mount && entry.mount_point == mount_point; - }; - - // Transform all matching entries and assume they are all adjacent for simplicity. - for (auto&& entry : GetEntriesByPred(fstab, pred)) { - // .blk_device is replaced with the DSU partition. - entry->blk_device = partition; - // .avb_keys hints first_stage_mount to load the chained-vbmeta image from partition - // footer. See aosp/932779 for more details. - entry->avb_keys = kDsuKeysDir; - // .logical_partition_name is required to look up AVB Hashtree descriptors. - entry->logical_partition_name = lp_name; - entry->fs_mgr_flags.logical = true; - entry->fs_mgr_flags.slot_select = false; - entry->fs_mgr_flags.slot_select_other = false; - - if (auto it = std::find(lack_fs_list.begin(), lack_fs_list.end(), entry->fs_type); - it != lack_fs_list.end()) { - lack_fs_list.erase(it); + std::vector<FstabEntry*> entries = GetEntriesForMountPoint(fstab, mount_point); + if (entries.empty()) { + FstabEntry entry = { + .blk_device = partition, + // .logical_partition_name is required to look up AVB Hashtree descriptors. + .logical_partition_name = "system", + .mount_point = mount_point, + .fs_type = "ext4", + .flags = MS_RDONLY, + .fs_options = "barrier=1", + .avb_keys = kDsuKeysDir, + }; + entry.fs_mgr_flags.wait = true; + entry.fs_mgr_flags.logical = true; + entry.fs_mgr_flags.first_stage_mount = true; + fstab->emplace_back(entry); + } else { + // If the corresponding partition exists, transform all its Fstab + // by pointing .blk_device to the DSU partition. + for (auto&& entry : entries) { + entry->blk_device = partition; + // AVB keys for DSU should always be under kDsuKeysDir. + entry->avb_keys = kDsuKeysDir; + entry->fs_mgr_flags.logical = true; } - } - - if (!lack_fs_list.empty()) { - // Insert at the end of the existing mountpoint group, or at the end of fstab. - // We assume there is at most one matching mountpoint group, which is the common case. - auto it = std::find_if_not(std::find_if(fstab->begin(), fstab->end(), pred), - fstab->end(), pred); - for (const auto& fs_type : lack_fs_list) { - it = std::next(fstab->insert(it, {.blk_device = partition, - .logical_partition_name = lp_name, - .mount_point = mount_point, - .fs_type = fs_type, - .flags = MS_RDONLY, - .avb_keys = kDsuKeysDir, - .fs_mgr_flags{ - .wait = true, - .logical = true, - .first_stage_mount = true, - }})); + // Make sure the ext4 is included to support GSI. + auto partition_ext4 = + std::find_if(fstab->begin(), fstab->end(), [&](const auto& entry) { + return entry.mount_point == mount_point && entry.fs_type == "ext4"; + }); + if (partition_ext4 == fstab->end()) { + auto new_entry = *GetEntryForMountPoint(fstab, mount_point); + new_entry.fs_type = "ext4"; + auto it = std::find_if(fstab->rbegin(), fstab->rend(), + [&mount_point](const auto& entry) { + return entry.mount_point == mount_point; + }); + auto end_of_mount_point_group = fstab->begin() + std::distance(it, fstab->rend()); + fstab->insert(end_of_mount_point_group, new_entry); } } } @@ -838,8 +857,18 @@ FstabEntry* GetEntryForMountPoint(Fstab* fstab, const std::string& path) { } std::vector<FstabEntry*> GetEntriesForMountPoint(Fstab* fstab, const std::string& path) { - return GetEntriesByPred(fstab, - [&path](const FstabEntry& entry) { return entry.mount_point == path; }); + std::vector<FstabEntry*> entries; + if (fstab == nullptr) { + return entries; + } + + for (auto& entry : *fstab) { + if (entry.mount_point == path) { + entries.emplace_back(&entry); + } + } + + return entries; } std::set<std::string> GetBootDevices() { diff --git a/fs_mgr/tests/fs_mgr_test.cpp b/fs_mgr/tests/fs_mgr_test.cpp index e33681c3f..6c881c0bf 100644 --- a/fs_mgr/tests/fs_mgr_test.cpp +++ b/fs_mgr/tests/fs_mgr_test.cpp @@ -1109,17 +1109,14 @@ TEST(fs_mgr, TransformFstabForDsu) { TemporaryFile tf; ASSERT_TRUE(tf.fd != -1); std::string fstab_contents = R"fs( -data /data f2fs noatime wait,latemount system /system erofs ro wait,logical,first_stage_mount system /system ext4 ro wait,logical,first_stage_mount vendor /vendor ext4 ro wait,logical,first_stage_mount +data /data f2fs noatime wait )fs"; ASSERT_TRUE(android::base::WriteStringToFile(fstab_contents, tf.path)); - // If GSI is installed, ReadFstabFromFile() would have called TransformFstabForDsu() implicitly. - // In other words, TransformFstabForDsu() would be called two times if running CTS-on-GSI, - // which implies TransformFstabForDsu() should be idempotent. Fstab fstab; EXPECT_TRUE(ReadFstabFromFile(tf.path, &fstab)); TransformFstabForDsu(&fstab, "dsu", {"system_gsi", "userdata_gsi"}); @@ -1127,23 +1124,21 @@ vendor /vendor ext4 ro wait,logical,first_stage_mount auto entry = fstab.begin(); - EXPECT_EQ("/data", entry->mount_point); - EXPECT_EQ("userdata_gsi", entry->blk_device); - entry++; - EXPECT_EQ("/system", entry->mount_point); EXPECT_EQ("system_gsi", entry->blk_device); - EXPECT_EQ("erofs", entry->fs_type); entry++; EXPECT_EQ("/system", entry->mount_point); EXPECT_EQ("system_gsi", entry->blk_device); - EXPECT_EQ("ext4", entry->fs_type); entry++; EXPECT_EQ("/vendor", entry->mount_point); EXPECT_EQ("vendor", entry->blk_device); entry++; + + EXPECT_EQ("/data", entry->mount_point); + EXPECT_EQ("userdata_gsi", entry->blk_device); + entry++; } TEST(fs_mgr, TransformFstabForDsu_synthesisExt4Entry) { @@ -1152,7 +1147,7 @@ TEST(fs_mgr, TransformFstabForDsu_synthesisExt4Entry) { std::string fstab_contents = R"fs( system /system erofs ro wait,logical,first_stage_mount vendor /vendor ext4 ro wait,logical,first_stage_mount -data /data f2fs noatime wait,latemount +data /data f2fs noatime wait )fs"; ASSERT_TRUE(android::base::WriteStringToFile(fstab_contents, tf.path)); @@ -1182,39 +1177,3 @@ data /data f2fs noatime wait,latemount EXPECT_EQ("userdata_gsi", entry->blk_device); entry++; } - -TEST(fs_mgr, TransformFstabForDsu_synthesisAllMissingEntries) { - TemporaryFile tf; - ASSERT_TRUE(tf.fd != -1); - std::string fstab_contents = R"fs( -data /data f2fs noatime wait,latemount -vendor /vendor ext4 ro wait,logical,first_stage_mount -)fs"; - - ASSERT_TRUE(android::base::WriteStringToFile(fstab_contents, tf.path)); - - Fstab fstab; - EXPECT_TRUE(ReadFstabFromFile(tf.path, &fstab)); - TransformFstabForDsu(&fstab, "dsu", {"system_gsi", "userdata_gsi"}); - ASSERT_EQ(4U, fstab.size()); - - auto entry = fstab.begin(); - - EXPECT_EQ("/data", entry->mount_point); - EXPECT_EQ("userdata_gsi", entry->blk_device); - entry++; - - EXPECT_EQ("/vendor", entry->mount_point); - EXPECT_EQ("vendor", entry->blk_device); - entry++; - - EXPECT_EQ("/system", entry->mount_point); - EXPECT_EQ("system_gsi", entry->blk_device); - EXPECT_EQ("ext4", entry->fs_type); - entry++; - - EXPECT_EQ("/system", entry->mount_point); - EXPECT_EQ("system_gsi", entry->blk_device); - EXPECT_EQ("erofs", entry->fs_type); - entry++; -} |