fs_mgr: fs_mgr_has_shared_blocks() needs logical blk_device
For logical partitions, the fstab supplied during
fs_mgr_overlayfs_setup() does not have the correct blk_device and
thus check in fs_mgr_has_shared_blocks() inside
fs_mgr_overlayfs_enabled() will fail to provide the correct status.
Call fs_mgr_update_logical_partition() to fix this up. Side effect
is an API change where fstab can no longer be considered const when
passed into fs_mgr_overlayfs_mount_all() and
fs_mgr_overlayfs_required_devices().
Some additional minor cleanup as well. Move fs_mgr_rm_all() higher
up as-is in the file as it has no dependencies, which will complicate
future changes. Add --help to adb-remount-test.sh unit test script,
improve error handling and checking.
Test: adb-remount-test.sh
Bug: 109821005
Bug: 117605276
Change-Id: I548d3797d49661529490d1a0bf96b63e57491704
diff --git a/fs_mgr/fs_mgr_overlayfs.cpp b/fs_mgr/fs_mgr_overlayfs.cpp
index ad488a9..d9842f7 100644
--- a/fs_mgr/fs_mgr_overlayfs.cpp
+++ b/fs_mgr/fs_mgr_overlayfs.cpp
@@ -41,6 +41,7 @@
#include <android-base/strings.h>
#include <android-base/unique_fd.h>
#include <ext4_utils/ext4_utils.h>
+#include <fs_mgr.h>
#include <fs_mgr_dm_linear.h>
#include <fs_mgr_overlayfs.h>
#include <fstab/fstab.h>
@@ -127,13 +128,63 @@
return (vst.f_bfree >= (vst.f_blocks * kPercentThreshold / 100));
}
-bool fs_mgr_overlayfs_enabled(const struct fstab_rec* fsrec) {
+bool fs_mgr_overlayfs_enabled(struct fstab_rec* fsrec) {
// readonly filesystem, can not be mount -o remount,rw
// if squashfs or if free space is (near) zero making such a remount
// virtually useless, or if there are shared blocks that prevent remount,rw
- return ("squashfs"s == fsrec->fs_type) ||
- fs_mgr_has_shared_blocks(fsrec->mount_point, fsrec->blk_device) ||
- !fs_mgr_filesystem_has_space(fsrec->mount_point);
+ if (("squashfs"s == fsrec->fs_type) || !fs_mgr_filesystem_has_space(fsrec->mount_point)) {
+ return true;
+ }
+ if (fs_mgr_is_logical(fsrec)) {
+ fs_mgr_update_logical_partition(fsrec);
+ }
+ return fs_mgr_has_shared_blocks(fsrec->mount_point, fsrec->blk_device);
+}
+
+bool fs_mgr_rm_all(const std::string& path, bool* change = nullptr, int level = 0) {
+ auto save_errno = errno;
+ std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(path.c_str()), closedir);
+ if (!dir) {
+ if (errno == ENOENT) {
+ errno = save_errno;
+ return true;
+ }
+ PERROR << "opendir " << path << " depth=" << level;
+ if ((errno == EPERM) && (level != 0)) {
+ errno = save_errno;
+ return true;
+ }
+ return false;
+ }
+ dirent* entry;
+ auto ret = true;
+ while ((entry = readdir(dir.get()))) {
+ if (("."s == entry->d_name) || (".."s == entry->d_name)) continue;
+ auto file = path + "/" + entry->d_name;
+ if (entry->d_type == DT_UNKNOWN) {
+ struct stat st;
+ save_errno = errno;
+ if (!lstat(file.c_str(), &st) && (st.st_mode & S_IFDIR)) entry->d_type = DT_DIR;
+ errno = save_errno;
+ }
+ if (entry->d_type == DT_DIR) {
+ ret &= fs_mgr_rm_all(file, change, level + 1);
+ if (!rmdir(file.c_str())) {
+ if (change) *change = true;
+ } else {
+ if (errno != ENOENT) ret = false;
+ PERROR << "rmdir " << file << " depth=" << level;
+ }
+ continue;
+ }
+ if (!unlink(file.c_str())) {
+ if (change) *change = true;
+ } else {
+ if (errno != ENOENT) ret = false;
+ PERROR << "rm " << file << " depth=" << level;
+ }
+ }
+ return ret;
}
const auto kUpperName = "upper"s;
@@ -235,7 +286,7 @@
return ret;
}
-bool fs_mgr_wants_overlayfs(const fstab_rec* fsrec) {
+bool fs_mgr_wants_overlayfs(fstab_rec* fsrec) {
if (!fsrec) return false;
auto fsrec_mount_point = fsrec->mount_point;
@@ -260,53 +311,6 @@
return true;
}
-
-bool fs_mgr_rm_all(const std::string& path, bool* change = nullptr, int level = 0) {
- auto save_errno = errno;
- std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(path.c_str()), closedir);
- if (!dir) {
- if (errno == ENOENT) {
- errno = save_errno;
- return true;
- }
- PERROR << "opendir " << path << " depth=" << level;
- if ((errno == EPERM) && (level != 0)) {
- errno = save_errno;
- return true;
- }
- return false;
- }
- dirent* entry;
- auto ret = true;
- while ((entry = readdir(dir.get()))) {
- if (("."s == entry->d_name) || (".."s == entry->d_name)) continue;
- auto file = path + "/" + entry->d_name;
- if (entry->d_type == DT_UNKNOWN) {
- struct stat st;
- save_errno = errno;
- if (!lstat(file.c_str(), &st) && (st.st_mode & S_IFDIR)) entry->d_type = DT_DIR;
- errno = save_errno;
- }
- if (entry->d_type == DT_DIR) {
- ret &= fs_mgr_rm_all(file, change, level + 1);
- if (!rmdir(file.c_str())) {
- if (change) *change = true;
- } else {
- if (errno != ENOENT) ret = false;
- PERROR << "rmdir " << file << " depth=" << level;
- }
- continue;
- }
- if (!unlink(file.c_str())) {
- if (change) *change = true;
- } else {
- if (errno != ENOENT) ret = false;
- PERROR << "rm " << file << " depth=" << level;
- }
- }
- return ret;
-}
-
constexpr char kOverlayfsFileContext[] = "u:object_r:overlayfs_file:s0";
bool fs_mgr_overlayfs_setup_dir(const std::string& dir, std::string* overlay, bool* change) {
@@ -532,8 +536,7 @@
}
}
-std::vector<std::string> fs_mgr_candidate_list(const fstab* fstab,
- const char* mount_point = nullptr) {
+std::vector<std::string> fs_mgr_candidate_list(fstab* fstab, const char* mount_point = nullptr) {
std::vector<std::string> mounts;
if (!fstab) return mounts;
@@ -734,7 +737,7 @@
} // namespace
-bool fs_mgr_overlayfs_mount_all(const fstab* fstab) {
+bool fs_mgr_overlayfs_mount_all(fstab* fstab) {
auto ret = false;
if (!fs_mgr_wants_overlayfs()) return ret;
@@ -761,7 +764,7 @@
return ret;
}
-std::vector<std::string> fs_mgr_overlayfs_required_devices(const fstab* fstab) {
+std::vector<std::string> fs_mgr_overlayfs_required_devices(fstab* fstab) {
if (fs_mgr_get_entry_for_mount_point(const_cast<struct fstab*>(fstab), kScratchMountPoint)) {
return {};
}
diff --git a/fs_mgr/include/fs_mgr_overlayfs.h b/fs_mgr/include/fs_mgr_overlayfs.h
index 3274e0e..550dd18 100644
--- a/fs_mgr/include/fs_mgr_overlayfs.h
+++ b/fs_mgr/include/fs_mgr_overlayfs.h
@@ -21,8 +21,8 @@
#include <string>
#include <vector>
-bool fs_mgr_overlayfs_mount_all(const fstab* fstab);
-std::vector<std::string> fs_mgr_overlayfs_required_devices(const fstab* fstab);
+bool fs_mgr_overlayfs_mount_all(fstab* fstab);
+std::vector<std::string> fs_mgr_overlayfs_required_devices(fstab* fstab);
bool fs_mgr_overlayfs_setup(const char* backing = nullptr, const char* mount_point = nullptr,
bool* change = nullptr);
bool fs_mgr_overlayfs_teardown(const char* mount_point = nullptr, bool* change = nullptr);
diff --git a/fs_mgr/tests/adb-remount-test.sh b/fs_mgr/tests/adb-remount-test.sh
index d4ca574..497f33f 100755
--- a/fs_mgr/tests/adb-remount-test.sh
+++ b/fs_mgr/tests/adb-remount-test.sh
@@ -1,14 +1,21 @@
#! /bin/bash
-#
-# adb remount tests (overlayfs focus)
-#
-# Conditions:
-# - Must be a userdebug build.
-# - Must be in adb mode.
-# - Kernel must have overlayfs enabled and patched to support override_creds.
-# - Must have either squashfs, ext4-dedupe or right-sized partitions.
-# - Minimum expectation system and vender are overlayfs covered partitions.
-#
+
+USAGE="USAGE: `basename ${0}` [-s <SerialNumber>]
+
+adb remount tests (overlayfs focus)
+
+Conditions:
+ - Must be a userdebug build.
+ - Must be in adb mode.
+ - Kernel must have overlayfs enabled and patched to support override_creds.
+ - Must have either squashfs, ext4-dedupe or right-sized partitions.
+ - Minimum expectation system and vender are overlayfs covered partitions.
+"
+
+if [ X"${1}" = X"--help" -o X"${1}" = X"-h" -o X"${1}" = X"-?" ]; then
+ echo "${USAGE}" >&2
+ exit 0
+fi
# Helper Variables
@@ -86,11 +93,15 @@
adb reboot remount-test
}
-[ "USAGE: adb_wait
+[ "USAGE: adb_wait [timeout]
-Returns: waits until the device has returned" ]
+Returns: waits until the device has returned or the optional timeout" ]
adb_wait() {
- adb wait-for-device
+ if [ -n "${1}" ]; then
+ timeout --preserve-status --signal=KILL ${1} adb wait-for-device
+ else
+ adb wait-for-device
+ fi
}
[ "USAGE: adb_root
@@ -178,6 +189,10 @@
fi
inFastboot && die "device in fastboot mode"
+if ! inAdb; then
+ echo "${ORANGE}[ WARNING ]${NORMAL} device not in adb mode ... waiting 2 minutes"
+ adb_wait 2m
+fi
inAdb || die "device not in adb mode"
isDebuggable || die "device not a debug build"
@@ -205,8 +220,9 @@
adb_reboot &&
adb_wait &&
adb_sh df -k </dev/null | head -1 &&
- adb_sh df -k </dev/null | grep "^overlay " &&
- adb_sh df -k </dev/null | grep "^overlay .* /system\$" >/dev/null ||
+ adb_sh df -k </dev/null | grep "^overlay " ||
+ die "overlay takeover failed"
+adb_sh df -k </dev/null | grep "^overlay .* /system\$" >/dev/null ||
echo "${ORANGE}[ WARNING ]${NORMAL} overlay takeover before remount not complete" >&2
adb_root &&