Loading fs_mgr/fs_mgr_overlayfs.cpp +37 −83 Original line number Diff line number Diff line Loading @@ -785,8 +785,7 @@ bool fs_mgr_overlayfs_mount(const std::string& mount_point) { } // Mount kScratchMountPoint bool fs_mgr_overlayfs_mount_scratch(const std::string& device_path, const std::string mnt_type, bool readonly = false) { bool MountScratch(const std::string& device_path, bool readonly = false) { if (readonly) { if (!fs_mgr_access(device_path)) { LOG(ERROR) << "Path does not exist: " << device_path; Loading @@ -797,9 +796,12 @@ bool fs_mgr_overlayfs_mount_scratch(const std::string& device_path, const std::s return false; } auto f2fs = fs_mgr_is_f2fs(device_path); auto ext4 = fs_mgr_is_ext4(device_path); if (!f2fs && !ext4) { std::vector<const char*> filesystem_candidates; if (fs_mgr_is_f2fs(device_path)) { filesystem_candidates = {"f2fs", "ext4"}; } else if (fs_mgr_is_ext4(device_path)) { filesystem_candidates = {"ext4", "f2fs"}; } else { LOG(ERROR) << "Scratch partition is not f2fs or ext4"; return false; } Loading @@ -816,11 +818,7 @@ bool fs_mgr_overlayfs_mount_scratch(const std::string& device_path, const std::s FstabEntry entry; entry.blk_device = device_path; entry.mount_point = kScratchMountPoint; entry.fs_type = mnt_type; if ((mnt_type == "f2fs") && !f2fs) entry.fs_type = "ext4"; if ((mnt_type == "ext4") && !ext4) entry.fs_type = "f2fs"; entry.flags = MS_NOATIME | MS_RDONLY; auto mounted = true; if (!readonly) { entry.flags &= ~MS_RDONLY; entry.flags |= MS_SYNCHRONOUS; Loading @@ -831,14 +829,12 @@ bool fs_mgr_overlayfs_mount_scratch(const std::string& device_path, const std::s if (fs_mgr_overlayfs_already_mounted("/data", false)) { entry.fs_mgr_flags.check = true; } if (mounted) mounted = fs_mgr_do_mount_one(entry) == 0; if (!mounted) { if ((entry.fs_type == "f2fs") && ext4) { entry.fs_type = "ext4"; mounted = fs_mgr_do_mount_one(entry) == 0; } else if ((entry.fs_type == "ext4") && f2fs) { entry.fs_type = "f2fs"; mounted = fs_mgr_do_mount_one(entry) == 0; bool mounted = false; for (auto fs_type : filesystem_candidates) { entry.fs_type = fs_type; if (fs_mgr_do_mount_one(entry) == 0) { mounted = true; break; } } if (!createcon.Restore()) { Loading @@ -854,39 +850,6 @@ bool fs_mgr_overlayfs_mount_scratch(const std::string& device_path, const std::s const std::string kMkF2fs("/system/bin/make_f2fs"); const std::string kMkExt4("/system/bin/mke2fs"); // Only a suggestion for _first_ try during mounting std::string fs_mgr_overlayfs_scratch_mount_type() { if (!access(kMkF2fs.c_str(), X_OK) && fs_mgr_filesystem_available("f2fs")) { return "f2fs"; } if (!access(kMkExt4.c_str(), X_OK) && fs_mgr_filesystem_available("ext4")) { return "ext4"; } return "auto"; } // Note: we do not check access() here except for the super partition, since // in first-stage init we wouldn't have registed by-name symlinks for "other" // partitions that won't be mounted. static std::string GetPhysicalScratchDevice() { auto slot_number = fs_mgr_overlayfs_slot_number(); auto super_device = fs_mgr_overlayfs_super_device(slot_number); auto path = fs_mgr_overlayfs_super_device(slot_number == 0); if (super_device != path) { return path; } if (fs_mgr_access(super_device)) { // Do not try to use system_other on a DAP device. return ""; } auto other_slot = fs_mgr_get_other_slot_suffix(); if (!other_slot.empty()) { return kPhysicalDevice + "system" + other_slot; } return ""; } // Note: The scratch partition of DSU is managed by gsid, and should be initialized during // first-stage-mount. Just check if the DM device for DSU scratch partition is created or not. static std::string GetDsuScratchDevice() { Loading Loading @@ -923,27 +886,30 @@ static std::string GetBootScratchDevice() { return device; } // There is no dynamic scratch, so try and find a physical one. return GetPhysicalScratchDevice(); return ""; } bool fs_mgr_overlayfs_make_scratch(const std::string& scratch_device, const std::string& mnt_type) { bool MakeScratchFilesystem(const std::string& scratch_device) { // Force mkfs by design for overlay support of adb remount, simplify and // thus do not rely on fsck to correct problems that could creep in. auto fs_type = ""s; auto command = ""s; if (mnt_type == "f2fs") { if (!access(kMkF2fs.c_str(), X_OK) && fs_mgr_filesystem_available("f2fs")) { fs_type = "f2fs"; command = kMkF2fs + " -w 4096 -f -d1 -l" + android::base::Basename(kScratchMountPoint); } else if (mnt_type == "ext4") { } else if (!access(kMkExt4.c_str(), X_OK) && fs_mgr_filesystem_available("ext4")) { fs_type = "ext4"; command = kMkExt4 + " -F -b 4096 -t ext4 -m 0 -O has_journal -M " + kScratchMountPoint; } else { LERROR << mnt_type << " has no mkfs cookbook"; LERROR << "No supported mkfs command or filesystem driver available, supported filesystems " "are: f2fs, ext4"; return false; } command += " " + scratch_device + " >/dev/null 2>/dev/null </dev/null"; fs_mgr_set_blk_ro(scratch_device, false); auto ret = system(command.c_str()); if (ret) { LERROR << "make " << mnt_type << " filesystem on " << scratch_device << " return=" << ret; LERROR << "make " << fs_type << " filesystem on " << scratch_device << " return=" << ret; return false; } return true; Loading Loading @@ -1123,7 +1089,7 @@ static bool CreateScratchOnData(std::string* scratch_device, bool* partition_exi return true; } static bool CanUseSuperPartition(const Fstab& fstab, bool* is_virtual_ab) { static bool CanUseSuperPartition(const Fstab& fstab) { auto slot_number = fs_mgr_overlayfs_slot_number(); auto super_device = fs_mgr_overlayfs_super_device(slot_number); if (!fs_mgr_rw_access(super_device) || !fs_mgr_overlayfs_has_logical(fstab)) { Loading @@ -1133,7 +1099,6 @@ static bool CanUseSuperPartition(const Fstab& fstab, bool* is_virtual_ab) { if (!metadata) { return false; } *is_virtual_ab = !!(metadata->header.flags & LP_HEADER_FLAG_VIRTUAL_AB_DEVICE); return true; } Loading @@ -1146,23 +1111,15 @@ bool fs_mgr_overlayfs_create_scratch(const Fstab& fstab, std::string* scratch_de return *partition_exists; } // Try a physical partition first. *scratch_device = GetPhysicalScratchDevice(); if (!scratch_device->empty() && fs_mgr_rw_access(*scratch_device)) { *partition_exists = true; return true; } // If that fails, see if we can land on super. bool is_virtual_ab; if (CanUseSuperPartition(fstab, &is_virtual_ab)) { // Try ImageManager on /data first. bool can_use_data = false; if (is_virtual_ab && FilesystemHasReliablePinning("/data", &can_use_data) && can_use_data) { if (FilesystemHasReliablePinning("/data", &can_use_data) && can_use_data) { return CreateScratchOnData(scratch_device, partition_exists); } // If that fails, see if we can land on super. if (CanUseSuperPartition(fstab)) { return CreateDynamicScratch(scratch_device, partition_exists); } return false; } Loading @@ -1180,9 +1137,8 @@ bool fs_mgr_overlayfs_setup_scratch(const Fstab& fstab) { } // If the partition exists, assume first that it can be mounted. auto mnt_type = fs_mgr_overlayfs_scratch_mount_type(); if (partition_exists) { if (fs_mgr_overlayfs_mount_scratch(scratch_device, mnt_type)) { if (MountScratch(scratch_device)) { if (fs_mgr_access(kScratchMountPoint + kOverlayTopDir) || fs_mgr_filesystem_has_space(kScratchMountPoint)) { return true; Loading @@ -1195,12 +1151,12 @@ bool fs_mgr_overlayfs_setup_scratch(const Fstab& fstab) { } } if (!fs_mgr_overlayfs_make_scratch(scratch_device, mnt_type)) { if (!MakeScratchFilesystem(scratch_device)) { LOG(ERROR) << "Failed to format scratch partition"; return false; } return fs_mgr_overlayfs_mount_scratch(scratch_device, mnt_type); return MountScratch(scratch_device); } #if ALLOW_ADBD_DISABLE_VERITY Loading Loading @@ -1319,14 +1275,13 @@ static void TryMountScratch() { if (!WaitForFile(scratch_device, 10s)) { return; } const auto mount_type = fs_mgr_overlayfs_scratch_mount_type(); if (!fs_mgr_overlayfs_mount_scratch(scratch_device, mount_type, true /* readonly */)) { if (!MountScratch(scratch_device, true /* readonly */)) { return; } auto has_overlayfs_dir = fs_mgr_access(kScratchMountPoint + kOverlayTopDir); fs_mgr_overlayfs_umount_scratch(); if (has_overlayfs_dir) { fs_mgr_overlayfs_mount_scratch(scratch_device, mount_type); MountScratch(scratch_device); } } Loading Loading @@ -1565,8 +1520,7 @@ OverlayfsTeardownResult fs_mgr_overlayfs_teardown(const char* mount_point, bool* if ((mount_point != nullptr) && !fs_mgr_overlayfs_already_mounted(kScratchMountPoint, false)) { std::string scratch_device = GetBootScratchDevice(); if (!scratch_device.empty()) { mount_scratch = fs_mgr_overlayfs_mount_scratch(scratch_device, fs_mgr_overlayfs_scratch_mount_type()); mount_scratch = MountScratch(scratch_device); } } Loading Loading @@ -1687,7 +1641,7 @@ void TeardownAllOverlayForMountPoint(const std::string& mount_point) { if (auto info = EnsureScratchMapped(); info.has_value()) { // Map scratch device, mount kScratchMountPoint and teardown kScratchMountPoint. fs_mgr_overlayfs_umount_scratch(); if (fs_mgr_overlayfs_mount_scratch(info->device, fs_mgr_overlayfs_scratch_mount_type())) { if (MountScratch(info->device)) { bool should_destroy_scratch = false; fs_mgr_overlayfs_teardown_one(kScratchMountPoint, teardown_dir, ignore_change, &should_destroy_scratch); Loading @@ -1702,7 +1656,7 @@ void TeardownAllOverlayForMountPoint(const std::string& mount_point) { std::string scratch_device; if (MapDsuScratchDevice(&scratch_device)) { fs_mgr_overlayfs_umount_scratch(); if (fs_mgr_overlayfs_mount_scratch(scratch_device, fs_mgr_overlayfs_scratch_mount_type())) { if (MountScratch(scratch_device)) { fs_mgr_overlayfs_teardown_one(kScratchMountPoint, teardown_dir, ignore_change); fs_mgr_overlayfs_umount_scratch(); } Loading fs_mgr/tests/adb-remount-test.sh +53 −61 Original line number Diff line number Diff line Loading @@ -1241,40 +1241,45 @@ adb_sh grep -qE " (/system|/) [^ ]* rw," /proc/mounts </dev/null || adb_sh grep -q " /vendor [^ ]* rw," /proc/mounts </dev/null || die -t "${T}" "/vendor is not RW" scratch_on_super=false if ${overlayfs_needed}; then is_overlayfs_mounted || die -t "${T}" "expected overlay takeover" else is_overlayfs_mounted && die -t "${T}" "unexpected overlay takeover" fi is_overlayfs_mounted /system || die -t "${T}" "expected overlay to takeover /system after remount" # If scratch_partition && uses_dynamic_scratch, then scratch is on super. # If scratch_partition && !uses_dynamic_scratch, then scratch is super_other, system_other. # If !scratch_partition, then scratch is on /data via image_manager. uses_dynamic_scratch=false scratch_partition= virtual_ab=$(get_property ro.virtual_ab.enabled) if ${overlayfs_needed}; then # Collect information about the scratch device if we have one M=$(adb_sh cat /proc/mounts </dev/null | awk '$2 == "/mnt/scratch" { print $1, $3; exit }') [ -z "${M}" ] && die "cannot find any scratch device mounted on /mnt/scratch" if [ -n "${M}" ]; then scratch_device=$(echo "${M}" | awk '{ print $1 }') scratch_filesystem=$(echo "${M}" | awk '{ print $2 }') scratch_size=$(adb_sh df -k "${scratch_device}" </dev/null | tail +2 | head -1 | awk '{ print $2 }') [ -z "${scratch_size}" ] && die "cannot get size of scratch device (${scratch_device})" if [ -n "${virtual_ab}" ]; then LOG INFO "using dynamic scratch partition on /data (VAB device)" elif [[ "${scratch_device}" == /dev/block/by-name/* ]]; then scratch_partition="${scratch_device##/dev/block/by-name/}" LOG INFO "using physical scratch partition ${scratch_partition}" else uses_dynamic_scratch=true scratch_partition=scratch # Detect scratch partition backed by super? for b in "/dev/block/by-name/super"{,_${ACTIVE_SLOT}}; do if adb_test -e "${b}"; then device=$(adb_su realpath "${b}") D=$(adb_su stat -c '0x%t 0x%T' "${device}") major=$(echo "${D}" | awk '{ print $1 }') minor=$(echo "${D}" | awk '{ print $2 }') super_devt=$(( major )):$(( minor )) if adb_su dmctl table scratch | tail +2 | grep -q -w "${super_devt}"; then scratch_on_super=true fi break fi done if ${scratch_on_super}; then LOG INFO "using dynamic scratch partition on super" else LOG INFO "using dynamic scratch partition on /data (VAB device)" fi LOG INFO "scratch device ${scratch_device} filesystem ${scratch_filesystem} size ${scratch_size}KiB" else LOG INFO "cannot find any scratch device mounted on /mnt/scratch, using scratch on /cache" fi for d in ${OVERLAYFS_BACKING}; do if adb_test -d /${d}/overlay/system/upper; then Loading @@ -1283,8 +1288,6 @@ if ${overlayfs_needed}; then done data_device=$(adb_sh awk '$2 == "/data" { print $1; exit }' /proc/mounts) is_overlayfs_mounted /system 2>/dev/null || die -t "${T}" "expected overlay to takeover /system after remount" # KISS (we do not support sub-mounts for system partitions currently) adb_sh grep "^overlay " /proc/mounts </dev/null | grep -vE "^overlay.* /(apex|system|vendor)/[^ ]" | Loading Loading @@ -1312,6 +1315,8 @@ if ${overlayfs_needed}; then die "remount overlayfs missed a spot (rw)" fi done else is_overlayfs_mounted && die -t "${T}" "unexpected overlay takeover" fi LOG OK "adb remount RW" Loading Loading @@ -1455,31 +1460,18 @@ else fastboot_getvar is-userspace yes && is_userspace_fastboot=true # check ${scratch_partition} via fastboot if [ -n "${scratch_partition}" ]; then fastboot_getvar partition-type:${scratch_partition} raw || ( fastboot reboot && false) || die "fastboot can not see ${scratch_partition} parameters" if ${uses_dynamic_scratch}; then fastboot_getvar has-slot:${scratch_partition} no && fastboot_getvar is-logical:${scratch_partition} yes || ( fastboot reboot && false) || die "fastboot can not see ${scratch_partition} parameters" LOG INFO "expect fastboot erase ${scratch_partition} to fail" fastboot erase ${scratch_partition} && ( fastboot reboot || true) && die "fastboot can erase ${scratch_partition}" else fastboot_getvar is-logical:${scratch_partition} no || ( fastboot reboot && false) || die "fastboot can not see ${scratch_partition} parameters" fastboot reboot-bootloader || die "fastboot reboot bootloader" fi LOG INFO "expect fastboot format ${scratch_partition} to fail" fastboot format ${scratch_partition} && ( fastboot reboot || true) && die "fastboot can format ${scratch_partition}" if ${scratch_on_super}; then fastboot_getvar partition-type:scratch raw || die "fastboot cannot see parameter partition-type:scratch" fastboot_getvar has-slot:scratch no || die "fastboot cannot see parameter has-slot:scratch" fastboot_getvar is-logical:scratch yes || die "fastboot cannot see parameter is-logical:scratch" LOG INFO "expect fastboot erase scratch to fail" fastboot erase scratch && die "fastboot can erase scratch" LOG INFO "expect fastboot format scratch to fail" fastboot format scratch && die "fastboot can format scratch" fi fastboot reboot || die "cannot reboot out of fastboot" Loading Loading @@ -1539,9 +1531,9 @@ for i in ${MOUNTS} /system/priv-app; do done ################################################################################ if ${is_bootloader_fastboot} && [ -n "${scratch_partition}" ]; then if ${is_bootloader_fastboot} && ${scratch_on_super}; then LOG RUN "test fastboot flash to ${scratch_partition} recovery" LOG RUN "test fastboot flash to scratch recovery" avc_check adb reboot fastboot </dev/null || Loading @@ -1550,15 +1542,15 @@ if ${is_bootloader_fastboot} && [ -n "${scratch_partition}" ]; then dd if=/dev/zero of=${img} bs=4096 count=16 2>/dev/null && fastboot_wait ${FASTBOOT_WAIT} || die "reboot into fastboot to flash scratch `usb_status`" fastboot flash --force ${scratch_partition} ${img} fastboot flash --force scratch ${img} err=${?} fastboot reboot || die "can not reboot out of fastboot" [ 0 -eq ${err} ] || die "fastboot flash ${scratch_partition}" die "fastboot flash scratch" adb_wait ${ADB_WAIT} && adb_root || die "did not reboot after flashing empty ${scratch_partition} `usb_status`" die "did not reboot after flashing empty scratch $(usb_status)" T=`adb_date` D=`adb disable-verity 2>&1` err=${?} Loading @@ -1578,7 +1570,7 @@ if ${is_bootloader_fastboot} && [ -n "${scratch_partition}" ]; then [ ${err} = 0 ] && [ X"${D}" = X"${D##*setup failed}" ] && [ X"${D}" != X"${D##*[Uu]sing overlayfs}" ] && LOG OK "${scratch_partition} recreated" || LOG OK "recreated scratch" || die -t ${T} "setup for overlayfs" adb remount >&2 || die -t ${T} "remount failed" Loading Loading
fs_mgr/fs_mgr_overlayfs.cpp +37 −83 Original line number Diff line number Diff line Loading @@ -785,8 +785,7 @@ bool fs_mgr_overlayfs_mount(const std::string& mount_point) { } // Mount kScratchMountPoint bool fs_mgr_overlayfs_mount_scratch(const std::string& device_path, const std::string mnt_type, bool readonly = false) { bool MountScratch(const std::string& device_path, bool readonly = false) { if (readonly) { if (!fs_mgr_access(device_path)) { LOG(ERROR) << "Path does not exist: " << device_path; Loading @@ -797,9 +796,12 @@ bool fs_mgr_overlayfs_mount_scratch(const std::string& device_path, const std::s return false; } auto f2fs = fs_mgr_is_f2fs(device_path); auto ext4 = fs_mgr_is_ext4(device_path); if (!f2fs && !ext4) { std::vector<const char*> filesystem_candidates; if (fs_mgr_is_f2fs(device_path)) { filesystem_candidates = {"f2fs", "ext4"}; } else if (fs_mgr_is_ext4(device_path)) { filesystem_candidates = {"ext4", "f2fs"}; } else { LOG(ERROR) << "Scratch partition is not f2fs or ext4"; return false; } Loading @@ -816,11 +818,7 @@ bool fs_mgr_overlayfs_mount_scratch(const std::string& device_path, const std::s FstabEntry entry; entry.blk_device = device_path; entry.mount_point = kScratchMountPoint; entry.fs_type = mnt_type; if ((mnt_type == "f2fs") && !f2fs) entry.fs_type = "ext4"; if ((mnt_type == "ext4") && !ext4) entry.fs_type = "f2fs"; entry.flags = MS_NOATIME | MS_RDONLY; auto mounted = true; if (!readonly) { entry.flags &= ~MS_RDONLY; entry.flags |= MS_SYNCHRONOUS; Loading @@ -831,14 +829,12 @@ bool fs_mgr_overlayfs_mount_scratch(const std::string& device_path, const std::s if (fs_mgr_overlayfs_already_mounted("/data", false)) { entry.fs_mgr_flags.check = true; } if (mounted) mounted = fs_mgr_do_mount_one(entry) == 0; if (!mounted) { if ((entry.fs_type == "f2fs") && ext4) { entry.fs_type = "ext4"; mounted = fs_mgr_do_mount_one(entry) == 0; } else if ((entry.fs_type == "ext4") && f2fs) { entry.fs_type = "f2fs"; mounted = fs_mgr_do_mount_one(entry) == 0; bool mounted = false; for (auto fs_type : filesystem_candidates) { entry.fs_type = fs_type; if (fs_mgr_do_mount_one(entry) == 0) { mounted = true; break; } } if (!createcon.Restore()) { Loading @@ -854,39 +850,6 @@ bool fs_mgr_overlayfs_mount_scratch(const std::string& device_path, const std::s const std::string kMkF2fs("/system/bin/make_f2fs"); const std::string kMkExt4("/system/bin/mke2fs"); // Only a suggestion for _first_ try during mounting std::string fs_mgr_overlayfs_scratch_mount_type() { if (!access(kMkF2fs.c_str(), X_OK) && fs_mgr_filesystem_available("f2fs")) { return "f2fs"; } if (!access(kMkExt4.c_str(), X_OK) && fs_mgr_filesystem_available("ext4")) { return "ext4"; } return "auto"; } // Note: we do not check access() here except for the super partition, since // in first-stage init we wouldn't have registed by-name symlinks for "other" // partitions that won't be mounted. static std::string GetPhysicalScratchDevice() { auto slot_number = fs_mgr_overlayfs_slot_number(); auto super_device = fs_mgr_overlayfs_super_device(slot_number); auto path = fs_mgr_overlayfs_super_device(slot_number == 0); if (super_device != path) { return path; } if (fs_mgr_access(super_device)) { // Do not try to use system_other on a DAP device. return ""; } auto other_slot = fs_mgr_get_other_slot_suffix(); if (!other_slot.empty()) { return kPhysicalDevice + "system" + other_slot; } return ""; } // Note: The scratch partition of DSU is managed by gsid, and should be initialized during // first-stage-mount. Just check if the DM device for DSU scratch partition is created or not. static std::string GetDsuScratchDevice() { Loading Loading @@ -923,27 +886,30 @@ static std::string GetBootScratchDevice() { return device; } // There is no dynamic scratch, so try and find a physical one. return GetPhysicalScratchDevice(); return ""; } bool fs_mgr_overlayfs_make_scratch(const std::string& scratch_device, const std::string& mnt_type) { bool MakeScratchFilesystem(const std::string& scratch_device) { // Force mkfs by design for overlay support of adb remount, simplify and // thus do not rely on fsck to correct problems that could creep in. auto fs_type = ""s; auto command = ""s; if (mnt_type == "f2fs") { if (!access(kMkF2fs.c_str(), X_OK) && fs_mgr_filesystem_available("f2fs")) { fs_type = "f2fs"; command = kMkF2fs + " -w 4096 -f -d1 -l" + android::base::Basename(kScratchMountPoint); } else if (mnt_type == "ext4") { } else if (!access(kMkExt4.c_str(), X_OK) && fs_mgr_filesystem_available("ext4")) { fs_type = "ext4"; command = kMkExt4 + " -F -b 4096 -t ext4 -m 0 -O has_journal -M " + kScratchMountPoint; } else { LERROR << mnt_type << " has no mkfs cookbook"; LERROR << "No supported mkfs command or filesystem driver available, supported filesystems " "are: f2fs, ext4"; return false; } command += " " + scratch_device + " >/dev/null 2>/dev/null </dev/null"; fs_mgr_set_blk_ro(scratch_device, false); auto ret = system(command.c_str()); if (ret) { LERROR << "make " << mnt_type << " filesystem on " << scratch_device << " return=" << ret; LERROR << "make " << fs_type << " filesystem on " << scratch_device << " return=" << ret; return false; } return true; Loading Loading @@ -1123,7 +1089,7 @@ static bool CreateScratchOnData(std::string* scratch_device, bool* partition_exi return true; } static bool CanUseSuperPartition(const Fstab& fstab, bool* is_virtual_ab) { static bool CanUseSuperPartition(const Fstab& fstab) { auto slot_number = fs_mgr_overlayfs_slot_number(); auto super_device = fs_mgr_overlayfs_super_device(slot_number); if (!fs_mgr_rw_access(super_device) || !fs_mgr_overlayfs_has_logical(fstab)) { Loading @@ -1133,7 +1099,6 @@ static bool CanUseSuperPartition(const Fstab& fstab, bool* is_virtual_ab) { if (!metadata) { return false; } *is_virtual_ab = !!(metadata->header.flags & LP_HEADER_FLAG_VIRTUAL_AB_DEVICE); return true; } Loading @@ -1146,23 +1111,15 @@ bool fs_mgr_overlayfs_create_scratch(const Fstab& fstab, std::string* scratch_de return *partition_exists; } // Try a physical partition first. *scratch_device = GetPhysicalScratchDevice(); if (!scratch_device->empty() && fs_mgr_rw_access(*scratch_device)) { *partition_exists = true; return true; } // If that fails, see if we can land on super. bool is_virtual_ab; if (CanUseSuperPartition(fstab, &is_virtual_ab)) { // Try ImageManager on /data first. bool can_use_data = false; if (is_virtual_ab && FilesystemHasReliablePinning("/data", &can_use_data) && can_use_data) { if (FilesystemHasReliablePinning("/data", &can_use_data) && can_use_data) { return CreateScratchOnData(scratch_device, partition_exists); } // If that fails, see if we can land on super. if (CanUseSuperPartition(fstab)) { return CreateDynamicScratch(scratch_device, partition_exists); } return false; } Loading @@ -1180,9 +1137,8 @@ bool fs_mgr_overlayfs_setup_scratch(const Fstab& fstab) { } // If the partition exists, assume first that it can be mounted. auto mnt_type = fs_mgr_overlayfs_scratch_mount_type(); if (partition_exists) { if (fs_mgr_overlayfs_mount_scratch(scratch_device, mnt_type)) { if (MountScratch(scratch_device)) { if (fs_mgr_access(kScratchMountPoint + kOverlayTopDir) || fs_mgr_filesystem_has_space(kScratchMountPoint)) { return true; Loading @@ -1195,12 +1151,12 @@ bool fs_mgr_overlayfs_setup_scratch(const Fstab& fstab) { } } if (!fs_mgr_overlayfs_make_scratch(scratch_device, mnt_type)) { if (!MakeScratchFilesystem(scratch_device)) { LOG(ERROR) << "Failed to format scratch partition"; return false; } return fs_mgr_overlayfs_mount_scratch(scratch_device, mnt_type); return MountScratch(scratch_device); } #if ALLOW_ADBD_DISABLE_VERITY Loading Loading @@ -1319,14 +1275,13 @@ static void TryMountScratch() { if (!WaitForFile(scratch_device, 10s)) { return; } const auto mount_type = fs_mgr_overlayfs_scratch_mount_type(); if (!fs_mgr_overlayfs_mount_scratch(scratch_device, mount_type, true /* readonly */)) { if (!MountScratch(scratch_device, true /* readonly */)) { return; } auto has_overlayfs_dir = fs_mgr_access(kScratchMountPoint + kOverlayTopDir); fs_mgr_overlayfs_umount_scratch(); if (has_overlayfs_dir) { fs_mgr_overlayfs_mount_scratch(scratch_device, mount_type); MountScratch(scratch_device); } } Loading Loading @@ -1565,8 +1520,7 @@ OverlayfsTeardownResult fs_mgr_overlayfs_teardown(const char* mount_point, bool* if ((mount_point != nullptr) && !fs_mgr_overlayfs_already_mounted(kScratchMountPoint, false)) { std::string scratch_device = GetBootScratchDevice(); if (!scratch_device.empty()) { mount_scratch = fs_mgr_overlayfs_mount_scratch(scratch_device, fs_mgr_overlayfs_scratch_mount_type()); mount_scratch = MountScratch(scratch_device); } } Loading Loading @@ -1687,7 +1641,7 @@ void TeardownAllOverlayForMountPoint(const std::string& mount_point) { if (auto info = EnsureScratchMapped(); info.has_value()) { // Map scratch device, mount kScratchMountPoint and teardown kScratchMountPoint. fs_mgr_overlayfs_umount_scratch(); if (fs_mgr_overlayfs_mount_scratch(info->device, fs_mgr_overlayfs_scratch_mount_type())) { if (MountScratch(info->device)) { bool should_destroy_scratch = false; fs_mgr_overlayfs_teardown_one(kScratchMountPoint, teardown_dir, ignore_change, &should_destroy_scratch); Loading @@ -1702,7 +1656,7 @@ void TeardownAllOverlayForMountPoint(const std::string& mount_point) { std::string scratch_device; if (MapDsuScratchDevice(&scratch_device)) { fs_mgr_overlayfs_umount_scratch(); if (fs_mgr_overlayfs_mount_scratch(scratch_device, fs_mgr_overlayfs_scratch_mount_type())) { if (MountScratch(scratch_device)) { fs_mgr_overlayfs_teardown_one(kScratchMountPoint, teardown_dir, ignore_change); fs_mgr_overlayfs_umount_scratch(); } Loading
fs_mgr/tests/adb-remount-test.sh +53 −61 Original line number Diff line number Diff line Loading @@ -1241,40 +1241,45 @@ adb_sh grep -qE " (/system|/) [^ ]* rw," /proc/mounts </dev/null || adb_sh grep -q " /vendor [^ ]* rw," /proc/mounts </dev/null || die -t "${T}" "/vendor is not RW" scratch_on_super=false if ${overlayfs_needed}; then is_overlayfs_mounted || die -t "${T}" "expected overlay takeover" else is_overlayfs_mounted && die -t "${T}" "unexpected overlay takeover" fi is_overlayfs_mounted /system || die -t "${T}" "expected overlay to takeover /system after remount" # If scratch_partition && uses_dynamic_scratch, then scratch is on super. # If scratch_partition && !uses_dynamic_scratch, then scratch is super_other, system_other. # If !scratch_partition, then scratch is on /data via image_manager. uses_dynamic_scratch=false scratch_partition= virtual_ab=$(get_property ro.virtual_ab.enabled) if ${overlayfs_needed}; then # Collect information about the scratch device if we have one M=$(adb_sh cat /proc/mounts </dev/null | awk '$2 == "/mnt/scratch" { print $1, $3; exit }') [ -z "${M}" ] && die "cannot find any scratch device mounted on /mnt/scratch" if [ -n "${M}" ]; then scratch_device=$(echo "${M}" | awk '{ print $1 }') scratch_filesystem=$(echo "${M}" | awk '{ print $2 }') scratch_size=$(adb_sh df -k "${scratch_device}" </dev/null | tail +2 | head -1 | awk '{ print $2 }') [ -z "${scratch_size}" ] && die "cannot get size of scratch device (${scratch_device})" if [ -n "${virtual_ab}" ]; then LOG INFO "using dynamic scratch partition on /data (VAB device)" elif [[ "${scratch_device}" == /dev/block/by-name/* ]]; then scratch_partition="${scratch_device##/dev/block/by-name/}" LOG INFO "using physical scratch partition ${scratch_partition}" else uses_dynamic_scratch=true scratch_partition=scratch # Detect scratch partition backed by super? for b in "/dev/block/by-name/super"{,_${ACTIVE_SLOT}}; do if adb_test -e "${b}"; then device=$(adb_su realpath "${b}") D=$(adb_su stat -c '0x%t 0x%T' "${device}") major=$(echo "${D}" | awk '{ print $1 }') minor=$(echo "${D}" | awk '{ print $2 }') super_devt=$(( major )):$(( minor )) if adb_su dmctl table scratch | tail +2 | grep -q -w "${super_devt}"; then scratch_on_super=true fi break fi done if ${scratch_on_super}; then LOG INFO "using dynamic scratch partition on super" else LOG INFO "using dynamic scratch partition on /data (VAB device)" fi LOG INFO "scratch device ${scratch_device} filesystem ${scratch_filesystem} size ${scratch_size}KiB" else LOG INFO "cannot find any scratch device mounted on /mnt/scratch, using scratch on /cache" fi for d in ${OVERLAYFS_BACKING}; do if adb_test -d /${d}/overlay/system/upper; then Loading @@ -1283,8 +1288,6 @@ if ${overlayfs_needed}; then done data_device=$(adb_sh awk '$2 == "/data" { print $1; exit }' /proc/mounts) is_overlayfs_mounted /system 2>/dev/null || die -t "${T}" "expected overlay to takeover /system after remount" # KISS (we do not support sub-mounts for system partitions currently) adb_sh grep "^overlay " /proc/mounts </dev/null | grep -vE "^overlay.* /(apex|system|vendor)/[^ ]" | Loading Loading @@ -1312,6 +1315,8 @@ if ${overlayfs_needed}; then die "remount overlayfs missed a spot (rw)" fi done else is_overlayfs_mounted && die -t "${T}" "unexpected overlay takeover" fi LOG OK "adb remount RW" Loading Loading @@ -1455,31 +1460,18 @@ else fastboot_getvar is-userspace yes && is_userspace_fastboot=true # check ${scratch_partition} via fastboot if [ -n "${scratch_partition}" ]; then fastboot_getvar partition-type:${scratch_partition} raw || ( fastboot reboot && false) || die "fastboot can not see ${scratch_partition} parameters" if ${uses_dynamic_scratch}; then fastboot_getvar has-slot:${scratch_partition} no && fastboot_getvar is-logical:${scratch_partition} yes || ( fastboot reboot && false) || die "fastboot can not see ${scratch_partition} parameters" LOG INFO "expect fastboot erase ${scratch_partition} to fail" fastboot erase ${scratch_partition} && ( fastboot reboot || true) && die "fastboot can erase ${scratch_partition}" else fastboot_getvar is-logical:${scratch_partition} no || ( fastboot reboot && false) || die "fastboot can not see ${scratch_partition} parameters" fastboot reboot-bootloader || die "fastboot reboot bootloader" fi LOG INFO "expect fastboot format ${scratch_partition} to fail" fastboot format ${scratch_partition} && ( fastboot reboot || true) && die "fastboot can format ${scratch_partition}" if ${scratch_on_super}; then fastboot_getvar partition-type:scratch raw || die "fastboot cannot see parameter partition-type:scratch" fastboot_getvar has-slot:scratch no || die "fastboot cannot see parameter has-slot:scratch" fastboot_getvar is-logical:scratch yes || die "fastboot cannot see parameter is-logical:scratch" LOG INFO "expect fastboot erase scratch to fail" fastboot erase scratch && die "fastboot can erase scratch" LOG INFO "expect fastboot format scratch to fail" fastboot format scratch && die "fastboot can format scratch" fi fastboot reboot || die "cannot reboot out of fastboot" Loading Loading @@ -1539,9 +1531,9 @@ for i in ${MOUNTS} /system/priv-app; do done ################################################################################ if ${is_bootloader_fastboot} && [ -n "${scratch_partition}" ]; then if ${is_bootloader_fastboot} && ${scratch_on_super}; then LOG RUN "test fastboot flash to ${scratch_partition} recovery" LOG RUN "test fastboot flash to scratch recovery" avc_check adb reboot fastboot </dev/null || Loading @@ -1550,15 +1542,15 @@ if ${is_bootloader_fastboot} && [ -n "${scratch_partition}" ]; then dd if=/dev/zero of=${img} bs=4096 count=16 2>/dev/null && fastboot_wait ${FASTBOOT_WAIT} || die "reboot into fastboot to flash scratch `usb_status`" fastboot flash --force ${scratch_partition} ${img} fastboot flash --force scratch ${img} err=${?} fastboot reboot || die "can not reboot out of fastboot" [ 0 -eq ${err} ] || die "fastboot flash ${scratch_partition}" die "fastboot flash scratch" adb_wait ${ADB_WAIT} && adb_root || die "did not reboot after flashing empty ${scratch_partition} `usb_status`" die "did not reboot after flashing empty scratch $(usb_status)" T=`adb_date` D=`adb disable-verity 2>&1` err=${?} Loading @@ -1578,7 +1570,7 @@ if ${is_bootloader_fastboot} && [ -n "${scratch_partition}" ]; then [ ${err} = 0 ] && [ X"${D}" = X"${D##*setup failed}" ] && [ X"${D}" != X"${D##*[Uu]sing overlayfs}" ] && LOG OK "${scratch_partition} recreated" || LOG OK "recreated scratch" || die -t ${T} "setup for overlayfs" adb remount >&2 || die -t ${T} "remount failed" Loading