lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite for Android: free password hash cracker in your pocket
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20180118161238.13792-2-dima@arista.com>
Date:   Thu, 18 Jan 2018 16:12:33 +0000
From:   Dmitry Safonov <dima@...sta.com>
To:     linux-kernel@...r.kernel.org
Cc:     Dmitry Safonov <dima@...sta.com>,
        Andrew Morton <akpm@...ux-foundation.org>,
        David Miller <davem@...emloft.net>,
        Eric Dumazet <edumazet@...gle.com>,
        Frederic Weisbecker <fweisbec@...il.com>,
        Hannes Frederic Sowa <hannes@...essinduktion.org>,
        Ingo Molnar <mingo@...nel.org>,
        "Levin, Alexander (Sasha Levin)" <alexander.levin@...izon.com>,
        Linus Torvalds <torvalds@...ux-foundation.org>,
        Mauro Carvalho Chehab <mchehab@...pensource.com>,
        Mike Galbraith <efault@....de>,
        Paolo Abeni <pabeni@...hat.com>,
        "Paul E. McKenney" <paulmck@...ux.vnet.ibm.com>,
        Peter Zijlstra <peterz@...radead.org>,
        Radu Rendec <rrendec@...sta.com>,
        Rik van Riel <riel@...hat.com>,
        Stanislaw Gruszka <sgruszka@...hat.com>,
        Thomas Gleixner <tglx@...utronix.de>,
        Wanpeng Li <wanpeng.li@...mail.com>
Subject: [RFC 1/6] softirq: Add softirq_groups boot parameter

ksoftirqd thread allows to defer softirqs if the system is under storm.
While it prevents userspace from cpu-time starving, it increases
latencies for other softirqs (that are not raised under storm).

As creation of one ksoftirqd thread per-each-softirq-per-cpu will be
insane on a huge machines, separate softirqs by groups.
It will allow to defer softirqs of one group and continue servicing
from other. That means that under a storm of one group's softirqs,
softirqs from the other group will be serviced as they come and will
not have latency issues.
For each softirq group will be created a per-cpu kthread which
will process deferred softirqs of the group.

The parameter will allow an admin define how many ksoftirqd threads
will be created on each cpu and which softirqs have the same
deferring group.

Signed-off-by: Dmitry Safonov <dima@...sta.com>
---
 Documentation/admin-guide/kernel-parameters.txt | 16 +++++
 include/linux/interrupt.h                       |  1 +
 kernel/softirq.c                                | 87 +++++++++++++++++++++++++
 3 files changed, 104 insertions(+)

diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 46b26bfee27b..d5c44703a299 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -3940,6 +3940,22 @@
 			Format: <integer>
 			Default: -1 (no limit)
 
+	softirq_groups=
+			[KNL] The count and contents of softirq groups.
+			Format:[group1],[group2],[groupN]
+			where group is <softirq1>/<softirq2>/<softirqM>
+			E.g: softirq_groups=HI/TIMER/HRTIMER,NET_TX/NET_RX,BLOCK
+
+			Defines how many ksoftirqd threads create *per-cpu*.
+			For each group one ksoftirqd thread is created.
+			The total number of threads created is
+			(NR_CPUS * NR_SOFTIRQ_GROUPS).
+			Admin can define one softirq in different softirq
+			groups. Softirqs those have no group defined will
+			be put in default softirq_group. If all softirqs
+			have been placed into groups default group is not
+			created.
+
 	softlockup_panic=
 			[KNL] Should the soft-lockup detector generate panics.
 			Format: <integer>
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
index 69c238210325..5bb6b435f0bb 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -486,6 +486,7 @@ extern const char * const softirq_to_name[NR_SOFTIRQS];
 struct softirq_action
 {
 	void	(*action)(struct softirq_action *);
+	u32	group_mask;
 };
 
 asmlinkage void do_softirq(void);
