dynup / kpatch

kpatch - live kernel patching
GNU General Public License v2.0
1.49k stars 305 forks source link

kpatch/kpatch: Optimize patch transition timing with a while loop #1408

Open oceansue opened 1 month ago

oceansue commented 1 month ago

Optimize the timing of patch transitions by using a while loop to check the transition status, replacing the for loop with a 1-second sleep. This approach reduces the likelihood of timeouts due to system load, potentially speeding up patch transitions.

oceansue commented 1 month ago

issues: https://github.com/dynup/kpatch/issues/1409

oceansue commented 1 month ago

@joe-lawrence @jpoimboe PTAL. Thanks. Fix SC2004 warnings in kpatch script.

joe-lawrence commented 1 month ago

Hi @oceansue , a few questions and comments about the PR:

oceansue commented 1 month ago

Hi @joe-lawrence ,Thank you for your response:

I‘ve been considering whether there might be a better solution for this issue (#1409) on my system. But so far, This patch seems to be working well. However, It does result in a short-term increase in CPU load.

joe-lawrence commented 1 month ago

Hi @oceansue :

Given the long transition time reported in #1409, I might have expected a change like:

diff --git a/kpatch/kpatch b/kpatch/kpatch
index edfccfead917..0ca6aaf78fd1 100755
--- a/kpatch/kpatch
+++ b/kpatch/kpatch
@@ -26,9 +26,9 @@
 INSTALLDIR=/var/lib/kpatch
 SCRIPTDIR="$(readlink -f "$(dirname "$(type -p "$0")")")"
 VERSION="0.9.9"
-POST_ENABLE_WAIT=15    # seconds
-POST_SIGNAL_WAIT=60    # seconds
-MODULE_REF_WAIT=15     # seconds
+POST_ENABLE_WAIT="${POST_ENABLE_WAIT:-15}"     # seconds
+POST_SIGNAL_WAIT="${POST_SIGNAL_WAIT:-60}"     # seconds
+MODULE_REF_WAIT="${MODULE_REF_WAIT:-15}"       # seconds

 # How many times to try loading the patch if activeness safety check fails.
 MAX_LOAD_ATTEMPTS=5

which would let the user set POST_ENABLE_WAIT, POST_SIGNAL_WAIT, MODULE_REF_WAIT environment variables without the script overriding them (ie, $ POST_ENABLE_WAIT=1500 ./kpatch/kpatch).

oceansue commented 5 days ago

I've been trying to fix this recently, but unfortunately, I haven't made any progress. It seems that this commit is the only one that can solve the problem I'm encountering. I want to find a way to minimize the modification of code functionality and meet my needs.

This is the patch I'm considering.

diff --git a/kpatch/kpatch b/kpatch/kpatch
index edfccfe..815dacb 100755
--- a/kpatch/kpatch
+++ b/kpatch/kpatch
@@ -245,29 +245,32 @@ signal_stalled_processes() {

 wait_for_patch_transition() {
        local module="$1"
-       local i
+       local i=0

        in_transition "$module" || return 0

        echo "waiting (up to $POST_ENABLE_WAIT seconds) for patch transition to complete..."
-       for (( i=0; i<POST_ENABLE_WAIT; i++ )); do
+       start_time=$SECONDS
+       while [ $i -lt $POST_ENABLE_WAIT ]; do
                if ! in_transition "$module" ; then
                        echo "transition complete ($i seconds)"
+                      sleep 1s
                        return 0
                fi
-               sleep 1s
+               i=$(( SECONDS - start_time ))
        done

        echo "patch transition has stalled!"
        signal_stalled_processes

        echo "waiting (up to $POST_SIGNAL_WAIT seconds) for patch transition to complete..."
-       for (( i=0; i<POST_SIGNAL_WAIT; i++ )); do
+       start_time=$SECONDS
+       while [ $i -lt $POST_SIGNAL_WAIT ]; do
                if ! in_transition "$module" ; then
                        echo "transition complete ($i seconds)"
                        return 0
                fi
-               sleep 1s
+               i=$(( SECONDS - start_time ))
        done

        return 1
joe-lawrence commented 2 days ago

@oceansue : with the minimal patch in place, what is reported by "transition complete ($i seconds)" ? Also, can you attach/inline an example kpatch that requires the modification? Thanks.

oceansue commented 2 days ago

Test environment: kernel: 4.19.180 The cpu is the company's own 32 cores

use https://github.com/dynup/kpatch/pull/1408#issuecomment-2380661870 patch:

sudo ./kpatch load ../kpatch-build/livepatch-cmdline.ko 
loading patch module: ../kpatch-build/livepatch-cmdline.ko
waiting (up to 15 seconds) for patch transition to complete...
patch transition has stalled!
signaling stalled process(es):
waiting (up to 60 seconds) for patch transition to complete...
transition complete (11 seconds)
ocean@ocean-PC:~/kpatch/kpatch$ sudo ./kpatch unload ../kpatch-build/livepatch-cmdline.ko 
disabling patch module: livepatch_cmdline
waiting (up to 15 seconds) for patch transition to complete...
patch transition has stalled!
signaling stalled process(es):
waiting (up to 60 seconds) for patch transition to complete...
transition complete (8 seconds)
unloading patch module: livepatch_cmdline

revert https://github.com/dynup/kpatch/pull/1408#issuecomment-2380661870 patch:

ocean@ocean-PC:~/kpatch/kpatch$ sudo ./kpatch load ../kpatch-build/livepatch-cmdline.ko 
module already loaded, re-enabling
waiting (up to 15 seconds) for patch transition to complete...
patch transition has stalled!
signaling stalled process(es):
waiting (up to 60 seconds) for patch transition to complete...

Stalled processes:
module livepatch_cmdline did not complete its transition, disabling...
waiting (up to 15 seconds) for patch transition to complete...
transition complete (2 seconds)
kpatch: error: failed to re-enable module livepatch_cmdline (transition stalled), patch disabled

For other CPUs, if the transition can be completed in 15 seconds, the patch will have no effect. If it cannot be completed in more than 15 seconds, the program will enter a 60 second transition period during which the program will frequently access the sys interface to speed up the transition.

Also, I found that the bug seems to be caused by multiple cores, and when I limit the number of cores to less than 8, the transformation can be done successfully. When the number of cores is more than 8, the transformation doesn't go so well and requires this patch to fix it.I was unable to find a multi-core (>32) processor with x86 architecture to verify.