From e34549af332e4be13a2ffb385455280d4736c1a9 Mon Sep 17 00:00:00 2001 From: Jooyung Han Date: Fri, 9 Aug 2024 15:58:53 +0900 Subject: [PATCH 1/2] Clean up userspace-reboot The feature was deprecated last year. Bug: 292469129 Test: atest CtsInitTestCases Change-Id: I826502770ab3fa566be57a33829f1103efa893fb --- fs_mgr/fs_mgr.cpp | 200 ++----------------------------- fs_mgr/include/fs_mgr.h | 21 +--- fs_mgr/tests/fs_mgr_test.cpp | 17 --- init/builtins.cpp | 37 +----- init/property_service.cpp | 5 +- init/property_service_test.cpp | 6 - init/reboot.cpp | 210 +-------------------------------- rootdir/init.rc | 41 ------- rootdir/init.usb.rc | 4 - 9 files changed, 15 insertions(+), 526 deletions(-) diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp index 3e70f7937..76578dd2c 100644 --- a/fs_mgr/fs_mgr.cpp +++ b/fs_mgr/fs_mgr.cpp @@ -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; @@ -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 */) == @@ -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) { @@ -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; } } } @@ -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; } } @@ -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(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* 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 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) { diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h index 2e1cf76ea..af5ae2d16 100644 --- a/fs_mgr/include/fs_mgr.h +++ b/fs_mgr/include/fs_mgr.h @@ -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. @@ -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 @@ -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); diff --git a/fs_mgr/tests/fs_mgr_test.cpp b/fs_mgr/tests/fs_mgr_test.cpp index 322bf1b08..bd3d6b532 100644 --- a/fs_mgr/tests/fs_mgr_test.cpp +++ b/fs_mgr/tests/fs_mgr_test.cpp @@ -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); diff --git a/init/builtins.cpp b/init/builtins.cpp index 606ea8c0a..2b965b66c 100644 --- a/init/builtins.cpp +++ b/init/builtins.cpp @@ -606,8 +606,6 @@ static Result queue_fs_event(int code) { return Error() << "Invalid code: " << code; } -static int initial_mount_fstab_return_code = -1; - /* <= Q: mount_all [ ]* [--]* * >= R: mount_all [ ] [--]* * @@ -648,19 +646,10 @@ static Result 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(); } @@ -1178,29 +1167,6 @@ static Result ExecVdcRebootOnFailure(const std::string& vdc_arg) { return ExecWithFunctionOnFailure(args, reboot); } -static Result 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 do_installkey(const BuiltinArguments& args) { if (!is_file_crypto()) return {}; @@ -1361,7 +1327,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}}}, diff --git a/init/property_service.cpp b/init/property_service.cpp index 0d6eb1533..053239f02 100644 --- a/init/property_service.cpp +++ b/init/property_service.cpp @@ -102,7 +102,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 { @@ -569,8 +568,8 @@ std::optional 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}; } } diff --git a/init/property_service_test.cpp b/init/property_service_test.cpp index 5f34cc4da..eed8312cf 100644 --- a/init/property_service_test.cpp +++ b/init/property_service_test.cpp @@ -82,12 +82,6 @@ TEST(property_service, userspace_reboot_not_supported) { GTEST_SKIP() << "Skipping test, must be run as root."; return; } - const std::string original_value = GetProperty("init.userspace_reboot.is_supported", ""); - auto guard = android::base::make_scope_guard([&original_value]() { - SetProperty("init.userspace_reboot.is_supported", original_value); - }); - - ASSERT_TRUE(SetProperty("init.userspace_reboot.is_supported", "false")); EXPECT_FALSE(SetProperty("sys.powerctl", "reboot,userspace")); } diff --git a/init/reboot.cpp b/init/reboot.cpp index 150f8f40e..66ee9772a 100644 --- a/init/reboot.cpp +++ b/init/reboot.cpp @@ -87,16 +87,6 @@ static bool shutting_down = false; static const std::set kDebuggingServices{"tombstoned", "logd", "adbd", "console"}; -static std::set GetPostDataDebuggingServices() { - std::set ret; - for (const auto& s : ServiceList::GetInstance()) { - if (kDebuggingServices.count(s->name()) && s->is_post_data()) { - ret.insert(s->name()); - } - } - return ret; -} - static void PersistRebootReason(const char* reason, bool write_to_property) { if (write_to_property) { SetProperty(LAST_REBOOT_REASON_PROPERTY, reason); @@ -810,196 +800,6 @@ static void EnterShutdown() { } } -static void LeaveShutdown() { - LOG(INFO) << "Leaving shutdown mode"; - shutting_down = false; - StartSendingMessages(); -} - -static std::chrono::milliseconds GetMillisProperty(const std::string& name, - std::chrono::milliseconds default_value) { - auto value = GetUintProperty(name, static_cast(default_value.count())); - return std::chrono::milliseconds(std::move(value)); -} - -static Result DoUserspaceReboot() { - LOG(INFO) << "Userspace reboot initiated"; - // An ugly way to pass a more precise reason on why fallback to hard reboot was triggered. - std::string sub_reason = ""; - auto guard = android::base::make_scope_guard([&sub_reason] { - // Leave shutdown so that we can handle a full reboot. - LeaveShutdown(); - trigger_shutdown("reboot,userspace_failed,shutdown_aborted," + sub_reason); - }); - // Triggering userspace-reboot-requested will result in a bunch of setprop - // actions. We should make sure, that all of them are propagated before - // proceeding with userspace reboot. Synchronously setting sys.init.userspace_reboot.in_progress - // property is not perfect, but it should do the trick. - if (!android::sysprop::InitProperties::userspace_reboot_in_progress(true)) { - sub_reason = "setprop"; - return Error() << "Failed to set sys.init.userspace_reboot.in_progress property"; - } - EnterShutdown(); - if (!SetProperty("sys.powerctl", "")) { - sub_reason = "resetprop"; - return Error() << "Failed to reset sys.powerctl property"; - } - std::set stop_first; - // Remember the services that were enabled. We will need to manually enable them again otherwise - // triggers like class_start won't restart them. - std::set were_enabled; - for (const auto& s : ServiceList::GetInstance().services_in_shutdown_order()) { - if (s->is_post_data() && !kDebuggingServices.count(s->name())) { - stop_first.insert(s->name()); - } - // TODO(ioffe): we should also filter out temporary services here. - if (s->is_post_data() && s->IsEnabled()) { - were_enabled.insert(s->name()); - } - } - { - Timer sync_timer; - LOG(INFO) << "sync() before terminating services..."; - sync(); - LOG(INFO) << "sync() took " << sync_timer; - } - auto sigterm_timeout = GetMillisProperty("init.userspace_reboot.sigterm.timeoutmillis", 5s); - auto sigkill_timeout = GetMillisProperty("init.userspace_reboot.sigkill.timeoutmillis", 10s); - LOG(INFO) << "Timeout to terminate services: " << sigterm_timeout.count() << "ms " - << "Timeout to kill services: " << sigkill_timeout.count() << "ms"; - std::string services_file_name = "/metadata/userspacereboot/services.txt"; - const int flags = O_RDWR | O_CREAT | O_SYNC | O_APPEND | O_CLOEXEC; - StopServicesAndLogViolations(stop_first, sigterm_timeout, true /* SIGTERM */); - if (int r = StopServicesAndLogViolations(stop_first, sigkill_timeout, false /* SIGKILL */); - r > 0) { - auto fd = unique_fd(TEMP_FAILURE_RETRY(open(services_file_name.c_str(), flags, 0666))); - android::base::WriteStringToFd("Post-data services still running: \n", fd); - for (const auto& s : ServiceList::GetInstance()) { - if (s->IsRunning() && stop_first.count(s->name())) { - android::base::WriteStringToFd(s->name() + "\n", fd); - } - } - sub_reason = "sigkill"; - return Error() << r << " post-data services are still running"; - } - if (auto result = KillZramBackingDevice(); !result.ok()) { - sub_reason = "zram"; - return result; - } - if (auto result = CallVdc("volume", "reset"); !result.ok()) { - sub_reason = "vold_reset"; - return result; - } - const auto& debugging_services = GetPostDataDebuggingServices(); - if (int r = StopServicesAndLogViolations(debugging_services, sigkill_timeout, - false /* SIGKILL */); - r > 0) { - auto fd = unique_fd(TEMP_FAILURE_RETRY(open(services_file_name.c_str(), flags, 0666))); - android::base::WriteStringToFd("Debugging services still running: \n", fd); - for (const auto& s : ServiceList::GetInstance()) { - if (s->IsRunning() && debugging_services.count(s->name())) { - android::base::WriteStringToFd(s->name() + "\n", fd); - } - } - sub_reason = "sigkill_debug"; - return Error() << r << " debugging services are still running"; - } - { - Timer sync_timer; - LOG(INFO) << "sync() after stopping services..."; - sync(); - LOG(INFO) << "sync() took " << sync_timer; - } - if (auto result = UnmountAllApexes(); !result.ok()) { - sub_reason = "apex"; - return result; - } - if (!SwitchToMountNamespaceIfNeeded(NS_BOOTSTRAP).ok()) { - sub_reason = "ns_switch"; - return Error() << "Failed to switch to bootstrap namespace"; - } - ActionManager::GetInstance().RemoveActionIf([](const auto& action) -> bool { - if (action->IsFromApex()) { - std::string trigger_name = action->BuildTriggersString(); - LOG(INFO) << "Removing action (" << trigger_name << ") from (" << action->filename() - << ":" << action->line() << ")"; - return true; - } - return false; - }); - // Remove services that were defined in an APEX - ServiceList::GetInstance().RemoveServiceIf([](const std::unique_ptr& s) -> bool { - if (s->is_from_apex()) { - LOG(INFO) << "Removing service '" << s->name() << "' because it's defined in an APEX"; - return true; - } - return false; - }); - // Re-enable services - for (const auto& s : ServiceList::GetInstance()) { - if (were_enabled.count(s->name())) { - LOG(INFO) << "Re-enabling service '" << s->name() << "'"; - s->Enable(); - } - } - ServiceList::GetInstance().ResetState(); - LeaveShutdown(); - ActionManager::GetInstance().QueueEventTrigger("userspace-reboot-resume"); - guard.Disable(); // Go on with userspace reboot. - return {}; -} - -static void UserspaceRebootWatchdogThread() { - auto started_timeout = GetMillisProperty("init.userspace_reboot.started.timeoutmillis", 10s); - if (!WaitForProperty("sys.init.userspace_reboot.in_progress", "1", started_timeout)) { - LOG(ERROR) << "Userspace reboot didn't start in " << started_timeout.count() - << "ms. Switching to full reboot"; - // Init might be wedged, don't try to write reboot reason into a persistent property and do - // a dirty reboot. - PersistRebootReason("userspace_failed,watchdog_triggered,failed_to_start", false); - RebootSystem(ANDROID_RB_RESTART2, "userspace_failed,watchdog_triggered,failed_to_start"); - } - LOG(INFO) << "Starting userspace reboot watchdog"; - auto watchdog_timeout = GetMillisProperty("init.userspace_reboot.watchdog.timeoutmillis", 5min); - LOG(INFO) << "UserspaceRebootWatchdog timeout: " << watchdog_timeout.count() << "ms"; - if (!WaitForProperty("sys.boot_completed", "1", watchdog_timeout)) { - LOG(ERROR) << "Failed to boot in " << watchdog_timeout.count() - << "ms. Switching to full reboot"; - // In this case device is in a boot loop. Only way to recover is to do dirty reboot. - // Since init might be wedged, don't try to write reboot reason into a persistent property. - PersistRebootReason("userspace_failed,watchdog_triggered,failed_to_boot", false); - RebootSystem(ANDROID_RB_RESTART2, "userspace_failed,watchdog_triggered,failed_to_boot"); - } - LOG(INFO) << "Device booted, stopping userspace reboot watchdog"; -} - -static void HandleUserspaceReboot() { - if (!android::sysprop::InitProperties::is_userspace_reboot_supported().value_or(false)) { - LOG(ERROR) << "Attempted a userspace reboot on a device that doesn't support it"; - return; - } - // Spinnig up a separate thread will fail the setns call later in the boot sequence. - // Fork a new process to monitor userspace reboot while we are investigating a better solution. - pid_t pid = fork(); - if (pid < 0) { - PLOG(ERROR) << "Failed to fork process for userspace reboot watchdog. Switching to full " - << "reboot"; - trigger_shutdown("reboot,userspace_failed,watchdog_fork"); - return; - } - if (pid == 0) { - // Child - UserspaceRebootWatchdogThread(); - _exit(EXIT_SUCCESS); - } - LOG(INFO) << "Clearing queue and starting userspace-reboot-requested trigger"; - auto& am = ActionManager::GetInstance(); - am.ClearQueue(); - am.QueueEventTrigger("userspace-reboot-requested"); - auto handler = [](const BuiltinArguments&) { return DoUserspaceReboot(); }; - am.QueueBuiltinAction(handler, "userspace-reboot"); -} - /** * Check if "command" field is set in bootloader message. * @@ -1030,7 +830,6 @@ void HandlePowerctlMessage(const std::string& command) { std::string reboot_target = ""; bool run_fsck = false; bool command_invalid = false; - bool userspace_reboot = false; if (cmd_params[0] == "shutdown") { cmd = ANDROID_RB_POWEROFF; @@ -1051,8 +850,8 @@ void HandlePowerctlMessage(const std::string& command) { if (cmd_params.size() >= 2) { reboot_target = cmd_params[1]; if (reboot_target == "userspace") { - LOG(INFO) << "Userspace reboot requested"; - userspace_reboot = true; + LOG(ERROR) << "Userspace reboot is deprecated."; + return; } // adb reboot fastboot should boot into bootloader for devices not // supporting logical partitions. @@ -1130,11 +929,6 @@ void HandlePowerctlMessage(const std::string& command) { // messages, etc) from properties during reboot. StopSendingMessages(); - if (userspace_reboot) { - HandleUserspaceReboot(); - return; - } - LOG(INFO) << "Clear action queue and start shutdown trigger"; ActionManager::GetInstance().ClearQueue(); // Queue shutdown trigger first diff --git a/rootdir/init.rc b/rootdir/init.rc index b804c1bde..a9178aabb 100644 --- a/rootdir/init.rc +++ b/rootdir/init.rc @@ -620,7 +620,6 @@ on post-fs mkdir /metadata/bootstat 0750 system log mkdir /metadata/ota 0750 root system mkdir /metadata/ota/snapshots 0750 root system - mkdir /metadata/userspacereboot 0770 root system mkdir /metadata/watchdog 0770 root system mkdir /metadata/apex 0700 root system @@ -1323,46 +1322,6 @@ on property:ro.debuggable=1 on init && property:ro.debuggable=1 start console -on userspace-reboot-requested - # TODO(b/135984674): reset all necessary properties here. - setprop sys.boot_completed "" - setprop dev.bootcomplete "" - setprop sys.init.updatable_crashing "" - setprop sys.init.updatable_crashing_process_name "" - setprop sys.user.0.ce_available "" - setprop sys.shutdown.requested "" - setprop service.bootanim.exit "" - setprop service.bootanim.progress "" - -on userspace-reboot-fs-remount - # Make sure that vold is running. - # This is mostly a precaution measure in case vold for some reason wasn't running when - # userspace reboot was initiated. - start vold - exec - system system -- /system/bin/vdc checkpoint resetCheckpoint - exec - system system -- /system/bin/vdc checkpoint markBootAttempt - # Unmount /data_mirror mounts in the reverse order of corresponding mounts. - umount /data_mirror/data_ce/null/0 - umount /data_mirror/data_ce/null - umount /data_mirror/data_de/null - umount /data_mirror/storage_area/0 - umount /data_mirror/storage_area - umount /data_mirror/cur_profiles - umount /data_mirror/ref_profiles - umount /data_mirror - remount_userdata - start bootanim - -on userspace-reboot-resume - trigger userspace-reboot-fs-remount - trigger post-fs-data - trigger zygote-start - trigger early-boot - trigger boot - -on property:sys.boot_completed=1 && property:sys.init.userspace_reboot.in_progress=1 - setprop sys.init.userspace_reboot.in_progress "" - # Multi-Gen LRU Experiment on property:persist.device_config.mglru_native.lru_gen_config=none write /sys/kernel/mm/lru_gen/enabled 0 diff --git a/rootdir/init.usb.rc b/rootdir/init.usb.rc index dde784e25..b30d6d02c 100644 --- a/rootdir/init.usb.rc +++ b/rootdir/init.usb.rc @@ -139,7 +139,3 @@ on property:sys.usb.typec.power_role=source on property:sys.usb.typec.power_role=sink write /sys/class/dual_role_usb/otg_default/power_role ${sys.usb.typec.power_role} setprop sys.usb.typec.state ${sys.usb.typec.power_role} - -on userspace-reboot-requested - setprop sys.usb.config "" - setprop sys.usb.state "" From f91503bd18de89c38be495b14ca045be31fd54d7 Mon Sep 17 00:00:00 2001 From: Jooyung Han Date: Fri, 9 Aug 2024 16:17:20 +0900 Subject: [PATCH 2/2] Clean up userspace-reboot (#2) Bug: 292469129 Test: CtsInitTestCases Test: system/core/bootstat/boot_reason_test.sh Change-Id: I00deb50c5634ade6b69d5b6bf4d08c5101e0beb8 --- init/builtins.cpp | 26 ++++++++------------------ 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/init/builtins.cpp b/init/builtins.cpp index 2b965b66c..122adb7f6 100644 --- a/init/builtins.cpp +++ b/init/builtins.cpp @@ -1137,29 +1137,19 @@ static Result ExecWithFunctionOnFailure(const std::vector& ar } static Result 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( - {"--prompt_and_wipe_data", "--reason="s + reboot_reason}); - !result.ok()) { - LOG(FATAL) << "Could not reboot into recovery: " << result.error(); - } - } else { - LOG(ERROR) << "Failure (reboot suppressed): " << reboot_reason; + if (IsFbeEnabled() && !android::gsi::IsGsiRunning()) { + LOG(ERROR) << message << ": Rebooting into recovery, reason: " << reboot_reason; + if (auto result = reboot_into_recovery( + {"--prompt_and_wipe_data", "--reason="s + reboot_reason}); + !result.ok()) { + LOG(FATAL) << "Could not reboot into recovery: " << result.error(); } } else { - LOG(ERROR) << message << ": rebooting, reason: " << reboot_reason; - trigger_shutdown("reboot," + reboot_reason); + LOG(ERROR) << "Failure (reboot suppressed): " << reboot_reason; } };