diff --git a/fs_mgr/fs_mgr_overlayfs.cpp b/fs_mgr/fs_mgr_overlayfs.cpp index 732567074..fb57715ce 100644 --- a/fs_mgr/fs_mgr_overlayfs.cpp +++ b/fs_mgr/fs_mgr_overlayfs.cpp @@ -16,6 +16,7 @@ #include #include +#include #include #include #include @@ -25,6 +26,7 @@ #include #include #include +#include #include #include @@ -36,6 +38,8 @@ #include #include #include +#include +#include #include #include @@ -112,9 +116,11 @@ bool fs_mgr_filesystem_has_space(const char* mount_point) { bool fs_mgr_overlayfs_enabled(const 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. - return ("squashfs"s == fsrec->fs_type) || !fs_mgr_filesystem_has_space(fsrec->mount_point); + // 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); } constexpr char upper_name[] = "upper"; @@ -191,6 +197,7 @@ bool fs_mgr_wants_overlayfs(const fstab_rec* fsrec) { auto fsrec_mount_point = fsrec->mount_point; if (!fsrec_mount_point) return false; + if (!fsrec->blk_device) return false; if (!fsrec->fs_type) return false; @@ -493,3 +500,25 @@ bool fs_mgr_overlayfs_teardown(const char* mount_point, bool* change) { } #endif // ALLOW_ADBD_DISABLE_VERITY != 0 + +bool fs_mgr_has_shared_blocks(const std::string& mount_point, const std::string& dev) { + struct statfs fs; + if ((statfs((mount_point + "/lost+found").c_str(), &fs) == -1) || + (fs.f_type != EXT4_SUPER_MAGIC)) { + return false; + } + + android::base::unique_fd fd(open(dev.c_str(), O_RDONLY | O_CLOEXEC)); + if (fd < 0) return false; + + struct ext4_super_block sb; + if ((TEMP_FAILURE_RETRY(lseek64(fd, 1024, SEEK_SET)) < 0) || + (TEMP_FAILURE_RETRY(read(fd, &sb, sizeof(sb))) < 0)) { + return false; + } + + struct fs_info info; + if (ext4_parse_sb(&sb, &info) < 0) return false; + + return (info.feat_ro_compat & EXT4_FEATURE_RO_COMPAT_SHARED_BLOCKS) != 0; +} diff --git a/fs_mgr/include/fs_mgr_overlayfs.h b/fs_mgr/include/fs_mgr_overlayfs.h index 1d2ff03f8..ceb45de3e 100644 --- a/fs_mgr/include/fs_mgr_overlayfs.h +++ b/fs_mgr/include/fs_mgr_overlayfs.h @@ -18,7 +18,10 @@ #include +#include + bool fs_mgr_overlayfs_mount_all(); 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); +bool fs_mgr_has_shared_blocks(const std::string& mount_point, const std::string& dev);