diff --git a/kernel/softirq.c b/kernel/softirq.c
index 2f5e87f1bae2..c9aecdd57107 100644
--- a/kernel/softirq.c
+++ b/kernel/softirq.c
@@ -54,6 +54,7 @@ EXPORT_SYMBOL(irq_stat);
 #endif
 
 static struct softirq_action softirq_vec[NR_SOFTIRQS] __cacheline_aligned_in_smp;
+static unsigned __initdata nr_softirq_groups = 0;
 
 DEFINE_PER_CPU(struct task_struct *, ksoftirqd);
 
@@ -635,10 +636,25 @@ void tasklet_hrtimer_init(struct tasklet_hrtimer *ttimer,
 }
 EXPORT_SYMBOL_GPL(tasklet_hrtimer_init);
 
+static void __init setup_default_softirq_group(unsigned nr)
+{
+	unsigned i;
+
+	for (i = 0; i < NR_SOFTIRQS; i++) {
+		u32 *gr_mask = &softirq_vec[i].group_mask;
+
+		if (!*gr_mask)
+			*gr_mask |= (1 << nr);
+		pr_debug("softirq-%s: %#x\n", softirq_to_name[i], *gr_mask);
+	}
+}
+
 void __init softirq_init(void)
 {
 	int cpu;
 
+	setup_default_softirq_group(nr_softirq_groups++);
+
 	for_each_possible_cpu(cpu) {
 		per_cpu(tasklet_vec, cpu).tail =
 			&per_cpu(tasklet_vec, cpu).head;
@@ -750,6 +766,77 @@ static __init int spawn_ksoftirqd(void)
 }
 early_initcall(spawn_ksoftirqd);
 
+static __init __u32 parse_softirq_name(char *name, size_t len)
+{
+	__u32 i;
+
+	for (i = 0; i < NR_SOFTIRQS; i++)
+		if (strncmp(name, softirq_to_name[i], len) == 0)
+			return i;
+
+	pr_warn("softirq: Ignored `%.*s' in softirq group", (int)len, name);
+
+	return NR_SOFTIRQS;
+}
+
+static bool __init parse_softirq_group(char *start, char *end, u32 group)
+{
+	char *next_softirq = strchrnul(start, '/');
+	bool is_empty = true;
+	u32 softirq_nr;
+
+	if (next_softirq == start)
+		return !is_empty;
+
+	do {
+		next_softirq = min(next_softirq, end);
+
+		softirq_nr = parse_softirq_name(start, next_softirq - start);
+		if (softirq_nr < NR_SOFTIRQS) {
+			softirq_vec[softirq_nr].group_mask |= (1 << group);
+			is_empty = false;
+		}
+
+		if (next_softirq == end)
+			break;
+
+		start = next_softirq + 1;
+		next_softirq = strchrnul(start, '/');
+	} while (1);
+
+	return !is_empty;
+}
+
+/*
+ * Format e.g.:
+ * softirq_groups=HI/TIMER/HRTIMER,NET_TX/NET_RX,BLOCK,TASKLET
+ * Admin *can* define one softirq in different groups.
+ * Softirqs those have no group defined will be put in default softirq_group.
+ * If all softirqs have been placed into groups, default group is not created.
+ */
+static int __init setup_softirq_groups(char *s)
+{
+	char *next_group = strchrnul(s, ',');
+	unsigned i = 0;
+
+	do {
+		/* Skip empty softirq groups. */
+		if (parse_softirq_group(s, next_group, i))
+			i++;
+
+		if (*next_group == '\0')
+			break;
+
+		s = next_group + 1;
+		next_group = strchrnul(s, ',');
+	} while(i < 31); /* if there is default softirq group it's nr 31 */
+
+	nr_softirq_groups = i;
+
+	return 0;
+}
+early_param("softirq_groups", setup_softirq_groups);
+
 /*
  * [ These __weak aliases are kept in a separate compilation unit, so that
  *   GCC does not inline them incorrectly. ]
-- 
2.13.6

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