diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h index cdff06efe..9eb89b612 100644 --- a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h +++ b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h @@ -395,6 +395,10 @@ class SnapshotManager final : public ISnapshotManager { // first-stage to decide whether to launch snapuserd. bool IsSnapuserdRequired(); + // This is primarily used to device reboot. If OTA update is in progress, + // init will avoid killing processes + bool IsUserspaceSnapshotUpdateInProgress(); + enum class SnapshotDriver { DM_SNAPSHOT, DM_USER, diff --git a/fs_mgr/libsnapshot/snapshot.cpp b/fs_mgr/libsnapshot/snapshot.cpp index 6fed09cbc..10d2f185a 100644 --- a/fs_mgr/libsnapshot/snapshot.cpp +++ b/fs_mgr/libsnapshot/snapshot.cpp @@ -4349,5 +4349,16 @@ std::string SnapshotManager::ReadSourceBuildFingerprint() { return status.source_build_fingerprint(); } +bool SnapshotManager::IsUserspaceSnapshotUpdateInProgress() { + auto slot = GetCurrentSlot(); + if (slot == Slot::Target) { + if (IsSnapuserdRequired()) { + return true; + } + } + + return false; +} + } // namespace snapshot } // namespace android diff --git a/init/reboot.cpp b/init/reboot.cpp index a3fc53419..27a7876db 100644 --- a/init/reboot.cpp +++ b/init/reboot.cpp @@ -51,6 +51,7 @@ #include #include #include +#include #include #include #include @@ -422,11 +423,31 @@ static UmountStat TryUmountAndFsck(unsigned int cmd, bool run_fsck, if (run_fsck && !FindPartitionsToUmount(&block_devices, &emulated_devices, false)) { return UMOUNT_STAT_ERROR; } - + auto sm = snapshot::SnapshotManager::New(); + bool ota_update_in_progress = false; + if (sm->IsUserspaceSnapshotUpdateInProgress()) { + LOG(INFO) << "OTA update in progress"; + ota_update_in_progress = true; + } UmountStat stat = UmountPartitions(timeout - t.duration()); if (stat != UMOUNT_STAT_SUCCESS) { LOG(INFO) << "umount timeout, last resort, kill all and try"; if (DUMP_ON_UMOUNT_FAILURE) DumpUmountDebuggingInfo(); + // Since umount timedout, we will try to kill all processes + // and do one more attempt to umount the partitions. + // + // However, if OTA update is in progress, we don't want + // to kill the snapuserd daemon as the daemon will + // be serving I/O requests. Killing the daemon will + // end up with I/O failures. If the update is in progress, + // we will just return the umount failure status immediately. + // This is ok, given the fact that killing the processes + // and doing an umount is just a last effort. We are + // still not doing fsck when all processes are killed. + // + if (ota_update_in_progress) { + return stat; + } KillAllProcesses(); // even if it succeeds, still it is timeout and do not run fsck with all processes killed UmountStat st = UmountPartitions(0ms);