From e5c023a1c20058703f1517a48848b4ecec563db6 Mon Sep 17 00:00:00 2001
From: xujing <xujing99@huawei.com>
Date: Mon, 10 Jan 2022 22:42:30 +0800
Subject: [PATCH] core: skip change device to dead in manager_catchup during
 booting

There is a problem during booting as follows:
1.systemd is processing all udev devices state but not finished
2.now calling daemon-reload, it will serialize and deserialize the device state
3.after deserialize, some devices is processed finished, it will cause devices
  state changed when calling manager_catchup and then set device to DEVICE_DEAD
  later which will cause some fs unmounted.

This patch just fix that fs will not unmounted during booting when calling
daemon-reload, if boot time is more than 10min, just ensure fs will not
unmounted during 10min after booting.
---
 src/core/device.c  | 16 ++++++++++++++++-
 src/core/manager.c |  5 +++++
 src/core/manager.h |  1 +
 3 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/src/core/device.c b/src/core/device.c
index 8f30c4e..71cb2a1 100644
--- a/src/core/device.c
+++ b/src/core/device.c
@@ -646,7 +647,10 @@ static int device_process_new(Manager *m, sd_device *dev) {
 }
 
 static void device_found_changed(Device *d, DeviceFound previous, DeviceFound now) {
+        Manager *m;
+
         assert(d);
+        m = UNIT(d)->manager;
 
         /* Didn't exist before, but does now? if so, generate a new invocation ID for it */
         if (previous == DEVICE_NOT_FOUND && now != DEVICE_NOT_FOUND)
@@ -659,10 +663,21 @@ static void device_found_changed(Device *d, DeviceFound previous, DeviceFound no
                 /* If the device has not been seen by udev yet, but is now referenced by the kernel, then we assume the
                  * kernel knows it now, and udev might soon too. */
                 device_set_state(d, DEVICE_TENTATIVE);
-        else
+        else {
+                if (m->in_manager_catchup && !MANAGER_IS_FINISHED(m)) {
+                        dual_timestamp boot_timestamp;
+
+                        dual_timestamp_get(&boot_timestamp);
+                        if (boot_timestamp.monotonic < 10*USEC_PER_MINUTE) {
+                                log_info("Want to change device to dead in manager_catchup during booting, skipping!");
+                                return;
+                        }
+                }
+
                 /* If nobody sees the device, or if the device was previously seen by udev and now is only referenced
                  * from the kernel, then we consider the device is gone, the kernel just hasn't noticed it yet. */
                 device_set_state(d, DEVICE_DEAD);
+        }
 }
 
 static void device_update_found_one(Device *d, DeviceFound found, DeviceFound mask) {
diff --git a/src/core/manager.c b/src/core/manager.c
index 41b7cf7..b948ac6 100644
--- a/src/core/manager.c
+++ b/src/core/manager.c
@@ -788,6 +788,7 @@ int manager_new(UnitFileScope scope, ManagerTestRunFlags test_run_flags, Manager
                 .test_run_flags = test_run_flags,
 
                 .default_oom_policy = OOM_STOP,
+                .in_manager_catchup = false,
         };
 
 #if ENABLE_EFI
@@ -1475,6 +1476,8 @@ static void manager_catchup(Manager *m) {
 
         log_debug("Invoking unit catchup() handlers…");
 
+        m->in_manager_catchup = true;
+
         /* Let's catch up on any state changes that happened while we were reloading/reexecing */
         HASHMAP_FOREACH_KEY(u, k, m->units) {
 
@@ -1484,6 +1487,8 @@ static void manager_catchup(Manager *m) {
 
                 unit_catchup(u);
         }
+
+        m->in_manager_catchup = false;
 }
 
 static void manager_distribute_fds(Manager *m, FDSet *fds) {
diff --git a/src/core/manager.h b/src/core/manager.h
index d1e540a..73c149f 100644
--- a/src/core/manager.h
+++ b/src/core/manager.h
@@ -423,6 +423,7 @@ struct Manager {
         unsigned notifygen;
 
         bool honor_device_enumeration;
+        bool in_manager_catchup;
 
         VarlinkServer *varlink_server;
         /* Only systemd-oomd should be using this to subscribe to changes in ManagedOOM settings */
-- 
2.23.0

