irqbalance/0005-Add-banscript-option.patch
Petr Holasek 914ea28980 Make irqbalance scan for new irqs when it detects new irqs (bz832815)
- Fixes SIGFPE crash for some banning configuration (bz849792)
- Fixes affinity_hint values processing (bz832815)
- Adds banirq and bansript options (bz837049)
- imake isn't needed for building any more (bz844359)
- Fixes clogging of syslog (bz837646)
- Added IRQBALANCE_ARGS variable for passing arguments via systemd(bz837048)
- Fixes --hint-policy=subset behavior (bz844381)
2012-08-23 15:27:51 +02:00

219 lines
6.5 KiB
Diff

From b18eb8f6b28cc9b0816be0fb8fe3468c9f64f345 Mon Sep 17 00:00:00 2001
From: Neil Horman <nhorman@tuxdriver.com>
Date: Thu, 5 Jul 2012 14:54:35 -0400
Subject: [PATCH 5/8] Add banscript option
Its been requested in several different ways, that irqbalance have a more robust
mechanism for setting balancing policy at run time. While I don't feel its
apropriate to have irqbalance be able to implement arbitrary balance policy
(having a flexible mechanism to define which irqs should be placed where can
become exceedingly complex), I do think we need some mechanism that easily
allows users to dynamically exclude irqs from the irqbalance policy at run time.
The banscript option does exactly this. It allows the user to point irqbalance
toward an exacutable file that is run one for each irq deiscovered passing the
sysfs path of the device and an irq vector as arguments. A zero exit code tells
irqbalance to manage the irq as it normally would, while a non-zero exit tells
irqbalance to ignore the interrupt entirely. This provides adminstrators a code
point with which to exclude irqs dynamically based on any programatic
informatino available, and to manage those irqs independently, etither via
another irqbalance like program, or via static affinity setting.
Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
Reesolves: http://code.google.com/p/irqbalance/issues/detail?id=33
---
classify.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
irqbalance.1 | 11 +++++++++++
irqbalance.c | 25 +++++++++++++++++++++----
irqbalance.h | 1 +
4 files changed, 79 insertions(+), 4 deletions(-)
diff --git a/classify.c b/classify.c
index d59da7f..750d946 100644
--- a/classify.c
+++ b/classify.c
@@ -207,6 +207,43 @@ out:
return new;
}
+static int check_for_irq_ban(char *path, int irq)
+{
+ char *cmd;
+ int rc;
+
+ if (!banscript)
+ return 0;
+
+ cmd = alloca(strlen(path)+strlen(banscript)+32);
+ if (!cmd)
+ return 0;
+
+ sprintf(cmd, "%s %s %d",banscript, path, irq);
+ rc = system(cmd);
+
+ /*
+ * The system command itself failed
+ */
+ if (rc == -1) {
+ if (debug_mode)
+ printf("%s failed, please check the --banscript option\n", cmd);
+ else
+ syslog(LOG_INFO, "%s failed, please check the --banscript option\n", cmd);
+ return 0;
+ }
+
+ if (WEXITSTATUS(rc)) {
+ if (debug_mode)
+ printf("irq %d is baned by %s\n", irq, banscript);
+ else
+ syslog(LOG_INFO, "irq %d is baned by %s\n", irq, banscript);
+ return 1;
+ }
+ return 0;
+
+}
+
/*
* Figures out which interrupt(s) relate to the device we're looking at in dirname
*/
@@ -231,6 +268,10 @@ static void build_one_dev_entry(const char *dirname)
irqnum = strtol(entry->d_name, NULL, 10);
if (irqnum) {
sprintf(path, "%s/%s", SYSDEV_DIR, dirname);
+ if (check_for_irq_ban(path, irqnum)) {
+ add_banned_irq(irqnum);
+ continue;
+ }
new = add_one_irq_to_db(path, irqnum);
if (!new)
continue;
@@ -253,6 +294,11 @@ static void build_one_dev_entry(const char *dirname)
*/
if (irqnum) {
sprintf(path, "%s/%s", SYSDEV_DIR, dirname);
+ if (check_for_irq_ban(path, irqnum)) {
+ add_banned_irq(irqnum);
+ goto done;
+ }
+
new = add_one_irq_to_db(path, irqnum);
if (!new)
goto done;
diff --git a/irqbalance.1 b/irqbalance.1
index 978c7c1..63b0e26 100644
--- a/irqbalance.1
+++ b/irqbalance.1
@@ -69,6 +69,17 @@ Add the specified irq list to the set of banned irqs. irqbalance will not affect
the affinity of any irqs on the banned list, allowing them to be specified
manually. This option is addative and can be specified multiple times
+.TP
+.B --banscript=<script>
+Execute the specified script for each irq that is discovered, passing the sysfs
+path to the associated device as the first argument, and the irq vector as the
+second. An exit value of 0 tells irqbalance that this interrupt should balanced
+and managed as a normal irq, while a non-zero exit code indicates this irq
+should be ignored by irqbalance completely (see --banirq above). Use of this
+script provides users the ability to dynamically select which irqs get exluded
+from balancing, and provides an opportunity for manual affinity setting in one
+single code point.
+
.SH "ENVIRONMENT VARIABLES"
.TP
.B IRQBALANCE_ONESHOT
diff --git a/irqbalance.c b/irqbalance.c
index 5d40321..0184f0f 100644
--- a/irqbalance.c
+++ b/irqbalance.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2006, Intel Corporation
+ * Copyright (C) 2012, Neil Horman <nhorman@tuxdriver.com>
*
* This file is part of irqbalance
*
@@ -45,6 +46,7 @@ extern cpumask_t banned_cpus;
enum hp_e hint_policy = HINT_POLICY_SUBSET;
unsigned long power_thresh = ULONG_MAX;
unsigned long long cycle_count = 0;
+char *banscript = NULL;
void sleep_approx(int seconds)
{
@@ -66,6 +68,8 @@ struct option lopts[] = {
{"debug", 0, NULL, 'd'},
{"hintpolicy", 1, NULL, 'h'},
{"powerthresh", 1, NULL, 'p'},
+ {"banirq", 1 , NULL, 'i'},
+ {"banscript", 1, NULL, 'b'},
{0, 0, 0, 0}
};
@@ -79,9 +83,10 @@ static void parse_command_line(int argc, char **argv)
{
int opt;
int longind;
+ unsigned long val;
while ((opt = getopt_long(argc, argv,
- "odh:p:b:",
+ "odh:i:p:b:",
lopts, &longind)) != -1) {
switch(opt) {
@@ -193,6 +198,12 @@ int main(int argc, char** argv)
if (argc>1 && strstr(argv[1],"--oneshot"))
one_shot_mode=1;
#endif
+
+ /*
+ * Open the syslog connection
+ */
+ openlog(argv[0], 0, LOG_DAEMON);
+
if (getenv("IRQBALANCE_BANNED_CPUS")) {
cpumask_parse_user(getenv("IRQBALANCE_BANNED_CPUS"), strlen(getenv("IRQBALANCE_BANNED_CPUS")), banned_cpus);
}
@@ -221,8 +232,16 @@ int main(int argc, char** argv)
/* On single core UP systems irqbalance obviously has no work to do */
- if (core_count<2)
+ if (core_count<2) {
+ char *msg = "Balancing is ineffective on systems with a "
+ "single cache domain. Shutting down\n";
+
+ if (debug_mode)
+ printf("%s", msg);
+ else
+ syslog(LOG_INFO, "%s", msg);
exit(EXIT_SUCCESS);
+ }
/* On dual core/hyperthreading shared cache systems just do a one shot setup */
if (cache_domain_count==1)
one_shot_mode = 1;
@@ -231,8 +250,6 @@ int main(int argc, char** argv)
if (daemon(0,0))
exit(EXIT_FAILURE);
- openlog(argv[0], 0, LOG_DAEMON);
-
#ifdef HAVE_LIBCAP_NG
// Drop capabilities
capng_clear(CAPNG_SELECT_BOTH);
diff --git a/irqbalance.h b/irqbalance.h
index 043bfe6..425e0dd 100644
--- a/irqbalance.h
+++ b/irqbalance.h
@@ -68,6 +68,7 @@ extern int need_rescan;
extern enum hp_e hint_policy;
extern unsigned long long cycle_count;
extern unsigned long power_thresh;
+extern char *banscript;
/*
* Numa node access routines
--
1.7.11.4