]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
core/unit: allow overriding an ongoing freeze operation
authormsizanoen1 <msizanoen@qtmlabs.xyz>
Wed, 7 Dec 2022 13:46:01 +0000 (20:46 +0700)
committermsizanoen1 <msizanoen@qtmlabs.xyz>
Wed, 7 Dec 2022 23:54:53 +0000 (00:54 +0100)
Sometimes a freeze operation can hang due to the presence of kernel
threads inside the unit cgroup (e.g. QEMU-KVM). This ensures that the
ThawUnit operation invoked by systemd-sleep at wakeup always thaws the
unit.

src/core/dbus-unit.c
src/core/dbus-unit.h
src/core/unit.c
src/libsystemd/sd-bus/bus-common-errors.h

index 19a71b6cb388f2ee447b0b380eff3d86f8bb452c..0702373ab0f427cb7bec5621c1d972b44eb19f3d 100644 (file)
@@ -782,14 +782,15 @@ static int bus_unit_method_freezer_generic(sd_bus_message *message, void *userda
         if (r == 0)
                 reply_no_delay = true;
 
-        assert(!u->pending_freezer_message);
+        if (u->pending_freezer_message) {
+                bus_unit_send_pending_freezer_message(u, true);
+                assert(!u->pending_freezer_message);
+        }
 
-        r = sd_bus_message_new_method_return(message, &u->pending_freezer_message);
-        if (r < 0)
-                return r;
+        u->pending_freezer_message = sd_bus_message_ref(message);
 
         if (reply_no_delay) {
-                r = bus_unit_send_pending_freezer_message(u);
+                r = bus_unit_send_pending_freezer_message(u, false);
                 if (r < 0)
                         return r;
         }
@@ -1661,7 +1662,8 @@ void bus_unit_send_pending_change_signal(Unit *u, bool including_new) {
         bus_unit_send_change_signal(u);
 }
 
-int bus_unit_send_pending_freezer_message(Unit *u) {
+int bus_unit_send_pending_freezer_message(Unit *u, bool cancelled) {
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         int r;
 
         assert(u);
@@ -1669,7 +1671,18 @@ int bus_unit_send_pending_freezer_message(Unit *u) {
         if (!u->pending_freezer_message)
                 return 0;
 
-        r = sd_bus_send(NULL, u->pending_freezer_message, NULL);
+        if (cancelled)
+                r = sd_bus_message_new_method_error(
+                                u->pending_freezer_message,
+                                &reply,
+                                &SD_BUS_ERROR_MAKE_CONST(
+                                                BUS_ERROR_FREEZE_CANCELLED, "Freeze operation aborted"));
+        else
+                r = sd_bus_message_new_method_return(u->pending_freezer_message, &reply);
+        if (r < 0)
+                return r;
+
+        r = sd_bus_send(NULL, reply, NULL);
         if (r < 0)
                 log_warning_errno(r, "Failed to send queued message, ignoring: %m");
 
index 643edcd87e972a44a9efac907708e11a2111fc57..6b7828e4bae50e46518eef7521db7daf9496bed8 100644 (file)
@@ -10,7 +10,7 @@ extern const sd_bus_vtable bus_unit_cgroup_vtable[];
 
 void bus_unit_send_change_signal(Unit *u);
 void bus_unit_send_pending_change_signal(Unit *u, bool including_new);
-int bus_unit_send_pending_freezer_message(Unit *u);
+int bus_unit_send_pending_freezer_message(Unit *u, bool cancelled);
 void bus_unit_send_removed_signal(Unit *u);
 
 int bus_unit_method_start_generic(sd_bus_message *message, Unit *u, JobType job_type, bool reload_if_possible, sd_bus_error *error);
index 29b07a6e7a84dc43b657ac81fc1ee6da3794b2bb..e0d54d8fe184d420c5eb920caab40419481fd309 100644 (file)
@@ -5829,7 +5829,7 @@ void unit_frozen(Unit *u) {
 
         u->freezer_state = FREEZER_FROZEN;
 
-        bus_unit_send_pending_freezer_message(u);
+        bus_unit_send_pending_freezer_message(u, false);
 }
 
 void unit_thawed(Unit *u) {
@@ -5837,7 +5837,7 @@ void unit_thawed(Unit *u) {
 
         u->freezer_state = FREEZER_RUNNING;
 
-        bus_unit_send_pending_freezer_message(u);
+        bus_unit_send_pending_freezer_message(u, false);
 }
 
 static int unit_freezer_action(Unit *u, FreezerAction action) {
@@ -5862,7 +5862,8 @@ static int unit_freezer_action(Unit *u, FreezerAction action) {
         if (s != UNIT_ACTIVE)
                 return -EHOSTDOWN;
 
-        if (IN_SET(u->freezer_state, FREEZER_FREEZING, FREEZER_THAWING))
+        if ((IN_SET(u->freezer_state, FREEZER_FREEZING, FREEZER_THAWING) && action == FREEZER_FREEZE) ||
+            (u->freezer_state == FREEZER_THAWING && action == FREEZER_THAW))
                 return -EALREADY;
 
         r = method(u);
index d4a1fb689ebf2faba9129d2e9449dadeb6672684..40d6abc41319671c371754613befe687108ac2a2 100644 (file)
@@ -31,6 +31,7 @@
 #define BUS_ERROR_NOTHING_TO_CLEAN             "org.freedesktop.systemd1.NothingToClean"
 #define BUS_ERROR_UNIT_BUSY                    "org.freedesktop.systemd1.UnitBusy"
 #define BUS_ERROR_UNIT_INACTIVE                "org.freedesktop.systemd1.UnitInactive"
+#define BUS_ERROR_FREEZE_CANCELLED             "org.freedesktop.systemd1.FreezeCancelled"
 
 #define BUS_ERROR_NO_SUCH_MACHINE              "org.freedesktop.machine1.NoSuchMachine"
 #define BUS_ERROR_NO_SUCH_IMAGE                "org.freedesktop.machine1.NoSuchImage"