diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp index 2dc47bb14..7b686f052 100644 --- a/fs_mgr/fs_mgr.cpp +++ b/fs_mgr/fs_mgr.cpp @@ -91,6 +91,7 @@ #define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a))) using android::base::Basename; +using android::base::GetBoolProperty; using android::base::Realpath; using android::base::StartsWith; using android::base::unique_fd; @@ -1357,14 +1358,33 @@ int fs_mgr_umount_all(android::fs_mgr::Fstab* fstab) { return ret; } +static std::string GetBlockDeviceForMountPoint(const std::string& mount_point) { + Fstab mounts; + if (!ReadFstabFromFile("/proc/mounts", &mounts)) { + LERROR << "Can't read /proc/mounts"; + return ""; + } + auto entry = GetEntryForMountPoint(&mounts, mount_point); + if (entry == nullptr) { + LWARNING << mount_point << " is not mounted"; + return ""; + } + return entry->blk_device; +} + // TODO(b/143970043): return different error codes based on which step failed. int fs_mgr_remount_userdata_into_checkpointing(Fstab* fstab) { - auto entry = GetMountedEntryForUserdata(fstab); - if (entry == nullptr) { + std::string block_device = GetBlockDeviceForMountPoint("/data"); + if (block_device.empty()) { + LERROR << "/data is not mounted"; + return -1; + } + auto fstab_entry = GetMountedEntryForUserdata(fstab); + if (fstab_entry == nullptr) { LERROR << "Can't find /data in fstab"; return -1; } - if (!entry->fs_mgr_flags.checkpoint_blk && !entry->fs_mgr_flags.checkpoint_fs) { + if (!fstab_entry->fs_mgr_flags.checkpoint_blk && !fstab_entry->fs_mgr_flags.checkpoint_fs) { LINFO << "Userdata doesn't support checkpointing. Nothing to do"; return 0; } @@ -1373,34 +1393,43 @@ int fs_mgr_remount_userdata_into_checkpointing(Fstab* fstab) { LINFO << "Checkpointing not needed. Don't remount"; return 0; } - if (entry->fs_mgr_flags.checkpoint_fs) { + bool force_umount_for_f2fs = + GetBoolProperty("sys.init.userdata_remount.force_umount_f2fs", false); + if (fstab_entry->fs_mgr_flags.checkpoint_fs && !force_umount_for_f2fs) { // Userdata is f2fs, simply remount it. - if (!checkpoint_manager.Update(&(*entry))) { + if (!checkpoint_manager.Update(fstab_entry)) { LERROR << "Failed to remount userdata in checkpointing mode"; return -1; } - if (mount(entry->blk_device.c_str(), entry->mount_point.c_str(), "none", - MS_REMOUNT | entry->flags, entry->fs_options.c_str()) != 0) { + if (mount(block_device.c_str(), fstab_entry->mount_point.c_str(), "none", + MS_REMOUNT | fstab_entry->flags, fstab_entry->fs_options.c_str()) != 0) { PERROR << "Failed to remount userdata in checkpointing mode"; return -1; } } else { - // STOPSHIP(b/143970043): support remounting for ext4 + metadata encryption. - if (should_use_metadata_encryption(*entry)) { - LWARNING << "Remounting into checkpointing is not supported for metadata encrypted " - << "ext4 userdata. Proceed with caution"; - return 0; - } + LINFO << "Unmounting /data before remounting into checkpointing mode"; if (umount2("/data", UMOUNT_NOFOLLOW) != 0) { PERROR << "Failed to umount /data"; return -1; } DeviceMapper& dm = DeviceMapper::Instance(); - // TODO(b/143970043): need to delete every dm-device under the one userdata is mounted on. - if (!dm.DeleteDeviceIfExists("bow")) { - LERROR << "Failed to delete dm-bow"; - return -1; + while (dm.IsDmBlockDevice(block_device)) { + auto next_device = dm.GetParentBlockDeviceByPath(block_device); + auto name = dm.GetDmDeviceNameByPath(block_device); + if (!name) { + LERROR << "Failed to get dm-name for " << block_device; + return -1; + } + LINFO << "Deleting " << block_device << " named " << *name; + if (!dm.DeleteDevice(*name, 3s)) { + return -1; + } + if (!next_device) { + LERROR << "Failed to find parent device for " << block_device; + } + block_device = *next_device; } + LINFO << "Remounting /data"; // TODO(b/143970043): remove this hack after fs_mgr_mount_all is refactored. int result = fs_mgr_mount_all(fstab, MOUNT_MODE_ONLY_USERDATA); return result == FS_MGR_MNTALL_FAIL ? -1 : 0;