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 &&