Loading fs_mgr/fs_mgr.cpp +8 −192 Original line number Diff line number Diff line Loading @@ -1433,16 +1433,16 @@ bool WasMetadataEncryptionInterrupted(const FstabEntry& entry) { // When multiple fstab records share the same mount_point, it will try to mount each // one in turn, and ignore any duplicates after a first successful mount. // Returns -1 on error, and FS_MGR_MNTALL_* otherwise. MountAllResult fs_mgr_mount_all(Fstab* fstab, int mount_mode) { int fs_mgr_mount_all(Fstab* fstab, int mount_mode) { int encryptable = FS_MGR_MNTALL_DEV_NOT_ENCRYPTABLE; int error_count = 0; CheckpointManager checkpoint_manager; AvbUniquePtr avb_handle(nullptr); bool wiped = false; bool userdata_mounted = false; if (fstab->empty()) { return {FS_MGR_MNTALL_FAIL, userdata_mounted}; return FS_MGR_MNTALL_FAIL; } bool scratch_can_be_mounted = true; Loading Loading @@ -1521,7 +1521,7 @@ MountAllResult fs_mgr_mount_all(Fstab* fstab, int mount_mode) { if (!avb_handle) { LERROR << "Failed to open AvbHandle"; set_type_property(encryptable); return {FS_MGR_MNTALL_FAIL, userdata_mounted}; return FS_MGR_MNTALL_FAIL; } } if (avb_handle->SetUpAvbHashtree(¤t_entry, true /* wait_for_verity_dev */) == Loading Loading @@ -1557,7 +1557,7 @@ MountAllResult fs_mgr_mount_all(Fstab* fstab, int mount_mode) { if (status == FS_MGR_MNTALL_FAIL) { // Fatal error - no point continuing. return {status, userdata_mounted}; return status; } if (status != FS_MGR_MNTALL_DEV_NOT_ENCRYPTABLE) { Loading @@ -1577,7 +1577,7 @@ MountAllResult fs_mgr_mount_all(Fstab* fstab, int mount_mode) { nullptr)) { LERROR << "Encryption failed"; set_type_property(encryptable); return {FS_MGR_MNTALL_FAIL, userdata_mounted}; return FS_MGR_MNTALL_FAIL; } } } Loading Loading @@ -1696,9 +1696,9 @@ MountAllResult fs_mgr_mount_all(Fstab* fstab, int mount_mode) { set_type_property(encryptable); if (error_count) { return {FS_MGR_MNTALL_FAIL, userdata_mounted}; return FS_MGR_MNTALL_FAIL; } else { return {encryptable, userdata_mounted}; return encryptable; } } Loading Loading @@ -1735,190 +1735,6 @@ int fs_mgr_umount_all(android::fs_mgr::Fstab* fstab) { return ret; } static std::chrono::milliseconds GetMillisProperty(const std::string& name, std::chrono::milliseconds default_value) { auto value = GetUintProperty(name, static_cast<uint64_t>(default_value.count())); return std::chrono::milliseconds(std::move(value)); } static bool fs_mgr_unmount_all_data_mounts(const std::string& data_block_device) { LINFO << __FUNCTION__ << "(): about to umount everything on top of " << data_block_device; Timer t; auto timeout = GetMillisProperty("init.userspace_reboot.userdata_remount.timeoutmillis", 5s); while (true) { bool umount_done = true; Fstab proc_mounts; if (!ReadFstabFromFile("/proc/mounts", &proc_mounts)) { LERROR << __FUNCTION__ << "(): Can't read /proc/mounts"; return false; } // Now proceed with other bind mounts on top of /data. for (const auto& entry : proc_mounts) { std::string block_device; if (StartsWith(entry.blk_device, "/dev/block") && !Realpath(entry.blk_device, &block_device)) { PWARNING << __FUNCTION__ << "(): failed to realpath " << entry.blk_device; block_device = entry.blk_device; } if (data_block_device == block_device) { if (umount2(entry.mount_point.c_str(), 0) != 0) { PERROR << __FUNCTION__ << "(): Failed to umount " << entry.mount_point; umount_done = false; } } } if (umount_done) { LINFO << __FUNCTION__ << "(): Unmounting /data took " << t; return true; } if (t.duration() > timeout) { LERROR << __FUNCTION__ << "(): Timed out unmounting all mounts on " << data_block_device; Fstab remaining_mounts; if (!ReadFstabFromFile("/proc/mounts", &remaining_mounts)) { LERROR << __FUNCTION__ << "(): Can't read /proc/mounts"; } else { LERROR << __FUNCTION__ << "(): Following mounts remaining"; for (const auto& e : remaining_mounts) { LERROR << __FUNCTION__ << "(): mount point: " << e.mount_point << " block device: " << e.blk_device; } } return false; } std::this_thread::sleep_for(50ms); } } static bool UnwindDmDeviceStack(const std::string& block_device, std::vector<std::string>* dm_stack) { if (!StartsWith(block_device, "/dev/block/")) { LWARNING << block_device << " is not a block device"; return false; } std::string current = block_device; DeviceMapper& dm = DeviceMapper::Instance(); while (true) { dm_stack->push_back(current); if (!dm.IsDmBlockDevice(current)) { break; } auto parent = dm.GetParentBlockDeviceByPath(current); if (!parent) { return false; } current = *parent; } return true; } FstabEntry* fs_mgr_get_mounted_entry_for_userdata(Fstab* fstab, const std::string& data_block_device) { std::vector<std::string> dm_stack; if (!UnwindDmDeviceStack(data_block_device, &dm_stack)) { LERROR << "Failed to unwind dm-device stack for " << data_block_device; return nullptr; } for (auto& entry : *fstab) { if (entry.mount_point != "/data") { continue; } std::string block_device; if (entry.fs_mgr_flags.logical) { if (!fs_mgr_update_logical_partition(&entry)) { LERROR << "Failed to update logic partition " << entry.blk_device; continue; } block_device = entry.blk_device; } else if (!Realpath(entry.blk_device, &block_device)) { PWARNING << "Failed to realpath " << entry.blk_device; block_device = entry.blk_device; } if (std::find(dm_stack.begin(), dm_stack.end(), block_device) != dm_stack.end()) { return &entry; } } LERROR << "Didn't find entry that was used to mount /data onto " << data_block_device; return nullptr; } // TODO(b/143970043): return different error codes based on which step failed. int fs_mgr_remount_userdata_into_checkpointing(Fstab* fstab) { Fstab proc_mounts; if (!ReadFstabFromFile("/proc/mounts", &proc_mounts)) { LERROR << "Can't read /proc/mounts"; return -1; } auto mounted_entry = GetEntryForMountPoint(&proc_mounts, "/data"); if (mounted_entry == nullptr) { LERROR << "/data is not mounted"; return -1; } std::string block_device; if (!Realpath(mounted_entry->blk_device, &block_device)) { PERROR << "Failed to realpath " << mounted_entry->blk_device; return -1; } auto fstab_entry = fs_mgr_get_mounted_entry_for_userdata(fstab, block_device); if (fstab_entry == nullptr) { LERROR << "Can't find /data in fstab"; return -1; } bool force_umount = GetBoolProperty("sys.init.userdata_remount.force_umount", false); if (force_umount) { LINFO << "Will force an umount of userdata even if it's not required"; } if (!force_umount && !SupportsCheckpoint(fstab_entry)) { LINFO << "Userdata doesn't support checkpointing. Nothing to do"; return 0; } CheckpointManager checkpoint_manager; if (!force_umount && !checkpoint_manager.NeedsCheckpoint()) { LINFO << "Checkpointing not needed. Don't remount"; return 0; } if (!force_umount && fstab_entry->fs_mgr_flags.checkpoint_fs) { // Userdata is f2fs, simply remount it. if (!checkpoint_manager.Update(fstab_entry)) { LERROR << "Failed to remount userdata in checkpointing mode"; return -1; } 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 { LINFO << "Unmounting /data before remounting into checkpointing mode"; if (!fs_mgr_unmount_all_data_mounts(block_device)) { LERROR << "Failed to umount /data"; return -1; } DeviceMapper& dm = DeviceMapper::Instance(); 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. auto result = fs_mgr_mount_all(fstab, MOUNT_MODE_ONLY_USERDATA); return result.code == FS_MGR_MNTALL_FAIL ? -1 : 0; } return 0; } // wrapper to __mount() and expects a fully prepared fstab_rec, // unlike fs_mgr_do_mount which does more things with avb / verity etc. int fs_mgr_do_mount_one(const FstabEntry& entry, const std::string& alt_mount_point) { Loading fs_mgr/include/fs_mgr.h +2 −19 Original line number Diff line number Diff line Loading @@ -58,13 +58,8 @@ enum mount_mode { #define FS_MGR_MNTALL_DEV_NEEDS_RECOVERY 4 #define FS_MGR_MNTALL_DEV_NOT_ENCRYPTABLE 0 #define FS_MGR_MNTALL_FAIL (-1) struct MountAllResult { // One of the FS_MGR_MNTALL_* returned code defined above. int code; // Whether userdata was mounted as a result of |fs_mgr_mount_all| call. bool userdata_mounted; }; // fs_mgr_mount_all() updates fstab entries that reference device-mapper. int fs_mgr_mount_all(android::fs_mgr::Fstab* fstab, int mount_mode); struct HashtreeInfo { // The hash algorithm used to build the merkle tree. Loading @@ -75,13 +70,6 @@ struct HashtreeInfo { bool check_at_most_once; }; // fs_mgr_mount_all() updates fstab entries that reference device-mapper. // Returns a |MountAllResult|. The first element is one of the FS_MNG_MNTALL_* return codes // defined above, and the second element tells whether this call to fs_mgr_mount_all was responsible // for mounting userdata. Later is required for init to correctly enqueue fs-related events as part // of userdata remount during userspace reboot. MountAllResult fs_mgr_mount_all(android::fs_mgr::Fstab* fstab, int mount_mode); #define FS_MGR_DOMNT_FAILED (-1) #define FS_MGR_DOMNT_BUSY (-2) #define FS_MGR_DOMNT_SUCCESS 0 Loading Loading @@ -127,11 +115,6 @@ enum FsMgrUmountStatus : int { // it destroys verity devices from device mapper after the device is unmounted. int fs_mgr_umount_all(android::fs_mgr::Fstab* fstab); // Finds a entry in |fstab| that was used to mount a /data on |data_block_device|. android::fs_mgr::FstabEntry* fs_mgr_get_mounted_entry_for_userdata( android::fs_mgr::Fstab* fstab, const std::string& data_block_device); int fs_mgr_remount_userdata_into_checkpointing(android::fs_mgr::Fstab* fstab); // Finds the dm_bow device on which this block device is stacked, or returns // empty string std::string fs_mgr_find_bow_device(const std::string& block_device); Loading fs_mgr/tests/fs_mgr_test.cpp +0 −17 Original line number Diff line number Diff line Loading @@ -1062,23 +1062,6 @@ TEST(fs_mgr, DefaultFstabContainsUserdata) { << "Default fstab doesn't contain /data entry"; } TEST(fs_mgr, UserdataMountedFromDefaultFstab) { if (getuid() != 0) { GTEST_SKIP() << "Must be run as root."; return; } Fstab fstab; ASSERT_TRUE(ReadDefaultFstab(&fstab)) << "Failed to read default fstab"; Fstab proc_mounts; ASSERT_TRUE(ReadFstabFromFile("/proc/mounts", &proc_mounts)) << "Failed to read /proc/mounts"; auto mounted_entry = GetEntryForMountPoint(&proc_mounts, "/data"); ASSERT_NE(mounted_entry, nullptr) << "/data is not mounted"; std::string block_device; ASSERT_TRUE(android::base::Realpath(mounted_entry->blk_device, &block_device)); ASSERT_NE(nullptr, fs_mgr_get_mounted_entry_for_userdata(&fstab, block_device)) << "/data wasn't mounted from default fstab"; } TEST(fs_mgr, ReadFstabFromFile_FsMgrOptions_Readahead_Size_KB) { TemporaryFile tf; ASSERT_TRUE(tf.fd != -1); Loading init/builtins.cpp +9 −54 Original line number Diff line number Diff line Loading @@ -606,8 +606,6 @@ static Result<void> queue_fs_event(int code) { return Error() << "Invalid code: " << code; } static int initial_mount_fstab_return_code = -1; /* <= Q: mount_all <fstab> [ <path> ]* [--<options>]* * >= R: mount_all [ <fstab> ] [--<options>]* * Loading Loading @@ -648,19 +646,10 @@ static Result<void> do_mount_all(const BuiltinArguments& args) { import_late(mount_all->rc_paths); } if (mount_fstab_result.userdata_mounted) { // This call to fs_mgr_mount_all mounted userdata. Keep the result in // order for userspace reboot to correctly remount userdata. LOG(INFO) << "Userdata mounted using " << (mount_all->fstab_path.empty() ? "(default fstab)" : mount_all->fstab_path) << " result : " << mount_fstab_result.code; initial_mount_fstab_return_code = mount_fstab_result.code; } if (queue_event) { /* queue_fs_event will queue event based on mount_fstab return code * and return processed return code*/ auto queue_fs_result = queue_fs_event(mount_fstab_result.code); auto queue_fs_result = queue_fs_event(mount_fstab_result); if (!queue_fs_result.ok()) { return Error() << "queue_fs_event() failed: " << queue_fs_result.error(); } Loading Loading @@ -1148,16 +1137,10 @@ static Result<void> ExecWithFunctionOnFailure(const std::vector<std::string>& ar } static Result<void> ExecVdcRebootOnFailure(const std::string& vdc_arg) { bool should_reboot_into_recovery = true; auto reboot_reason = vdc_arg + "_failed"; if (android::sysprop::InitProperties::userspace_reboot_in_progress().value_or(false)) { should_reboot_into_recovery = false; reboot_reason = "userspace_failed," + vdc_arg; } auto reboot = [reboot_reason, should_reboot_into_recovery](const std::string& message) { auto reboot = [reboot_reason](const std::string& message) { // TODO (b/122850122): support this in gsi if (should_reboot_into_recovery) { if (IsFbeEnabled() && !android::gsi::IsGsiRunning()) { LOG(ERROR) << message << ": Rebooting into recovery, reason: " << reboot_reason; if (auto result = reboot_into_recovery( Loading @@ -1168,39 +1151,12 @@ static Result<void> ExecVdcRebootOnFailure(const std::string& vdc_arg) { } else { LOG(ERROR) << "Failure (reboot suppressed): " << reboot_reason; } } else { LOG(ERROR) << message << ": rebooting, reason: " << reboot_reason; trigger_shutdown("reboot," + reboot_reason); } }; std::vector<std::string> args = {"exec", "/system/bin/vdc", "--wait", "cryptfs", vdc_arg}; return ExecWithFunctionOnFailure(args, reboot); } static Result<void> do_remount_userdata(const BuiltinArguments& args) { if (initial_mount_fstab_return_code == -1) { return Error() << "Calling remount_userdata too early"; } Fstab fstab; if (!ReadDefaultFstab(&fstab)) { // TODO(b/135984674): should we reboot here? return Error() << "Failed to read fstab"; } // TODO(b/135984674): check that fstab contains /data. if (auto rc = fs_mgr_remount_userdata_into_checkpointing(&fstab); rc < 0) { std::string proc_mounts_output; android::base::ReadFileToString("/proc/mounts", &proc_mounts_output, true); android::base::WriteStringToFile(proc_mounts_output, "/metadata/userspacereboot/mount_info.txt"); trigger_shutdown("reboot,mount_userdata_failed"); } if (auto result = queue_fs_event(initial_mount_fstab_return_code); !result.ok()) { return Error() << "queue_fs_event() failed: " << result.error(); } return {}; } static Result<void> do_installkey(const BuiltinArguments& args) { if (!is_file_crypto()) return {}; Loading Loading @@ -1361,7 +1317,6 @@ const BuiltinFunctionMap& GetBuiltinFunctionMap() { {"umount_all", {0, 1, {false, do_umount_all}}}, {"update_linker_config", {0, 0, {false, do_update_linker_config}}}, {"readahead", {1, 2, {true, do_readahead}}}, {"remount_userdata", {0, 0, {false, do_remount_userdata}}}, {"restart", {1, 2, {false, do_restart}}}, {"restorecon", {1, kMax, {true, do_restorecon}}}, {"restorecon_recursive", {1, kMax, {true, do_restorecon_recursive}}}, Loading init/property_service.cpp +2 −3 Original line number Diff line number Diff line Loading @@ -100,7 +100,6 @@ using android::properties::BuildTrie; using android::properties::ParsePropertyInfoFile; using android::properties::PropertyInfoAreaFile; using android::properties::PropertyInfoEntry; using android::sysprop::InitProperties::is_userspace_reboot_supported; namespace android { namespace init { Loading Loading @@ -567,8 +566,8 @@ std::optional<uint32_t> HandlePropertySet(const std::string& name, const std::st } LOG(INFO) << "Received sys.powerctl='" << value << "' from pid: " << cr.pid << process_log_string; if (value == "reboot,userspace" && !is_userspace_reboot_supported().value_or(false)) { *error = "Userspace reboot is not supported by this device"; if (value == "reboot,userspace") { *error = "Userspace reboot is deprecated."; return {PROP_ERROR_INVALID_VALUE}; } } Loading Loading
fs_mgr/fs_mgr.cpp +8 −192 Original line number Diff line number Diff line Loading @@ -1433,16 +1433,16 @@ bool WasMetadataEncryptionInterrupted(const FstabEntry& entry) { // When multiple fstab records share the same mount_point, it will try to mount each // one in turn, and ignore any duplicates after a first successful mount. // Returns -1 on error, and FS_MGR_MNTALL_* otherwise. MountAllResult fs_mgr_mount_all(Fstab* fstab, int mount_mode) { int fs_mgr_mount_all(Fstab* fstab, int mount_mode) { int encryptable = FS_MGR_MNTALL_DEV_NOT_ENCRYPTABLE; int error_count = 0; CheckpointManager checkpoint_manager; AvbUniquePtr avb_handle(nullptr); bool wiped = false; bool userdata_mounted = false; if (fstab->empty()) { return {FS_MGR_MNTALL_FAIL, userdata_mounted}; return FS_MGR_MNTALL_FAIL; } bool scratch_can_be_mounted = true; Loading Loading @@ -1521,7 +1521,7 @@ MountAllResult fs_mgr_mount_all(Fstab* fstab, int mount_mode) { if (!avb_handle) { LERROR << "Failed to open AvbHandle"; set_type_property(encryptable); return {FS_MGR_MNTALL_FAIL, userdata_mounted}; return FS_MGR_MNTALL_FAIL; } } if (avb_handle->SetUpAvbHashtree(¤t_entry, true /* wait_for_verity_dev */) == Loading Loading @@ -1557,7 +1557,7 @@ MountAllResult fs_mgr_mount_all(Fstab* fstab, int mount_mode) { if (status == FS_MGR_MNTALL_FAIL) { // Fatal error - no point continuing. return {status, userdata_mounted}; return status; } if (status != FS_MGR_MNTALL_DEV_NOT_ENCRYPTABLE) { Loading @@ -1577,7 +1577,7 @@ MountAllResult fs_mgr_mount_all(Fstab* fstab, int mount_mode) { nullptr)) { LERROR << "Encryption failed"; set_type_property(encryptable); return {FS_MGR_MNTALL_FAIL, userdata_mounted}; return FS_MGR_MNTALL_FAIL; } } } Loading Loading @@ -1696,9 +1696,9 @@ MountAllResult fs_mgr_mount_all(Fstab* fstab, int mount_mode) { set_type_property(encryptable); if (error_count) { return {FS_MGR_MNTALL_FAIL, userdata_mounted}; return FS_MGR_MNTALL_FAIL; } else { return {encryptable, userdata_mounted}; return encryptable; } } Loading Loading @@ -1735,190 +1735,6 @@ int fs_mgr_umount_all(android::fs_mgr::Fstab* fstab) { return ret; } static std::chrono::milliseconds GetMillisProperty(const std::string& name, std::chrono::milliseconds default_value) { auto value = GetUintProperty(name, static_cast<uint64_t>(default_value.count())); return std::chrono::milliseconds(std::move(value)); } static bool fs_mgr_unmount_all_data_mounts(const std::string& data_block_device) { LINFO << __FUNCTION__ << "(): about to umount everything on top of " << data_block_device; Timer t; auto timeout = GetMillisProperty("init.userspace_reboot.userdata_remount.timeoutmillis", 5s); while (true) { bool umount_done = true; Fstab proc_mounts; if (!ReadFstabFromFile("/proc/mounts", &proc_mounts)) { LERROR << __FUNCTION__ << "(): Can't read /proc/mounts"; return false; } // Now proceed with other bind mounts on top of /data. for (const auto& entry : proc_mounts) { std::string block_device; if (StartsWith(entry.blk_device, "/dev/block") && !Realpath(entry.blk_device, &block_device)) { PWARNING << __FUNCTION__ << "(): failed to realpath " << entry.blk_device; block_device = entry.blk_device; } if (data_block_device == block_device) { if (umount2(entry.mount_point.c_str(), 0) != 0) { PERROR << __FUNCTION__ << "(): Failed to umount " << entry.mount_point; umount_done = false; } } } if (umount_done) { LINFO << __FUNCTION__ << "(): Unmounting /data took " << t; return true; } if (t.duration() > timeout) { LERROR << __FUNCTION__ << "(): Timed out unmounting all mounts on " << data_block_device; Fstab remaining_mounts; if (!ReadFstabFromFile("/proc/mounts", &remaining_mounts)) { LERROR << __FUNCTION__ << "(): Can't read /proc/mounts"; } else { LERROR << __FUNCTION__ << "(): Following mounts remaining"; for (const auto& e : remaining_mounts) { LERROR << __FUNCTION__ << "(): mount point: " << e.mount_point << " block device: " << e.blk_device; } } return false; } std::this_thread::sleep_for(50ms); } } static bool UnwindDmDeviceStack(const std::string& block_device, std::vector<std::string>* dm_stack) { if (!StartsWith(block_device, "/dev/block/")) { LWARNING << block_device << " is not a block device"; return false; } std::string current = block_device; DeviceMapper& dm = DeviceMapper::Instance(); while (true) { dm_stack->push_back(current); if (!dm.IsDmBlockDevice(current)) { break; } auto parent = dm.GetParentBlockDeviceByPath(current); if (!parent) { return false; } current = *parent; } return true; } FstabEntry* fs_mgr_get_mounted_entry_for_userdata(Fstab* fstab, const std::string& data_block_device) { std::vector<std::string> dm_stack; if (!UnwindDmDeviceStack(data_block_device, &dm_stack)) { LERROR << "Failed to unwind dm-device stack for " << data_block_device; return nullptr; } for (auto& entry : *fstab) { if (entry.mount_point != "/data") { continue; } std::string block_device; if (entry.fs_mgr_flags.logical) { if (!fs_mgr_update_logical_partition(&entry)) { LERROR << "Failed to update logic partition " << entry.blk_device; continue; } block_device = entry.blk_device; } else if (!Realpath(entry.blk_device, &block_device)) { PWARNING << "Failed to realpath " << entry.blk_device; block_device = entry.blk_device; } if (std::find(dm_stack.begin(), dm_stack.end(), block_device) != dm_stack.end()) { return &entry; } } LERROR << "Didn't find entry that was used to mount /data onto " << data_block_device; return nullptr; } // TODO(b/143970043): return different error codes based on which step failed. int fs_mgr_remount_userdata_into_checkpointing(Fstab* fstab) { Fstab proc_mounts; if (!ReadFstabFromFile("/proc/mounts", &proc_mounts)) { LERROR << "Can't read /proc/mounts"; return -1; } auto mounted_entry = GetEntryForMountPoint(&proc_mounts, "/data"); if (mounted_entry == nullptr) { LERROR << "/data is not mounted"; return -1; } std::string block_device; if (!Realpath(mounted_entry->blk_device, &block_device)) { PERROR << "Failed to realpath " << mounted_entry->blk_device; return -1; } auto fstab_entry = fs_mgr_get_mounted_entry_for_userdata(fstab, block_device); if (fstab_entry == nullptr) { LERROR << "Can't find /data in fstab"; return -1; } bool force_umount = GetBoolProperty("sys.init.userdata_remount.force_umount", false); if (force_umount) { LINFO << "Will force an umount of userdata even if it's not required"; } if (!force_umount && !SupportsCheckpoint(fstab_entry)) { LINFO << "Userdata doesn't support checkpointing. Nothing to do"; return 0; } CheckpointManager checkpoint_manager; if (!force_umount && !checkpoint_manager.NeedsCheckpoint()) { LINFO << "Checkpointing not needed. Don't remount"; return 0; } if (!force_umount && fstab_entry->fs_mgr_flags.checkpoint_fs) { // Userdata is f2fs, simply remount it. if (!checkpoint_manager.Update(fstab_entry)) { LERROR << "Failed to remount userdata in checkpointing mode"; return -1; } 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 { LINFO << "Unmounting /data before remounting into checkpointing mode"; if (!fs_mgr_unmount_all_data_mounts(block_device)) { LERROR << "Failed to umount /data"; return -1; } DeviceMapper& dm = DeviceMapper::Instance(); 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. auto result = fs_mgr_mount_all(fstab, MOUNT_MODE_ONLY_USERDATA); return result.code == FS_MGR_MNTALL_FAIL ? -1 : 0; } return 0; } // wrapper to __mount() and expects a fully prepared fstab_rec, // unlike fs_mgr_do_mount which does more things with avb / verity etc. int fs_mgr_do_mount_one(const FstabEntry& entry, const std::string& alt_mount_point) { Loading
fs_mgr/include/fs_mgr.h +2 −19 Original line number Diff line number Diff line Loading @@ -58,13 +58,8 @@ enum mount_mode { #define FS_MGR_MNTALL_DEV_NEEDS_RECOVERY 4 #define FS_MGR_MNTALL_DEV_NOT_ENCRYPTABLE 0 #define FS_MGR_MNTALL_FAIL (-1) struct MountAllResult { // One of the FS_MGR_MNTALL_* returned code defined above. int code; // Whether userdata was mounted as a result of |fs_mgr_mount_all| call. bool userdata_mounted; }; // fs_mgr_mount_all() updates fstab entries that reference device-mapper. int fs_mgr_mount_all(android::fs_mgr::Fstab* fstab, int mount_mode); struct HashtreeInfo { // The hash algorithm used to build the merkle tree. Loading @@ -75,13 +70,6 @@ struct HashtreeInfo { bool check_at_most_once; }; // fs_mgr_mount_all() updates fstab entries that reference device-mapper. // Returns a |MountAllResult|. The first element is one of the FS_MNG_MNTALL_* return codes // defined above, and the second element tells whether this call to fs_mgr_mount_all was responsible // for mounting userdata. Later is required for init to correctly enqueue fs-related events as part // of userdata remount during userspace reboot. MountAllResult fs_mgr_mount_all(android::fs_mgr::Fstab* fstab, int mount_mode); #define FS_MGR_DOMNT_FAILED (-1) #define FS_MGR_DOMNT_BUSY (-2) #define FS_MGR_DOMNT_SUCCESS 0 Loading Loading @@ -127,11 +115,6 @@ enum FsMgrUmountStatus : int { // it destroys verity devices from device mapper after the device is unmounted. int fs_mgr_umount_all(android::fs_mgr::Fstab* fstab); // Finds a entry in |fstab| that was used to mount a /data on |data_block_device|. android::fs_mgr::FstabEntry* fs_mgr_get_mounted_entry_for_userdata( android::fs_mgr::Fstab* fstab, const std::string& data_block_device); int fs_mgr_remount_userdata_into_checkpointing(android::fs_mgr::Fstab* fstab); // Finds the dm_bow device on which this block device is stacked, or returns // empty string std::string fs_mgr_find_bow_device(const std::string& block_device); Loading
fs_mgr/tests/fs_mgr_test.cpp +0 −17 Original line number Diff line number Diff line Loading @@ -1062,23 +1062,6 @@ TEST(fs_mgr, DefaultFstabContainsUserdata) { << "Default fstab doesn't contain /data entry"; } TEST(fs_mgr, UserdataMountedFromDefaultFstab) { if (getuid() != 0) { GTEST_SKIP() << "Must be run as root."; return; } Fstab fstab; ASSERT_TRUE(ReadDefaultFstab(&fstab)) << "Failed to read default fstab"; Fstab proc_mounts; ASSERT_TRUE(ReadFstabFromFile("/proc/mounts", &proc_mounts)) << "Failed to read /proc/mounts"; auto mounted_entry = GetEntryForMountPoint(&proc_mounts, "/data"); ASSERT_NE(mounted_entry, nullptr) << "/data is not mounted"; std::string block_device; ASSERT_TRUE(android::base::Realpath(mounted_entry->blk_device, &block_device)); ASSERT_NE(nullptr, fs_mgr_get_mounted_entry_for_userdata(&fstab, block_device)) << "/data wasn't mounted from default fstab"; } TEST(fs_mgr, ReadFstabFromFile_FsMgrOptions_Readahead_Size_KB) { TemporaryFile tf; ASSERT_TRUE(tf.fd != -1); Loading
init/builtins.cpp +9 −54 Original line number Diff line number Diff line Loading @@ -606,8 +606,6 @@ static Result<void> queue_fs_event(int code) { return Error() << "Invalid code: " << code; } static int initial_mount_fstab_return_code = -1; /* <= Q: mount_all <fstab> [ <path> ]* [--<options>]* * >= R: mount_all [ <fstab> ] [--<options>]* * Loading Loading @@ -648,19 +646,10 @@ static Result<void> do_mount_all(const BuiltinArguments& args) { import_late(mount_all->rc_paths); } if (mount_fstab_result.userdata_mounted) { // This call to fs_mgr_mount_all mounted userdata. Keep the result in // order for userspace reboot to correctly remount userdata. LOG(INFO) << "Userdata mounted using " << (mount_all->fstab_path.empty() ? "(default fstab)" : mount_all->fstab_path) << " result : " << mount_fstab_result.code; initial_mount_fstab_return_code = mount_fstab_result.code; } if (queue_event) { /* queue_fs_event will queue event based on mount_fstab return code * and return processed return code*/ auto queue_fs_result = queue_fs_event(mount_fstab_result.code); auto queue_fs_result = queue_fs_event(mount_fstab_result); if (!queue_fs_result.ok()) { return Error() << "queue_fs_event() failed: " << queue_fs_result.error(); } Loading Loading @@ -1148,16 +1137,10 @@ static Result<void> ExecWithFunctionOnFailure(const std::vector<std::string>& ar } static Result<void> ExecVdcRebootOnFailure(const std::string& vdc_arg) { bool should_reboot_into_recovery = true; auto reboot_reason = vdc_arg + "_failed"; if (android::sysprop::InitProperties::userspace_reboot_in_progress().value_or(false)) { should_reboot_into_recovery = false; reboot_reason = "userspace_failed," + vdc_arg; } auto reboot = [reboot_reason, should_reboot_into_recovery](const std::string& message) { auto reboot = [reboot_reason](const std::string& message) { // TODO (b/122850122): support this in gsi if (should_reboot_into_recovery) { if (IsFbeEnabled() && !android::gsi::IsGsiRunning()) { LOG(ERROR) << message << ": Rebooting into recovery, reason: " << reboot_reason; if (auto result = reboot_into_recovery( Loading @@ -1168,39 +1151,12 @@ static Result<void> ExecVdcRebootOnFailure(const std::string& vdc_arg) { } else { LOG(ERROR) << "Failure (reboot suppressed): " << reboot_reason; } } else { LOG(ERROR) << message << ": rebooting, reason: " << reboot_reason; trigger_shutdown("reboot," + reboot_reason); } }; std::vector<std::string> args = {"exec", "/system/bin/vdc", "--wait", "cryptfs", vdc_arg}; return ExecWithFunctionOnFailure(args, reboot); } static Result<void> do_remount_userdata(const BuiltinArguments& args) { if (initial_mount_fstab_return_code == -1) { return Error() << "Calling remount_userdata too early"; } Fstab fstab; if (!ReadDefaultFstab(&fstab)) { // TODO(b/135984674): should we reboot here? return Error() << "Failed to read fstab"; } // TODO(b/135984674): check that fstab contains /data. if (auto rc = fs_mgr_remount_userdata_into_checkpointing(&fstab); rc < 0) { std::string proc_mounts_output; android::base::ReadFileToString("/proc/mounts", &proc_mounts_output, true); android::base::WriteStringToFile(proc_mounts_output, "/metadata/userspacereboot/mount_info.txt"); trigger_shutdown("reboot,mount_userdata_failed"); } if (auto result = queue_fs_event(initial_mount_fstab_return_code); !result.ok()) { return Error() << "queue_fs_event() failed: " << result.error(); } return {}; } static Result<void> do_installkey(const BuiltinArguments& args) { if (!is_file_crypto()) return {}; Loading Loading @@ -1361,7 +1317,6 @@ const BuiltinFunctionMap& GetBuiltinFunctionMap() { {"umount_all", {0, 1, {false, do_umount_all}}}, {"update_linker_config", {0, 0, {false, do_update_linker_config}}}, {"readahead", {1, 2, {true, do_readahead}}}, {"remount_userdata", {0, 0, {false, do_remount_userdata}}}, {"restart", {1, 2, {false, do_restart}}}, {"restorecon", {1, kMax, {true, do_restorecon}}}, {"restorecon_recursive", {1, kMax, {true, do_restorecon_recursive}}}, Loading
init/property_service.cpp +2 −3 Original line number Diff line number Diff line Loading @@ -100,7 +100,6 @@ using android::properties::BuildTrie; using android::properties::ParsePropertyInfoFile; using android::properties::PropertyInfoAreaFile; using android::properties::PropertyInfoEntry; using android::sysprop::InitProperties::is_userspace_reboot_supported; namespace android { namespace init { Loading Loading @@ -567,8 +566,8 @@ std::optional<uint32_t> HandlePropertySet(const std::string& name, const std::st } LOG(INFO) << "Received sys.powerctl='" << value << "' from pid: " << cr.pid << process_log_string; if (value == "reboot,userspace" && !is_userspace_reboot_supported().value_or(false)) { *error = "Userspace reboot is not supported by this device"; if (value == "reboot,userspace") { *error = "Userspace reboot is deprecated."; return {PROP_ERROR_INVALID_VALUE}; } } Loading