diff --git a/fs_mgr/fs_mgr_overlayfs.cpp b/fs_mgr/fs_mgr_overlayfs.cpp index ad488a98d..d9842f7c2 100644 --- a/fs_mgr/fs_mgr_overlayfs.cpp +++ b/fs_mgr/fs_mgr_overlayfs.cpp @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -127,13 +128,63 @@ bool fs_mgr_filesystem_has_space(const char* mount_point) { 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(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 @@ std::vector fs_mgr_overlayfs_verity_enabled_list() { 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 @@ bool fs_mgr_wants_overlayfs(const fstab_rec* fsrec) { 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(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 @@ bool fs_mgr_overlayfs_mount(const std::string& mount_point) { } } -std::vector fs_mgr_candidate_list(const fstab* fstab, - const char* mount_point = nullptr) { +std::vector fs_mgr_candidate_list(fstab* fstab, const char* mount_point = nullptr) { std::vector mounts; if (!fstab) return mounts; @@ -734,7 +737,7 @@ bool fs_mgr_overlayfs_scratch_can_be_mounted(const std::string& scratch_device) } // 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 @@ bool fs_mgr_overlayfs_mount_all(const fstab* fstab) { return ret; } -std::vector fs_mgr_overlayfs_required_devices(const fstab* fstab) { +std::vector fs_mgr_overlayfs_required_devices(fstab* fstab) { if (fs_mgr_get_entry_for_mount_point(const_cast(fstab), kScratchMountPoint)) { return {}; } diff --git a/fs_mgr/include/fs_mgr_overlayfs.h b/fs_mgr/include/fs_mgr_overlayfs.h index 3274e0ec3..550dd1862 100644 --- a/fs_mgr/include/fs_mgr_overlayfs.h +++ b/fs_mgr/include/fs_mgr_overlayfs.h @@ -21,8 +21,8 @@ #include #include -bool fs_mgr_overlayfs_mount_all(const fstab* fstab); -std::vector fs_mgr_overlayfs_required_devices(const fstab* fstab); +bool fs_mgr_overlayfs_mount_all(fstab* fstab); +std::vector 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 d4ca57496..497f33f86 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 ] + +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() { 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 @@ if [ X"-s" = X"${1}" -a -n "${2}" ]; then 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_sh ls -d /cache/overlay /dev/null 2>&1 || adb_reboot && adb_wait && adb_sh df -k /dev/null || + adb_sh df -k /dev/null || echo "${ORANGE}[ WARNING ]${NORMAL} overlay takeover before remount not complete" >&2 adb_root &&