Calculate the number of cpus for kdump kernel to boot with.
The implementation relys on the following known factors:
*)reserved crash memory size for kdump kernel.
*)the number of cpus in first kernel.
*)architecture
-different memory overhead adding one extra cpu.
-different page size.
-different reserved crash memory policy.
*)large number of io devices
-probably requires large crash memory, so firstly it has
something to do with the reserved crash memory size.
-then we met an issue for x86_64: kdump runs out of vectors
with few cpus boot up, when requesting tons of irqs.
It gets different results with different crash memory size or
different architectures.
E.g. for x86_64:
"crash memory" "nr_cpus/maxcpus"
(0M, 256M]: 1
(256M, 1G]: 2
(1G, 2G]: 4
(2G, 4G]: 8
(4G, UMAX]: 16
E.g. for ppc64:
"crash memory" "nr_cpus/maxcpus"
(0M, 512M]: 1
(512M, 2G]: 2
(2G, 4G]: 4
(4G, 8G]: 8
(8G, UMAX]: 16
Signed-off-by: Xunlei Pang <xlpang(a)redhat.com>
---
kdumpctl | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 85 insertions(+), 1 deletion(-)
diff --git a/kdumpctl b/kdumpctl
index 9cd785a..36611c9 100755
--- a/kdumpctl
+++ b/kdumpctl
@@ -55,9 +55,92 @@ determine_dump_mode()
fi
}
+# Calculate the number of cpus for kdump kernel to boot with.
+# Known affected factors:
+# *)reserved crash memory size for kdump kernel.
+# *)the number of cpus in first kernel.
+# *)architecture
+# -different memory overhead adding one extra cpu.
+# -different page size.
+# -different reserved crash memory policy.
+# *)large number of io devices
+# -probably requires large crash memory, so firstly it has
+# something to do with the reserved crash memory size.
+# -then we met an issue for x86_64: kdump runs out of vectors
+# with few cpus boot up, when requesting tons of irqs.
calculate_kdump_cpus()
{
- echo -n "1"
+ local crashsize=$(get_reserved_memory_mb)
+ local stepsize nr_result nr_total nr_limit i
+ local nr_arch_min arch=$(uname -m)
+
+ # Every $stepsize in MB, one cpu is added. 256MB by default.
+ # e.g. If crashsize is 512MB for x86, boot 2 cpus for kdump.
+ stepsize=256
+ # Powerpc consumes more memory with an extra cpu boot up,
+ # compared with other arches. Double the stepsize for it.
+ if [ $arch = "ppc64" ]; then
+ stepsize=$(($stepsize * 2))
+ fi
+
+ # Get the total number of online cpus of the first kernel.
+ nr_total=$(nproc)
+ # Limit the number of cpu booted by kdump, more cpus means
+ # more risks for kdump in terms of memory. 16 is enough?
+ nr_limit=16
+
+ # (n*stepsize-stepsize, n*stepsize] -> n
+ crashsize=$((crashsize + $stepsize - 1))
+ nr_result=$(($crashsize / $stepsize))
+
+ # Conservatively(safer), round down to power of 2.
+ # Specifically, we want the following results:
+ # ( 0*stepsize, 1*stepsize]: 1
+ # ( 1*stepsize, 4*stepsize]: 2
+ # ( 4*stepsize, 8*stepsize]: 4
+ # ( 8*stepsize, 16*stepsize]: 8
+ # (16*stepsize, UMAX]: 16
+ i=0
+ while true; do
+ if [ $nr_result -le $((2**$i)) ]; then
+ if [ $i -gt 1 ]; then
+ i=$(($i - 1))
+ fi
+ nr_result=$((2**$i))
+ break
+ fi
+ i=$(($i + 1))
+ done
+
+ if [ $nr_result -gt $nr_limit ]; then
+ nr_result=$nr_limit
+ fi
+
+ # Special treatment for x86_64, in case kdump runs out of vectors.
+ if [ $arch = "x86_64" ]; then
+ nr_arch_min=$(ls /proc/irq/ -l | grep ^d | wc -l)
+ # Estimated minium cpus required by irqs(vectors), we roughly
+ # use 256-32(see kernel FIRST_EXTERNAL_VECTOR)=224 as the max
+ # supported vectors can be allocated to io devices per cpu.
+ nr_arch_min=$(($nr_arch_min + 223))
+ nr_arch_min=$(($nr_arch_min / 224))
+ if [ $nr_arch_min -gt 1 ]; then
+ # The system seems to have tons of irqs, add one more cpu
+ # for further safety.
+ nr_arch_min=$(($nr_arch_min + 1))
+ fi
+
+ if [ $nr_result -lt $nr_arch_min ]; then
+ nr_result=$nr_arch_min
+ fi
+ fi
+
+ # Never exceeds the actual number of cpus.
+ if [ $nr_result -gt $nr_total ]; then
+ nr_result=$nr_total
+ fi
+
+ echo -n "$nr_result"
}
# Automatically choose the number of cpus used by kdump kernel,
@@ -86,6 +169,7 @@ determine_kdump_cpus()
cpus=$(calculate_kdump_cpus)
sed -i $KDUMP_SYSCONFIG_FILE -e "s/nr_cpus=[0-9]*/nr_cpus=$cpus/g"
sed -i $KDUMP_SYSCONFIG_FILE -e "s/maxcpus=[0-9]*/maxcpus=$cpus/g"
+ echo "\"calc_kdump_cpus\" enabled: figured out $cpus cpus for kdump
kernel"
}
determine_kdump_sysconfig()
--
1.8.3.1