diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-07-19 17:08:41 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-07-19 17:08:41 +0000 |
commit | bd7e82772536472f3b0e1682af5b2f2280be58d0 (patch) | |
tree | 628c147ab93b992d7265e46db5e6fdffeffff328 | |
parent | 2af20c4b262bdc46ffb6afe60184319b41829e5e (diff) | |
parent | f0ed21294499ab2dc754ad9784fdeb9aeafd4523 (diff) | |
download | core-bd7e82772536472f3b0e1682af5b2f2280be58d0.tar.gz |
Merge cherrypicks of ['android-review.googlesource.com/2135096', 'android-review.googlesource.com/2135097'] into sparse-10316531-L68800000962056696.
SPARSE_CHANGE: I57132a55a089c7aae3e17c717ecd9dc1047fede8
SPARSE_CHANGE: I4afb443b7e527038fb42424543bb1538b01d5ec9
Change-Id: Ibe1c289e1b4d3af39fa2423139f134632032c37c
-rw-r--r-- | fs_mgr/fs_mgr_fstab.cpp | 171 | ||||
-rw-r--r-- | fs_mgr/tests/fs_mgr_test.cpp | 53 |
2 files changed, 118 insertions, 106 deletions
diff --git a/fs_mgr/fs_mgr_fstab.cpp b/fs_mgr/fs_mgr_fstab.cpp index 8c719c868..98e0f5a40 100644 --- a/fs_mgr/fs_mgr_fstab.cpp +++ b/fs_mgr/fs_mgr_fstab.cpp @@ -502,33 +502,18 @@ std::set<std::string> ExtraBootDevices(const Fstab& fstab) { return boot_devices; } -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; +template <typename Pred> +std::vector<FstabEntry*> GetEntriesByPred(Fstab* fstab, const Pred& pred) { + if (fstab == nullptr) { + return {}; } - return false; + std::vector<FstabEntry*> entries; + for (auto&& entry : *fstab) { + if (pred(entry)) { + entries.push_back(&entry); + } + } + return entries; } } // namespace @@ -591,38 +576,28 @@ 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; } - // userdata has been handled - if (partition == android::gsi::kDsuUserdata) { - continue; - } // scratch is handled by fs_mgr_overlayfs if (partition == android::gsi::kDsuScratch) { 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); + } + } + continue; + } + // Convert RO partitions. + // // dsu_partition_name = corresponding_partition_name + kDsuPostfix // e.g. // system_gsi for system @@ -630,45 +605,51 @@ 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; - 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; + + // 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); } - // 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); + } + + 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, + }})); } } } @@ -857,18 +838,8 @@ FstabEntry* GetEntryForMountPoint(Fstab* fstab, const std::string& path) { } std::vector<FstabEntry*> GetEntriesForMountPoint(Fstab* fstab, const std::string& 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; + return GetEntriesByPred(fstab, + [&path](const FstabEntry& entry) { return entry.mount_point == path; }); } std::set<std::string> GetBootDevices() { diff --git a/fs_mgr/tests/fs_mgr_test.cpp b/fs_mgr/tests/fs_mgr_test.cpp index 6c881c0bf..e33681c3f 100644 --- a/fs_mgr/tests/fs_mgr_test.cpp +++ b/fs_mgr/tests/fs_mgr_test.cpp @@ -1109,14 +1109,17 @@ 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"}); @@ -1124,21 +1127,23 @@ data /data f2fs noatime wait 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) { @@ -1147,7 +1152,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 +data /data f2fs noatime wait,latemount )fs"; ASSERT_TRUE(android::base::WriteStringToFile(fstab_contents, tf.path)); @@ -1177,3 +1182,39 @@ data /data f2fs noatime wait 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++; +} |