Merge "fastboot: Fix flashing failure when a sparse image has an avb footer." into main
diff --git a/bootstat/bootstat.cpp b/bootstat/bootstat.cpp
index 3b8866e..2d55e5a 100644
--- a/bootstat/bootstat.cpp
+++ b/bootstat/bootstat.cpp
@@ -461,6 +461,14 @@
{"reboot,smpl_timeout,pmic,main", 229},
{"reboot,ota,.*", 230},
{"reboot,periodic,.*", 231},
+ {"reboot,early,abl", 232},
+ {"reboot,early,bl2", 233},
+ {"reboot,longkey,pmic_cold", 234},
+ {"reboot,longkey,master_dc", 235},
+ {"reboot,ocp2,pmic,if", 236},
+ {"reboot,ocp,pmic,if", 237},
+ {"reboot,fship", 238},
+ {"reboot,ocp,.*", 239},
};
// Converts a string value representing the reason the system booted to an
diff --git a/fs_mgr/fs_mgr_overlayfs_mount.cpp b/fs_mgr/fs_mgr_overlayfs_mount.cpp
index 66faecd..ae7ed4c 100644
--- a/fs_mgr/fs_mgr_overlayfs_mount.cpp
+++ b/fs_mgr/fs_mgr_overlayfs_mount.cpp
@@ -381,54 +381,86 @@
auto retval = true;
- struct move_entry {
+ struct MoveEntry {
std::string mount_point;
std::string dir;
bool shared_flag;
};
- std::vector<move_entry> move;
+
+ std::vector<MoveEntry> moved_mounts;
auto parent_private = false;
auto parent_made_private = false;
auto dev_private = false;
auto dev_made_private = false;
- for (auto& entry : ReadMountinfoFromFile("/proc/self/mountinfo")) {
+
+ // There could be multiple mount entries with the same mountpoint.
+ // Group these entries together with stable_sort, and keep only the last entry of a group.
+ // Only move mount the last entry in an over mount group, because the other entries are
+ // overshadowed and only the filesystem mounted with the last entry participates in file
+ // pathname resolution.
+ auto mountinfo = ReadMountinfoFromFile("/proc/self/mountinfo");
+ std::stable_sort(mountinfo.begin(), mountinfo.end(), [](const auto& lhs, const auto& rhs) {
+ return lhs.mount_point < rhs.mount_point;
+ });
+ std::reverse(mountinfo.begin(), mountinfo.end());
+ auto erase_from = std::unique(
+ mountinfo.begin(), mountinfo.end(),
+ [](const auto& lhs, const auto& rhs) { return lhs.mount_point == rhs.mount_point; });
+ mountinfo.erase(erase_from, mountinfo.end());
+ std::reverse(mountinfo.begin(), mountinfo.end());
+ // mountinfo is reversed twice, so still is in lexical sorted order.
+
+ for (const auto& entry : mountinfo) {
if ((entry.mount_point == mount_point) && !entry.shared_flag) {
parent_private = true;
}
if ((entry.mount_point == "/dev") && !entry.shared_flag) {
dev_private = true;
}
+ }
+ // Need to make the original mountpoint MS_PRIVATE, so that the overlayfs can be MS_MOVE.
+ // This could happen if its parent mount is remounted later.
+ if (!parent_private) {
+ parent_made_private = fs_mgr_overlayfs_set_shared_mount(mount_point, false);
+ }
+
+ for (const auto& entry : mountinfo) {
+ // Find all immediate submounts.
if (!android::base::StartsWith(entry.mount_point, mount_point + "/")) {
continue;
}
- if (std::find_if(move.begin(), move.end(), [&entry](const auto& it) {
- return android::base::StartsWith(entry.mount_point, it.mount_point + "/");
- }) != move.end()) {
+ // Exclude duplicated or more specific entries.
+ if (std::find_if(moved_mounts.begin(), moved_mounts.end(), [&entry](const auto& it) {
+ return it.mount_point == entry.mount_point ||
+ android::base::StartsWith(entry.mount_point, it.mount_point + "/");
+ }) != moved_mounts.end()) {
continue;
}
+ // mountinfo is in lexical order, so no need to worry about |entry| being a parent mount of
+ // entries of |moved_mounts|.
// use as the bound directory in /dev.
- AutoSetFsCreateCon createcon;
- auto new_context = fs_mgr_get_context(entry.mount_point);
- if (new_context.empty() || !createcon.Set(new_context)) {
- continue;
- }
- move_entry new_entry = {std::move(entry.mount_point), "/dev/TemporaryDir-XXXXXX",
- entry.shared_flag};
- const auto target = mkdtemp(new_entry.dir.data());
- if (!createcon.Restore()) {
- return false;
- }
- if (!target) {
- retval = false;
- PERROR << "temporary directory for MS_BIND";
- continue;
+ MoveEntry new_entry{entry.mount_point, "/dev/TemporaryDir-XXXXXX", entry.shared_flag};
+ {
+ AutoSetFsCreateCon createcon;
+ auto new_context = fs_mgr_get_context(entry.mount_point);
+ if (new_context.empty() || !createcon.Set(new_context)) {
+ continue;
+ }
+ const auto target = mkdtemp(new_entry.dir.data());
+ if (!target) {
+ retval = false;
+ PERROR << "temporary directory for MS_MOVE";
+ continue;
+ }
+ if (!createcon.Restore()) {
+ retval = false;
+ rmdir(new_entry.dir.c_str());
+ continue;
+ }
}
- if (!parent_private && !parent_made_private) {
- parent_made_private = fs_mgr_overlayfs_set_shared_mount(mount_point, false);
- }
if (new_entry.shared_flag) {
new_entry.shared_flag = fs_mgr_overlayfs_set_shared_mount(new_entry.mount_point, false);
}
@@ -437,9 +469,10 @@
if (new_entry.shared_flag) {
fs_mgr_overlayfs_set_shared_mount(new_entry.mount_point, true);
}
+ rmdir(new_entry.dir.c_str());
continue;
}
- move.emplace_back(std::move(new_entry));
+ moved_mounts.push_back(std::move(new_entry));
}
// hijack __mount() report format to help triage
@@ -463,7 +496,7 @@
}
// Move submounts back.
- for (const auto& entry : move) {
+ for (const auto& entry : moved_mounts) {
if (!dev_private && !dev_made_private) {
dev_made_private = fs_mgr_overlayfs_set_shared_mount("/dev", false);
}
@@ -658,22 +691,13 @@
!fs_mgr_wants_overlayfs(&new_entry)) {
continue;
}
- auto new_mount_point = fs_mgr_mount_point(entry.mount_point);
- auto duplicate_or_more_specific = false;
- for (auto it = candidates.begin(); it != candidates.end();) {
- auto it_mount_point = fs_mgr_mount_point(it->mount_point);
- if ((it_mount_point == new_mount_point) ||
- (android::base::StartsWith(new_mount_point, it_mount_point + "/"))) {
- duplicate_or_more_specific = true;
- break;
- }
- if (android::base::StartsWith(it_mount_point, new_mount_point + "/")) {
- it = candidates.erase(it);
- } else {
- ++it;
- }
+ const auto new_mount_point = fs_mgr_mount_point(new_entry.mount_point);
+ if (std::find_if(candidates.begin(), candidates.end(), [&](const auto& it) {
+ return fs_mgr_mount_point(it.mount_point) == new_mount_point;
+ }) != candidates.end()) {
+ continue;
}
- if (!duplicate_or_more_specific) candidates.emplace_back(std::move(new_entry));
+ candidates.push_back(std::move(new_entry));
}
return candidates;
}
diff --git a/fs_mgr/fs_mgr_remount.cpp b/fs_mgr/fs_mgr_remount.cpp
index 4b3a5d3..18892f9 100644
--- a/fs_mgr/fs_mgr_remount.cpp
+++ b/fs_mgr/fs_mgr_remount.cpp
@@ -88,17 +88,6 @@
return entry.mount_point;
}
-const FstabEntry* GetWrappedEntry(const Fstab& overlayfs_candidates, const FstabEntry& entry) {
- auto mount_point = system_mount_point(entry);
- auto it = std::find_if(overlayfs_candidates.begin(), overlayfs_candidates.end(),
- [&mount_point](const auto& entry) {
- return android::base::StartsWith(mount_point,
- system_mount_point(entry) + "/");
- });
- if (it == overlayfs_candidates.end()) return nullptr;
- return &(*it);
-}
-
class MyLogger {
public:
explicit MyLogger(bool verbose) : verbose_(verbose) {}
@@ -196,9 +185,6 @@
if (auto candidate_entry = GetEntryForMountPoint(&candidates, entry.mount_point)) {
return candidate_entry->fs_type == entry.fs_type;
}
- if (GetWrappedEntry(candidates, entry)) {
- return false;
- }
return true;
}
@@ -252,11 +238,6 @@
}
const FstabEntry* entry = &*it;
- if (auto wrap = GetWrappedEntry(candidates, *entry); wrap != nullptr) {
- LOG(INFO) << "partition " << arg << " covered by overlayfs for " << wrap->mount_point
- << ", switching";
- entry = wrap;
- }
// If it's already remounted, include it so it gets gracefully skipped
// later on.