52b84b
From b89a1a9d19aa806feb984c8dba25116b5b5a52bc Mon Sep 17 00:00:00 2001
be3800
From: HATAYAMA Daisuke <d.hatayama@fujitsu.com>
be3800
Date: Wed, 24 Jul 2019 23:54:48 -0400
be3800
Subject: [PATCH] swap: finish the secondary swap units' jobs if deactivation
be3800
 of the primary swap unit fails
be3800
be3800
Currently, if deactivation of the primary swap unit fails:
be3800
be3800
    # LANG=C systemctl --no-pager stop dev-mapper-fedora\\x2dswap.swap
be3800
    Job for dev-mapper-fedora\x2dswap.swap failed.
be3800
    See "systemctl status "dev-mapper-fedora\\x2dswap.swap"" and "journalctl -xe" for details.
be3800
be3800
then there are still the running stop jobs for all the secondary swap units
be3800
that follow the primary one:
be3800
be3800
    # systemctl list-jobs
be3800
     JOB UNIT                                                                                                         TYPE STATE
be3800
     3233 dev-disk-by\x2duuid-2dc8b9b1\x2da0a5\x2d44d8\x2d89c4\x2d6cdd26cd5ce0.swap                                    stop running
be3800
     3232 dev-dm\x2d1.swap                                                                                             stop running
be3800
     3231 dev-disk-by\x2did-dm\x2duuid\x2dLVM\x2dyuXWpCCIurGzz2nkGCVnUFSi7GH6E3ZcQjkKLnF0Fil0RJmhoLN8fcOnDybWCMTj.swap stop running
be3800
     3230 dev-disk-by\x2did-dm\x2dname\x2dfedora\x2dswap.swap                                                          stop running
be3800
     3234 dev-fedora-swap.swap                                                                                         stop running
be3800
be3800
    5 jobs listed.
be3800
be3800
This remains endlessly because their JobTimeoutUSec is infinity:
be3800
be3800
    # LANG=C systemctl show -p JobTimeoutUSec dev-fedora-swap.swap
be3800
    JobTimeoutUSec=infinity
be3800
be3800
If this issue happens during system shutdown, the system shutdown appears to
be3800
get hang and the system will be forcibly shutdown or rebooted 30 minutes later
be3800
by the following configuration:
be3800
be3800
    # grep -E "^JobTimeout" /usr/lib/systemd/system/reboot.target
be3800
    JobTimeoutSec=30min
be3800
    JobTimeoutAction=reboot-force
be3800
be3800
The scenario in the real world seems that there is some service unit with
be3800
KillMode=none, processes whose memory is being swapped out are not killed
be3800
during stop operation in the service unit and then swapoff command fails.
be3800
be3800
On the other hand, it works well in successful case of swapoff command because
be3800
the secondary jobs monitor /proc/swaps file and can detect deletion of the
be3800
corresponding swap file.
be3800
be3800
This commit fixes the issue by finishing the secondary swap units' jobs if
be3800
deactivation of the primary swap unit fails.
be3800
be3800
Fixes: #11577
be3800
(cherry picked from commit 9c1f969d40f84d5cc98d810bab8b24148b2d8928)
be3800
52b84b
Resolves: #1749622
be3800
---
be3800
 src/core/swap.c | 10 ++++++++--
be3800
 1 file changed, 8 insertions(+), 2 deletions(-)
be3800
be3800
diff --git a/src/core/swap.c b/src/core/swap.c
be3800
index e717dbb54a..66a62d8a37 100644
be3800
--- a/src/core/swap.c
be3800
+++ b/src/core/swap.c
be3800
@@ -682,9 +682,15 @@ static void swap_enter_active(Swap *s, SwapResult f) {
be3800
 static void swap_enter_dead_or_active(Swap *s, SwapResult f) {
be3800
         assert(s);
be3800
 
be3800
-        if (s->from_proc_swaps)
be3800
+        if (s->from_proc_swaps) {
be3800
+                Swap *other;
be3800
+
be3800
                 swap_enter_active(s, f);
be3800
-        else
be3800
+
be3800
+                LIST_FOREACH_OTHERS(same_devnode, other, s)
be3800
+                        if (UNIT(other)->job)
be3800
+                                swap_enter_dead_or_active(other, f);
be3800
+        } else
be3800
                 swap_enter_dead(s, f);
be3800
 }
be3800