summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-07-19 17:08:41 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-07-19 17:08:41 +0000
commitbd7e82772536472f3b0e1682af5b2f2280be58d0 (patch)
tree628c147ab93b992d7265e46db5e6fdffeffff328
parent2af20c4b262bdc46ffb6afe60184319b41829e5e (diff)
parentf0ed21294499ab2dc754ad9784fdeb9aeafd4523 (diff)
downloadcore-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.cpp171
-rw-r--r--fs_mgr/tests/fs_mgr_test.cpp53
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++;
+}