summaryrefslogtreecommitdiff
path: root/extra/irqbalance
diff options
context:
space:
mode:
authorroot <root@rshg054.dnsready.net>2013-02-10 01:12:52 -0800
committerroot <root@rshg054.dnsready.net>2013-02-10 01:12:52 -0800
commit1bb2648cde916ac27d3dd75d7b64a4ddc89787b7 (patch)
tree016bfa1969323404c37dbef29cfc7242a5a8e9f3 /extra/irqbalance
parente9c244cac8e5dc1c59c7e8b7bc885fef04224b70 (diff)
Sun Feb 10 01:12:35 PST 2013
Diffstat (limited to 'extra/irqbalance')
-rw-r--r--extra/irqbalance/irqbalance-2011-08-09.patch1584
1 files changed, 0 insertions, 1584 deletions
diff --git a/extra/irqbalance/irqbalance-2011-08-09.patch b/extra/irqbalance/irqbalance-2011-08-09.patch
deleted file mode 100644
index fcdb8bdbf..000000000
--- a/extra/irqbalance/irqbalance-2011-08-09.patch
+++ /dev/null
@@ -1,1584 +0,0 @@
-diff --git a/ChangeLog b/ChangeLog
-deleted file mode 100644
-index f5e9428..0000000
---- a/ChangeLog
-+++ /dev/null
-@@ -1,3 +0,0 @@
--This is all tracked in the SVN repo. This file is just here to keep the
--autotools from complaining
--
-diff --git a/Makefile.am b/Makefile.am
-index 9847232..188e34f 100644
---- a/Makefile.am
-+++ b/Makefile.am
-@@ -22,17 +22,17 @@
-
- AUTOMAKE_OPTIONS = no-dependencies
- ACLOCAL_AMFLAGS = -I m4
--EXTRA_DIST = README INSTALL COPYING autogen.sh m4/cap-ng.m4 misc/irqbalance.service
--
-+EXTRA_DIST = INSTALL COPYING autogen.sh misc/irqbalance.service
-+
- INCLUDES = -I${top_srcdir}
--LIBS = $(CAPNG_LDADD) $(GLIB_LIBS) @LIBS@
--AM_CFLAGS = $(GLIB_CFLAGS)
-+AM_CFLAGS = $(LIBCAP_NG_CFLAGS) $(GLIB_CFLAGS)
- AM_CPPFLAGS = -W -Wall -Wshadow -Wformat -Wundef -D_GNU_SOURCE
- noinst_HEADERS = bitmap.h constants.h cpumask.h irqbalance.h non-atomic.h \
- types.h
- sbin_PROGRAMS = irqbalance
- irqbalance_SOURCES = activate.c bitmap.c classify.c cputree.c irqbalance.c \
-- irqlist.c numa.c placement.c powermode.c procinterrupts.c
-+ irqlist.c numa.c placement.c procinterrupts.c
-+irqbalance_LDADD = $(LIBCAP_NG_LIBS) $(GLIB_LIBS)
- dist_man_MANS = irqbalance.1
-
- CONFIG_CLEAN_FILES = debug*.list config/*
-@@ -40,3 +40,6 @@ clean-generic:
- rm -rf autom4te*.cache
- rm -f *.rej *.orig *~
-
-+if LOCAL_GLIB
-+SUBDIRS = glib-local
-+endif
-diff --git a/NEWS b/NEWS
-deleted file mode 100644
-index 7cc0277..0000000
---- a/NEWS
-+++ /dev/null
-@@ -1 +0,0 @@
--No news currently
-diff --git a/README b/README
-deleted file mode 100644
-index e69de29..0000000
-diff --git a/activate.c b/activate.c
-index 292c44a..02fc8dc 100644
---- a/activate.c
-+++ b/activate.c
-@@ -1,5 +1,6 @@
- /*
- * Copyright (C) 2006, Intel Corporation
-+ * Copyright (C) 2012, Neil Horman <nhorman@tuxdriver.com>
- *
- * This file is part of irqbalance
- *
-@@ -31,34 +32,63 @@
-
- #include "irqbalance.h"
-
-+static int check_affinity(struct irq_info *info, cpumask_t applied_mask)
-+{
-+ cpumask_t current_mask;
-+ char buf[PATH_MAX];
-+ char *line = NULL;
-+ size_t size = 0;
-+ FILE *file;
-+
-+ sprintf(buf, "/proc/irq/%i/smp_affinity", info->irq);
-+ file = fopen(buf, "r");
-+ if (!file)
-+ return 1;
-+ if (getline(&line, &size, file)==0) {
-+ free(line);
-+ fclose(file);
-+ return 1;
-+ }
-+ cpumask_parse_user(line, strlen(line), current_mask);
-+ fclose(file);
-+ free(line);
-+
-+ return cpus_equal(applied_mask, current_mask);
-+}
-
- static void activate_mapping(struct irq_info *info, void *data __attribute__((unused)))
- {
- char buf[PATH_MAX];
- FILE *file;
- cpumask_t applied_mask;
-+ int valid_mask = 0;
-+
-+ if ((hint_policy == HINT_POLICY_EXACT) &&
-+ (!cpus_empty(info->affinity_hint))) {
-+ applied_mask = info->affinity_hint;
-+ valid_mask = 1;
-+ } else if (info->assigned_obj) {
-+ applied_mask = info->assigned_obj->mask;
-+ valid_mask = 1;
-+ if ((hint_policy == HINT_POLICY_SUBSET) &&
-+ (!cpus_empty(info->affinity_hint)))
-+ cpus_and(applied_mask, applied_mask, info->affinity_hint);
-+ }
-
- /*
- * only activate mappings for irqs that have moved
- */
-- if (!info->moved)
-+ if (!info->moved && (!valid_mask || check_affinity(info, applied_mask)))
- return;
-
- if (!info->assigned_obj)
- return;
-
--
- sprintf(buf, "/proc/irq/%i/smp_affinity", info->irq);
- file = fopen(buf, "w");
- if (!file)
- return;
-
-- if ((hint_policy == HINT_POLICY_EXACT) &&
-- (!cpus_empty(info->affinity_hint)))
-- applied_mask = info->affinity_hint;
-- else
-- applied_mask = info->assigned_obj->mask;
--
- cpumask_scnprintf(buf, PATH_MAX, applied_mask);
- fprintf(file, "%s", buf);
- fclose(file);
-diff --git a/autogen.sh b/autogen.sh
-index 5ad9f14..b792e8b 100755
---- a/autogen.sh
-+++ b/autogen.sh
-@@ -1,4 +1,5 @@
- #! /bin/sh
- set -x -e
-+mkdir -p m4
- # --no-recursive is available only in recent autoconf versions
- autoreconf -fv --install
-diff --git a/classify.c b/classify.c
-index 124dab0..05b3bfb 100644
---- a/classify.c
-+++ b/classify.c
-@@ -52,6 +52,8 @@ static short class_codes[MAX_CLASS] = {
- };
-
- static GList *interrupts_db;
-+static GList *new_irq_list;
-+static GList *banned_irqs;
-
- #define SYSDEV_DIR "/sys/bus/pci/devices"
-
-@@ -63,6 +65,30 @@ static gint compare_ints(gconstpointer a, gconstpointer b)
- return ai->irq - bi->irq;
- }
-
-+void add_banned_irq(int irq)
-+{
-+ struct irq_info find, *new;
-+ GList *entry;
-+
-+ find.irq = irq;
-+ entry = g_list_find_custom(banned_irqs, &find, compare_ints);
-+ if (entry)
-+ return;
-+
-+ new = calloc(sizeof(struct irq_info), 1);
-+ if (!new) {
-+ if (debug_mode)
-+ printf("No memory to ban irq %d\n", irq);
-+ return;
-+ }
-+
-+ new->irq = irq;
-+
-+ banned_irqs = g_list_append(banned_irqs, new);
-+ return;
-+}
-+
-+
- /*
- * Inserts an irq_info struct into the intterupts_db list
- * devpath points to the device directory in sysfs for the
-@@ -90,6 +116,13 @@ static struct irq_info *add_one_irq_to_db(const char *devpath, int irq)
- return NULL;
- }
-
-+ entry = g_list_find_custom(banned_irqs, &find, compare_ints);
-+ if (entry) {
-+ if (debug_mode)
-+ printf("SKIPPING BANNED IRQ %d\n", irq);
-+ return NULL;
-+ }
-+
- new = calloc(sizeof(struct irq_info), 1);
- if (!new)
- return NULL;
-@@ -175,6 +208,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
- */
-@@ -199,6 +269,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;
-@@ -221,6 +295,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;
-@@ -248,6 +327,8 @@ void rebuild_irq_db(void)
- {
- DIR *devdir = opendir(SYSDEV_DIR);
- struct dirent *entry;
-+ GList *gentry;
-+ struct irq_info *ninfo, *iinfo;
-
- free_irq_db();
-
-@@ -263,22 +344,46 @@ void rebuild_irq_db(void)
- build_one_dev_entry(entry->d_name);
-
- } while (entry != NULL);
-+
- closedir(devdir);
-+
-+ if (!new_irq_list)
-+ return;
-+ gentry = g_list_first(new_irq_list);
-+ while(gentry) {
-+ ninfo = gentry->data;
-+ iinfo = get_irq_info(ninfo->irq);
-+ new_irq_list = g_list_remove(gentry, ninfo);
-+ if (!iinfo) {
-+ if (debug_mode)
-+ printf("Adding untracked IRQ %d to database\n", ninfo->irq);
-+ interrupts_db = g_list_append(interrupts_db, ninfo);
-+ } else
-+ free(ninfo);
-+
-+ gentry = g_list_first(new_irq_list);
-+ }
-+ g_list_free(new_irq_list);
-+ new_irq_list = NULL;
-+
- }
-
--struct irq_info *add_misc_irq(int irq)
-+struct irq_info *add_new_irq(int irq)
- {
-- struct irq_info *new;
-+ struct irq_info *new, *nnew;
-
- new = calloc(sizeof(struct irq_info), 1);
-- if (!new)
-+ nnew = calloc(sizeof(struct irq_info), 1);
-+ if (!new || !nnew)
- return NULL;
-
- new->irq = irq;
- new->type = IRQ_TYPE_LEGACY;
- new->class = IRQ_OTHER;
- new->numa_node = get_numa_node(-1);
-+ memcpy(nnew, new, sizeof(struct irq_info));
- interrupts_db = g_list_append(interrupts_db, new);
-+ new_irq_list = g_list_append(new_irq_list, nnew);
- return new;
- }
-
-@@ -307,7 +412,7 @@ struct irq_info *get_irq_info(int irq)
- void migrate_irq(GList **from, GList **to, struct irq_info *info)
- {
- GList *entry;
-- struct irq_info find, *tmp;;
-+ struct irq_info find, *tmp;
-
- find.irq = info->irq;
- entry = g_list_find_custom(*from, &find, compare_ints);
-@@ -325,18 +430,9 @@ static gint sort_irqs(gconstpointer A, gconstpointer B)
- a = (struct irq_info*)A;
- b = (struct irq_info*)B;
-
-- if (a->class < b->class)
-- return 1;
-- if (a->class > b->class)
-- return -1;
-- if (a->load < b->load)
-- return 1;
-- if (a->load > b->load)
-- return -1;
-- if (a<b)
-+ if (a->class < b->class || a->load < b->load || a < b)
- return 1;
- return -1;
--
- }
-
- void sort_irq_list(GList **list)
-diff --git a/configure.ac b/configure.ac
-index eed55ba..1230d66 100644
---- a/configure.ac
-+++ b/configure.ac
-@@ -1,49 +1,12 @@
--dnl
--define([AC_INIT_NOTICE],
--[### Generated automatically using autoconf version] AC_ACVERSION [
--### Copyright 2009 Steve Grubb <sgrubb@redhat.com>
--###
--### Permission is hereby granted, free of charge, to any person obtaining a
--### copy of this software and associated documentation files (the "Software"),
--### to deal in the Software without restriction, including without limitation
--### the rights to use, copy, modify, merge, publish, distribute, sublicense,
--### and/or sell copies of the Software, and to permit persons to whom the
--### Software is furnished to do so, subject to the following conditions:
--###
--### The above copyright notice and this permission notice shall be included
--### in all copies or substantial portions of the Software.
--###
--### THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
--### IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
--### FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
--### THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
--### OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
--### ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
--### OTHER DEALINGS IN THE SOFTWARE.
--###
--### For usage, run `./configure --help'
--### For more detailed information on installation, read the file `INSTALL'.
--###
--### If configuration succeeds, status is in the file `config.status'.
--### A log of configuration tests is in `config.log'.
--])
--
--AC_REVISION($Revision: 1.3 $)dnl
- AC_INIT(irqbalance,1.0.3)
- AC_PREREQ(2.12)dnl
- AM_CONFIG_HEADER(config.h)
-
--echo Configuring irqbalance $VERSION
--
- AC_CONFIG_MACRO_DIR([m4])
--AC_CANONICAL_TARGET
--AM_INIT_AUTOMAKE
-+AM_INIT_AUTOMAKE([foreign])
- AM_PROG_LIBTOOL
- AC_SUBST(LIBTOOL_DEPS)
-
--AC_MSG_NOTICE()
--AC_MSG_NOTICE([Checking for programs])
--
- AC_PROG_CC
- AC_PROG_INSTALL
- AC_PROG_AWK
-@@ -55,9 +18,6 @@ AS_IF([test "$enable_numa" = "no"],[
- ac_cv_lib_numa_numa_available=no
- ])
-
--AC_MSG_NOTICE
--AC_MSG_NOTICE([echo Checking for header files])
--
- AC_HEADER_STDC
- AC_CHECK_HEADERS([numa.h])
-
-@@ -70,10 +30,57 @@ AC_C_CONST
- AC_C_INLINE
- AM_PROG_CC_C_O
-
--PKG_CHECK_MODULES([GLIB], [glib-2.0 >= 2.28])
--LIBCAP_NG_PATH
-+AC_ARG_WITH([glib2],
-+ [AS_HELP_STRING([--without-glib2],
-+ [Don't use system glib2 library. Use local implementation instead.])],
-+ [],
-+ [with_glib2=check])
-+
-+local_glib2=
-+AS_IF(
-+ [test "x$with_glib2" = xyes],
-+ [PKG_CHECK_MODULES([GLIB], [glib-2.0 >= 2.28])],
-+
-+ [test "x$with_glib2" = xno],
-+ [local_glib2="yes"],
-+
-+ [PKG_CHECK_MODULES([GLIB], [glib-2.0 >= 2.28], [], [local_glib2="yes"])]
-+)
-+
-+AS_IF(
-+ [test "x$local_glib2" = xyes],
-+ [
-+ GLIB_CFLAGS=-I./glib-local
-+ GLIB_LIBS=glib-local/libglib.a
-+ AC_SUBST(GLIB_CFLAGS)
-+ AC_SUBST(GLIB_LIBS)
-+ AC_MSG_WARN(Using locale implementation of GList functions)
-+ ]
-+)
-+
-+AM_CONDITIONAL([LOCAL_GLIB], [test "x$local_glib2" = "xyes"])
-+
-+AC_ARG_WITH([libcap-ng],
-+ AS_HELP_STRING([libcap-ng], [Add libcap-ng-support @<:@default=auto@:>@]))
-+
-+AS_IF(
-+ [test "x$libcap_ng" != "xno"],
-+ [
-+ PKG_CHECK_MODULES([LIBCAP_NG], [libcap-ng],
-+ [AC_DEFINE(HAVE_LIBCAP_NG,1,[libcap-ng support])],
-+ [
-+ AS_IF(
-+ [test "x$libcap_ng" = "xyes"],
-+ [
-+ AC_MSG_ERROR([libcap-ng not found])
-+ ]
-+ )
-+ ]
-+ )
-+ ]
-+)
-
--AC_OUTPUT(Makefile)
-+AC_OUTPUT(Makefile glib-local/Makefile)
-
- AC_MSG_NOTICE()
- AC_MSG_NOTICE([irqbalance Version: $VERSION])
-diff --git a/cputree.c b/cputree.c
-index af4fd3a..9568967 100644
---- a/cputree.c
-+++ b/cputree.c
-@@ -1,5 +1,6 @@
- /*
- * Copyright (C) 2006, Intel Corporation
-+ * Copyright (C) 2012, Neil Horman <nhorman@tuxdriver.com>
- *
- * This file is part of irqbalance
- *
-diff --git a/glib-local/Makefile.am b/glib-local/Makefile.am
-new file mode 100644
-index 0000000..336b56e
---- /dev/null
-+++ b/glib-local/Makefile.am
-@@ -0,0 +1,8 @@
-+## Process this file with automake to produce Makefile.in
-+noinst_LIBRARIES = libglib.a
-+
-+libglib_a_SOURCES = glist.c
-+
-+libglib_a_CFLAGS = @GLIB_CFLAGS@
-+
-+noinst_HEADERS = glib.h glist.h
-diff --git a/glib-local/glib.h b/glib-local/glib.h
-new file mode 100644
-index 0000000..5874892
---- /dev/null
-+++ b/glib-local/glib.h
-@@ -0,0 +1 @@
-+#include <glist.h>
-diff --git a/glib-local/glist.c b/glib-local/glist.c
-new file mode 100644
-index 0000000..6fa1761
---- /dev/null
-+++ b/glib-local/glist.c
-@@ -0,0 +1,381 @@
-+#include <stdlib.h>
-+
-+#include "glist.h"
-+
-+/**
-+ * g_list_free:
-+ * @list: a #GList
-+ *
-+ * Frees all of the memory used by a #GList.
-+ * The freed elements are returned to the slice allocator.
-+ *
-+ * <note><para>
-+ * If list elements contain dynamically-allocated memory,
-+ * you should either use g_list_free_full() or free them manually
-+ * first.
-+ * </para></note>
-+ */
-+void
-+g_list_free (GList *list)
-+{
-+ GList *l = list;
-+
-+ while(l) {
-+ GList *tmp = l->next;
-+ free(l);
-+ l = tmp;
-+ }
-+}
-+
-+/**
-+ * g_list_last:
-+ * @list: a #GList
-+ *
-+ * Gets the last element in a #GList.
-+ *
-+ * Returns: the last element in the #GList,
-+ * or %NULL if the #GList has no elements
-+ */
-+GList*
-+g_list_last (GList *list)
-+{
-+ if (list)
-+ {
-+ while (list->next)
-+ list = list->next;
-+ }
-+
-+ return list;
-+}
-+
-+/**
-+ * g_list_append:
-+ * @list: a pointer to a #GList
-+ * @data: the data for the new element
-+ *
-+ * Adds a new element on to the end of the list.
-+ *
-+ * <note><para>
-+ * The return value is the new start of the list, which
-+ * may have changed, so make sure you store the new value.
-+ * </para></note>
-+ *
-+ * <note><para>
-+ * Note that g_list_append() has to traverse the entire list
-+ * to find the end, which is inefficient when adding multiple
-+ * elements. A common idiom to avoid the inefficiency is to prepend
-+ * the elements and reverse the list when all elements have been added.
-+ * </para></note>
-+ *
-+ * |[
-+ * /&ast; Notice that these are initialized to the empty list. &ast;/
-+ * GList *list = NULL, *number_list = NULL;
-+ *
-+ * /&ast; This is a list of strings. &ast;/
-+ * list = g_list_append (list, "first");
-+ * list = g_list_append (list, "second");
-+ *
-+ * /&ast; This is a list of integers. &ast;/
-+ * number_list = g_list_append (number_list, GINT_TO_POINTER (27));
-+ * number_list = g_list_append (number_list, GINT_TO_POINTER (14));
-+ * ]|
-+ *
-+ * Returns: the new start of the #GList
-+ */
-+GList*
-+g_list_append (GList *list,
-+ gpointer data)
-+{
-+ GList *new_list;
-+ GList *last;
-+
-+ new_list = malloc(sizeof(*new_list));
-+ new_list->data = data;
-+ new_list->next = NULL;
-+
-+ if (list)
-+ {
-+ last = g_list_last (list);
-+ /* g_assert (last != NULL); */
-+ last->next = new_list;
-+ new_list->prev = last;
-+
-+ return list;
-+ }
-+ else
-+ {
-+ new_list->prev = NULL;
-+ return new_list;
-+ }
-+}
-+
-+static inline GList*
-+_g_list_remove_link (GList *list,
-+ GList *link)
-+{
-+ if (link)
-+ {
-+ if (link->prev)
-+ link->prev->next = link->next;
-+ if (link->next)
-+ link->next->prev = link->prev;
-+
-+ if (link == list)
-+ list = list->next;
-+
-+ link->next = NULL;
-+ link->prev = NULL;
-+ }
-+
-+ return list;
-+}
-+
-+/**
-+ * g_list_delete_link:
-+ * @list: a #GList
-+ * @link_: node to delete from @list
-+ *
-+ * Removes the node link_ from the list and frees it.
-+ * Compare this to g_list_remove_link() which removes the node
-+ * without freeing it.
-+ *
-+ * Returns: the new head of @list
-+ */
-+GList*
-+g_list_delete_link (GList *list,
-+ GList *link_)
-+{
-+ list = _g_list_remove_link (list, link_);
-+ free (link_);
-+
-+ return list;
-+}
-+
-+/**
-+ * g_list_first:
-+ * @list: a #GList
-+ *
-+ * Gets the first element in a #GList.
-+ *
-+ * Returns: the first element in the #GList,
-+ * or %NULL if the #GList has no elements
-+ */
-+GList*
-+g_list_first (GList *list)
-+{
-+ if (list)
-+ {
-+ while (list->prev)
-+ list = list->prev;
-+ }
-+
-+ return list;
-+}
-+
-+static GList *
-+g_list_sort_merge (GList *l1,
-+ GList *l2,
-+ GFunc compare_func,
-+ gpointer user_data)
-+{
-+ GList list, *l, *lprev;
-+ gint cmp;
-+
-+ l = &list;
-+ lprev = NULL;
-+
-+ while (l1 && l2)
-+ {
-+ cmp = ((GCompareDataFunc) compare_func) (l1->data, l2->data, user_data);
-+
-+ if (cmp <= 0)
-+ {
-+ l->next = l1;
-+ l1 = l1->next;
-+ }
-+ else
-+ {
-+ l->next = l2;
-+ l2 = l2->next;
-+ }
-+ l = l->next;
-+ l->prev = lprev;
-+ lprev = l;
-+ }
-+ l->next = l1 ? l1 : l2;
-+ l->next->prev = l;
-+
-+ return list.next;
-+}
-+
-+static GList*
-+g_list_sort_real (GList *list,
-+ GFunc compare_func,
-+ gpointer user_data)
-+{
-+ GList *l1, *l2;
-+
-+ if (!list)
-+ return NULL;
-+ if (!list->next)
-+ return list;
-+
-+ l1 = list;
-+ l2 = list->next;
-+
-+ while ((l2 = l2->next) != NULL)
-+ {
-+ if ((l2 = l2->next) == NULL)
-+ break;
-+ l1 = l1->next;
-+ }
-+ l2 = l1->next;
-+ l1->next = NULL;
-+
-+ return g_list_sort_merge (g_list_sort_real (list, compare_func, user_data),
-+ g_list_sort_real (l2, compare_func, user_data),
-+ compare_func,
-+ user_data);
-+}
-+
-+/**
-+ * g_list_sort:
-+ * @list: a #GList
-+ * @compare_func: the comparison function used to sort the #GList.
-+ * This function is passed the data from 2 elements of the #GList
-+ * and should return 0 if they are equal, a negative value if the
-+ * first element comes before the second, or a positive value if
-+ * the first element comes after the second.
-+ *
-+ * Sorts a #GList using the given comparison function.
-+ *
-+ * Returns: the start of the sorted #GList
-+ */
-+/**
-+ * GCompareFunc:
-+ * @a: a value.
-+ * @b: a value to compare with.
-+ * @Returns: negative value if @a &lt; @b; zero if @a = @b; positive
-+ * value if @a > @b.
-+ *
-+ * Specifies the type of a comparison function used to compare two
-+ * values. The function should return a negative integer if the first
-+ * value comes before the second, 0 if they are equal, or a positive
-+ * integer if the first value comes after the second.
-+ **/
-+GList *
-+g_list_sort (GList *list,
-+ GCompareFunc compare_func)
-+{
-+ return g_list_sort_real (list, (GFunc) compare_func, NULL);
-+
-+}
-+
-+/**
-+ * g_list_length:
-+ * @list: a #GList
-+ *
-+ * Gets the number of elements in a #GList.
-+ *
-+ * <note><para>
-+ * This function iterates over the whole list to
-+ * count its elements.
-+ * </para></note>
-+ *
-+ * Returns: the number of elements in the #GList
-+ */
-+guint
-+g_list_length (GList *list)
-+{
-+ guint length;
-+
-+ length = 0;
-+ while (list)
-+ {
-+ length++;
-+ list = list->next;
-+ }
-+
-+ return length;
-+}
-+
-+/**
-+ * g_list_foreach:
-+ * @list: a #GList
-+ * @func: the function to call with each element's data
-+ * @user_data: user data to pass to the function
-+ *
-+ * Calls a function for each element of a #GList.
-+ */
-+/**
-+ * GFunc:
-+ * @data: the element's data.
-+ * @user_data: user data passed to g_list_foreach() or
-+ * g_slist_foreach().
-+ *
-+ * Specifies the type of functions passed to g_list_foreach() and
-+ * g_slist_foreach().
-+ **/
-+void
-+g_list_foreach (GList *list,
-+ GFunc func,
-+ gpointer user_data)
-+{
-+ while (list)
-+ {
-+ GList *next = list->next;
-+ (*func) (list->data, user_data);
-+ list = next;
-+ }
-+}
-+
-+/**
-+ * g_list_free_full:
-+ * @list: a pointer to a #GList
-+ * @free_func: the function to be called to free each element's data
-+ *
-+ * Convenience method, which frees all the memory used by a #GList, and
-+ * calls the specified destroy function on every element's data.
-+ *
-+ * Since: 2.28
-+ */
-+void
-+g_list_free_full (GList *list,
-+ GDestroyNotify free_func)
-+{
-+ g_list_foreach (list, (GFunc) free_func, NULL);
-+ g_list_free (list);
-+}
-+
-+/**
-+ * g_list_find_custom:
-+ * @list: a #GList
-+ * @data: user data passed to the function
-+ * @func: the function to call for each element.
-+ * It should return 0 when the desired element is found
-+ *
-+ * Finds an element in a #GList, using a supplied function to
-+ * find the desired element. It iterates over the list, calling
-+ * the given function which should return 0 when the desired
-+ * element is found. The function takes two #gconstpointer arguments,
-+ * the #GList element's data as the first argument and the
-+ * given user data.
-+ *
-+ * Returns: the found #GList element, or %NULL if it is not found
-+ */
-+GList*
-+g_list_find_custom (GList *list,
-+ gconstpointer data,
-+ GCompareFunc func)
-+{
-+ g_return_val_if_fail (func != NULL, list);
-+
-+ while (list)
-+ {
-+ if (! func (list->data, data))
-+ return list;
-+ list = list->next;
-+ }
-+
-+ return NULL;
-+}
-diff --git a/glib-local/glist.h b/glib-local/glist.h
-new file mode 100644
-index 0000000..47f2cfe
---- /dev/null
-+++ b/glib-local/glist.h
-@@ -0,0 +1,56 @@
-+#ifndef __G_LIST_H__
-+#define __G_LIST_H__
-+
-+typedef int gint;
-+typedef unsigned int guint;
-+typedef void* gpointer;
-+typedef const void *gconstpointer;
-+typedef gint (*GCompareFunc) (gconstpointer a,
-+ gconstpointer b);
-+typedef gint (*GCompareDataFunc) (gconstpointer a,
-+ gconstpointer b,
-+ gpointer user_data);
-+typedef void (*GFunc) (gpointer data,
-+ gpointer user_data);
-+typedef void (*GDestroyNotify) (gpointer data);
-+
-+struct _GList;
-+typedef struct _GList GList;
-+
-+struct _GList
-+{
-+ gpointer data;
-+ GList *next;
-+ GList *prev;
-+};
-+
-+/* Doubly linked lists
-+ */
-+void g_list_free (GList *list);
-+GList* g_list_append (GList *list,
-+ gpointer data);
-+GList* g_list_delete_link (GList *list,
-+ GList *link_);
-+GList* g_list_first (GList *list);
-+GList* g_list_sort (GList *list,
-+ GCompareFunc compare_func);
-+guint g_list_length (GList *list);
-+void g_list_foreach (GList *list,
-+ GFunc func,
-+ gpointer user_data);
-+void g_list_free_full (GList *list,
-+ GDestroyNotify free_func);
-+GList* g_list_find_custom (GList *list,
-+ gconstpointer data,
-+ GCompareFunc func);
-+
-+#define g_list_previous(list) ((list) ? (((GList *)(list))->prev) : NULL)
-+#define g_list_next(list) ((list) ? (((GList *)(list))->next) : NULL)
-+
-+#define g_return_val_if_fail(expr,val) do { \
-+ if (expr) { } else \
-+ { \
-+ return (val); \
-+ } } while(0);
-+
-+#endif /* __G_LIST_H__ */
-diff --git a/irqbalance.1 b/irqbalance.1
-index 55fc15f..20105bc 100644
---- a/irqbalance.1
-+++ b/irqbalance.1
-@@ -39,7 +39,11 @@ Causes irqbalance to be run once, after which the daemon exits
- .TP
-
- .B --debug
--Causes irqbalance to run in the foreground and extra debug information to be printed
-+Causes irqbalance to print extra debug information. Implies --foreground
-+
-+.TP
-+.B --foreground
-+Causes irqbalance to run in the foreground (without --debug)
-
- .TP
- .B --hintpolicy=[exact | subset | ignore]
-@@ -62,6 +66,30 @@ average cpu softirq workload, and no cpus are more than 1 standard deviation
- above (and have more than 1 irq assigned to them), attempt to place 1 cpu in
- powersave mode. In powersave mode, a cpu will not have any irqs balanced to it,
- in an effort to prevent that cpu from waking up without need.
-+
-+.TP
-+.B --banirq=<irqnum>
-+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.
-+
-+.TP
-+.B --pid=<file>
-+Have irqbalance write its process id to the specified file. By default no
-+pidfile is written. The written pidfile is automatically unlinked when
-+irqbalance exits.
-+
- .SH "ENVIRONMENT VARIABLES"
- .TP
- .B IRQBALANCE_ONESHOT
-@@ -75,9 +103,10 @@ Same as --debug
- .B IRQBALANCE_BANNED_CPUS
- Provides a mask of cpus which irqbalance should ignore and never assign interrupts to
-
-+.SH "SIGNALS"
- .TP
--.B IRQBALANCE_BANNED_INTERRUPTS
--A list of space delimited IRQ numbers that irqbalance should not touch
-+.B SIGHUP
-+Forces a rescan of the available irqs and system topology
-
- .SH "Homepage"
- http://code.google.com/p/irqbalance
-diff --git a/irqbalance.c b/irqbalance.c
-index 99c5db7..fbe6ac6 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
- *
-@@ -27,6 +28,10 @@
- #include <syslog.h>
- #include <unistd.h>
- #include <signal.h>
-+#include <time.h>
-+#include <sys/types.h>
-+#include <sys/stat.h>
-+#include <fcntl.h>
- #ifdef HAVE_GETOPT_LONG
- #include <getopt.h>
- #endif
-@@ -39,12 +44,15 @@
- volatile int keep_going = 1;
- int one_shot_mode;
- int debug_mode;
-+int foreground_mode;
- int numa_avail;
--int need_cpu_rescan;
-+int need_rescan;
- 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 *pidfile = NULL;
-+char *banscript = NULL;
-
- void sleep_approx(int seconds)
- {
-@@ -64,32 +72,45 @@ void sleep_approx(int seconds)
- struct option lopts[] = {
- {"oneshot", 0, NULL, 'o'},
- {"debug", 0, NULL, 'd'},
-+ {"foreground", 0, NULL, 'f'},
- {"hintpolicy", 1, NULL, 'h'},
- {"powerthresh", 1, NULL, 'p'},
-+ {"banirq", 1 , NULL, 'i'},
-+ {"banscript", 1, NULL, 'b'},
-+ {"pid", 1, NULL, 's'},
- {0, 0, 0, 0}
- };
-
- static void usage(void)
- {
-- printf("irqbalance [--oneshot | -o] [--debug | -d] [--hintpolicy= | -h [exact|subset|ignore]]\n");
-- printf(" [--powerthresh= | -p <off> | <n>]\n");
-+ printf("irqbalance [--oneshot | -o] [--debug | -d] [--foreground | -f] [--hintpolicy= | -h [exact|subset|ignore]]\n");
-+ printf(" [--powerthresh= | -p <off> | <n>] [--banirq= | -i <n>]\n");
- }
-
- static void parse_command_line(int argc, char **argv)
- {
- int opt;
- int longind;
-+ unsigned long val;
-
- while ((opt = getopt_long(argc, argv,
-- "odh:p:",
-+ "odfh:i:p:s:",
- lopts, &longind)) != -1) {
-
- switch(opt) {
- case '?':
- usage();
- exit(1);
-+ break;
-+ case 'b':
-+ banscript = strdup(optarg);
-+ break;
- case 'd':
- debug_mode=1;
-+ foreground_mode=1;
-+ break;
-+ case 'f':
-+ foreground_mode=1;
- break;
- case 'h':
- if (!strncmp(optarg, "exact", strlen(optarg)))
-@@ -103,6 +124,14 @@ static void parse_command_line(int argc, char **argv)
- exit(1);
- }
- break;
-+ case 'i':
-+ val = strtoull(optarg, NULL, 10);
-+ if (val == ULONG_MAX) {
-+ usage();
-+ exit(1);
-+ }
-+ add_banned_irq((int)val);
-+ break;
- case 'p':
- if (!strncmp(optarg, "off", strlen(optarg)))
- power_thresh = ULONG_MAX;
-@@ -117,6 +146,9 @@ static void parse_command_line(int argc, char **argv)
- case 'o':
- one_shot_mode=1;
- break;
-+ case 's':
-+ pidfile = optarg;
-+ break;
- }
- }
- }
-@@ -172,18 +204,34 @@ static void handler(int signum)
- keep_going = 0;
- }
-
-+static void force_rescan(int signum)
-+{
-+ if (cycle_count)
-+ need_rescan = 1;
-+}
-+
- int main(int argc, char** argv)
- {
-- struct sigaction action;
-+ struct sigaction action, hupaction;
-
- #ifdef HAVE_GETOPT_LONG
- parse_command_line(argc, argv);
- #else
-- if (argc>1 && strstr(argv[1],"--debug"))
-+ if (argc>1 && strstr(argv[1],"--debug")) {
- debug_mode=1;
-+ foreground_mode=1;
-+ }
-+ if (argc>1 && strstr(argv[1],"--foreground"))
-+ foreground_mode=1;
- 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);
- }
-@@ -212,17 +260,35 @@ 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 = "Balaincing 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;
-
-- if (!debug_mode)
-+ if (!foreground_mode) {
-+ int pidfd = -1;
- if (daemon(0,0))
- exit(EXIT_FAILURE);
-+ /* Write pidfile */
-+ if (pidfile && (pidfd = open(pidfile,
-+ O_WRONLY | O_CREAT | O_EXCL | O_TRUNC,
-+ S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) >= 0) {
-+ char str[16];
-+ snprintf(str, sizeof(str), "%u\n", getpid());
-+ write(pidfd, str, strlen(str));
-+ close(pidfd);
-+ }
-+ }
-
-- openlog(argv[0], 0, LOG_DAEMON);
-
- #ifdef HAVE_LIBCAP_NG
- // Drop capabilities
-@@ -236,6 +302,11 @@ int main(int argc, char** argv)
- parse_proc_interrupts();
- parse_proc_stat();
-
-+ hupaction.sa_handler = force_rescan;
-+ sigemptyset(&hupaction.sa_mask);
-+ hupaction.sa_flags = 0;
-+ sigaction(SIGHUP, &hupaction, NULL);
-+
- while (keep_going) {
- sleep_approx(SLEEP_INTERVAL);
- if (debug_mode)
-@@ -247,8 +318,8 @@ int main(int argc, char** argv)
- parse_proc_stat();
-
- /* cope with cpu hotplug -- detected during /proc/interrupts parsing */
-- if (need_cpu_rescan) {
-- need_cpu_rescan = 0;
-+ if (need_rescan) {
-+ need_rescan = 0;
- /* if there's a hotplug event we better turn off power mode for a bit until things settle */
- power_mode = 0;
- if (debug_mode)
-@@ -282,5 +353,10 @@ int main(int argc, char** argv)
-
- }
- free_object_tree();
-+
-+ /* Remove pidfile */
-+ if (!foreground_mode && pidfile)
-+ unlink(pidfile);
-+
- return EXIT_SUCCESS;
- }
-diff --git a/irqbalance.h b/irqbalance.h
-index 4e85325..e46f31f 100644
---- a/irqbalance.h
-+++ b/irqbalance.h
-@@ -9,6 +9,7 @@
- #include <stdint.h>
- #include <glib.h>
- #include <syslog.h>
-+#include <limits.h>
-
- #include "types.h"
- #ifdef HAVE_NUMA_H
-@@ -40,7 +41,6 @@ void dump_tree(void);
-
- void activate_mappings(void);
- void account_for_nic_stats(void);
--void check_power_mode(void);
- void clear_cpu_tree(void);
- void pci_numa_scan(void);
-
-@@ -64,10 +64,11 @@ enum hp_e {
- extern int debug_mode;
- extern int one_shot_mode;
- extern int power_mode;
--extern int need_cpu_rescan;
-+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
-@@ -103,10 +104,11 @@ extern int get_cpu_count(void);
- */
- extern void rebuild_irq_db(void);
- extern void free_irq_db(void);
-+extern void add_banned_irq(int irq);
- extern void for_each_irq(GList *list, void (*cb)(struct irq_info *info, void *data), void *data);
- extern struct irq_info *get_irq_info(int irq);
- extern void migrate_irq(GList **from, GList **to, struct irq_info *info);
--extern struct irq_info *add_misc_irq(int irq);
-+extern struct irq_info *add_new_irq(int irq);
- #define irq_numa_node(irq) ((irq)->numa_node)
-
-
-diff --git a/irqlist.c b/irqlist.c
-index c29ee84..2523173 100644
---- a/irqlist.c
-+++ b/irqlist.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 @@ struct load_balance_info {
- unsigned int num_within;
- unsigned int num_over;
- unsigned int num_under;
-+ unsigned int num_powersave;
- struct topo_obj *powersave;
- };
-
-@@ -106,13 +108,16 @@ static void migrate_overloaded_irqs(struct topo_obj *obj, void *data)
- struct load_balance_info *info = data;
- int deviation;
-
-+ if (obj->powersave_mode)
-+ info->num_powersave++;
-+
- /*
- * Don't rebalance irqs on objects whos load is below the average
- */
- if (obj->load <= info->avg_load) {
- if ((obj->load + info->std_deviation) <= info->avg_load) {
- info->num_under++;
-- if (!info->powersave)
-+ if (power_thresh != ULONG_MAX && !info->powersave)
- if (!obj->powersave_mode)
- info->powersave = obj;
- } else
-@@ -172,13 +177,13 @@ void update_migration_status(void)
- {
- struct load_balance_info info;
- find_overloaded_objs(cpus, info);
-- if (cycle_count > 5) {
-+ if (power_thresh != ULONG_MAX && cycle_count > 5) {
- if (!info.num_over && (info.num_under >= power_thresh) && info.powersave) {
- syslog(LOG_INFO, "cpu %d entering powersave mode\n", info.powersave->number);
- info.powersave->powersave_mode = 1;
- if (g_list_length(info.powersave->interrupts) > 0)
- for_each_irq(info.powersave->interrupts, force_irq_migration, NULL);
-- } else if (info.num_over) {
-+ } else if ((info.num_over) && (info.num_powersave)) {
- syslog(LOG_INFO, "Load average increasing, re-enabling all cpus for irq balancing\n");
- for_each_object(cpus, clear_powersave_mode, NULL);
- }
-diff --git a/m4/cap-ng.m4 b/m4/cap-ng.m4
-deleted file mode 100644
-index 0024edc..0000000
---- a/m4/cap-ng.m4
-+++ /dev/null
-@@ -1,40 +0,0 @@
--# libcap-ng.m4 - Checks for the libcap-ng support
--# Copyright (c) 2009 Steve Grubb sgrubb@redhat.com
--#
--AC_DEFUN([LIBCAP_NG_PATH],
--[
-- AC_ARG_WITH(libcap-ng,
-- [ --with-libcap-ng=[auto/yes/no] Add Libcap-ng support [default=auto]],,
-- with_libcap_ng=auto)
--
-- # Check for Libcap-ng API
-- #
-- # libcap-ng detection
--
-- if test x$with_libcap_ng = xno ; then
-- have_libcap_ng=no;
-- else
-- # Start by checking for header file
-- AC_CHECK_HEADER(cap-ng.h, capng_headers=yes, capng_headers=no)
--
-- # See if we have libcap-ng library
-- AC_CHECK_LIB(cap-ng, capng_clear,
-- CAPNG_LDADD=-lcap-ng,)
--
-- # Check results are usable
-- if test x$with_libcap_ng = xyes -a x$CAPNG_LDADD = x ; then
-- AC_MSG_ERROR(libcap-ng support was requested and the library was not found)
-- fi
-- if test x$CAPNG_LDADD != x -a $capng_headers = no ; then
-- AC_MSG_ERROR(libcap-ng libraries found but headers are missing)
-- fi
-- fi
-- AC_SUBST(CAPNG_LDADD)
-- AC_MSG_CHECKING(whether to use libcap-ng)
-- if test x$CAPNG_LDADD != x ; then
-- AC_DEFINE(HAVE_LIBCAP_NG,1,[libcap-ng support])
-- AC_MSG_RESULT(yes)
-- else
-- AC_MSG_RESULT(no)
-- fi
--])
-diff --git a/misc/irqbalance.env b/misc/irqbalance.env
-new file mode 100644
-index 0000000..bd87e3d
---- /dev/null
-+++ b/misc/irqbalance.env
-@@ -0,0 +1,26 @@
-+# irqbalance is a daemon process that distributes interrupts across
-+# CPUS on SMP systems. The default is to rebalance once every 10
-+# seconds. This is the environment file that is specified to systemd via the
-+# EnvironmentFile key in the service unit file (or via whatever method the init
-+# system you're using has.
-+#
-+# ONESHOT=yes
-+# after starting, wait for a minute, then look at the interrupt
-+# load and balance it once; after balancing exit and do not change
-+# it again.
-+#IRQBALANCE_ONESHOT=
-+
-+#
-+# IRQBALANCE_BANNED_CPUS
-+# 64 bit bitmask which allows you to indicate which cpu's should
-+# be skipped when reblancing irqs. Cpu numbers which have their
-+# corresponding bits set to one in this mask will not have any
-+# irq's assigned to them on rebalance
-+#
-+#IRQBALANCE_BANNED_CPUS=
-+
-+#
-+# IRQBALANCE_ARGS
-+# append any args here to the irqbalance daemon as documented in the man page
-+#
-+#IRQBALANCE_ARGS=
-diff --git a/misc/irqbalance.service b/misc/irqbalance.service
-index f349616..3139a83 100644
---- a/misc/irqbalance.service
-+++ b/misc/irqbalance.service
-@@ -3,9 +3,8 @@ Description=irqbalance daemon
- After=syslog.target
-
- [Service]
--EnvironmentFile=/etc/sysconfig/irqbalance
--Type=forking
--ExecStart=/usr/sbin/irqbalance $ONESHOT
-+EnvironmentFile=/path/to/irqbalance.env
-+ExecStart=/usr/sbin/irqbalance --foreground $IRQBALANCE_ARGS
-
- [Install]
- WantedBy=multi-user.target
-diff --git a/numa.c b/numa.c
-index 710ed67..96703bd 100644
---- a/numa.c
-+++ b/numa.c
-@@ -1,5 +1,6 @@
- /*
- * Copyright (C) 2006, Intel Corporation
-+ * Copyright (C) 2012, Neil Horman <nhorman@tuxdriver.com>
- *
- * This file is part of irqbalance
- *
-@@ -106,11 +107,11 @@ void build_numa_node_list(void)
- static void free_numa_node(gpointer data)
- {
- struct topo_obj *obj = data;
-- if (data == &unspecified_node)
-- return;
--
- g_list_free(obj->children);
-- free(data);
-+ g_list_free(obj->interrupts);
-+
-+ if (data != &unspecified_node)
-+ free(data);
- }
-
- void free_numa_node_list(void)
-diff --git a/placement.c b/placement.c
-index 108ccc9..1172849 100644
---- a/placement.c
-+++ b/placement.c
-@@ -1,5 +1,6 @@
- /*
- * Copyright (C) 2006, Intel Corporation
-+ * Copyright (C) 2012, Neil Horman <nhoramn@tuxdriver.com>
- *
- * This file is part of irqbalance
- *
-@@ -48,7 +49,7 @@ static void find_best_object(struct topo_obj *d, void *data)
- /*
- * Don't consider the unspecified numa node here
- */
-- if ((d->obj_type == OBJ_TYPE_NODE) && (d->number == -1))
-+ if (numa_avail && (d->obj_type == OBJ_TYPE_NODE) && (d->number == -1))
- return;
-
- /*
-diff --git a/powermode.c b/powermode.c
-deleted file mode 100644
-index 82ba490..0000000
---- a/powermode.c
-+++ /dev/null
-@@ -1,34 +0,0 @@
--/*
-- * Copyright (C) 2006, Intel Corporation
-- *
-- * This file is part of irqbalance
-- *
-- * This program file is free software; you can redistribute it and/or modify it
-- * under the terms of the GNU General Public License as published by the
-- * Free Software Foundation; version 2 of the License.
-- *
-- * This program is distributed in the hope that it will be useful, but WITHOUT
-- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-- * for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program in a file named COPYING; if not, write to the
-- * Free Software Foundation, Inc.,
-- * 51 Franklin Street, Fifth Floor,
-- * Boston, MA 02110-1301 USA
-- */
--#include "config.h"
--#include <stdio.h>
--#include <stdlib.h>
--#include <unistd.h>
--#include <stdint.h>
--#include <string.h>
--
--#include "irqbalance.h"
--
--
--void check_power_mode(void)
--{
--}
--
-diff --git a/procinterrupts.c b/procinterrupts.c
-index 4d3b07b..431fffa 100644
---- a/procinterrupts.c
-+++ b/procinterrupts.c
-@@ -1,5 +1,6 @@
- /*
- * Copyright (C) 2006, Intel Corporation
-+ * Copyright (C) 2012, Neil Horman <nhorman@tuxdriver.com>
- *
- * This file is part of irqbalance
- *
-@@ -32,6 +33,8 @@
-
- #define LINESIZE 4096
-
-+extern cpumask_t banned_cpus;
-+
- static int proc_int_has_msi = 0;
- static int msi_found_in_sysfs = 0;
-
-@@ -80,8 +83,12 @@ void parse_proc_interrupts(void)
- c++;
- number = strtoul(line, NULL, 10);
- info = get_irq_info(number);
-- if (!info)
-- info = add_misc_irq(number);
-+ if (!info) {
-+ if (!cycle_count)
-+ continue;
-+ need_rescan = 1;
-+ info = add_new_irq(number);
-+ }
-
- count = 0;
- cpunr = 0;
-@@ -97,7 +104,7 @@ void parse_proc_interrupts(void)
- cpunr++;
- }
- if (cpunr != core_count)
-- need_cpu_rescan = 1;
-+ need_rescan = 1;
-
- info->last_irq_count = info->irq_count;
- info->irq_count = count;
-@@ -217,6 +224,9 @@ void parse_proc_stat(void)
-
- cpunr = strtoul(&line[3], NULL, 10);
-
-+ if (cpu_isset(cpunr, banned_cpus))
-+ continue;
-+
- rc = sscanf(line, "%*s %*d %*d %*d %*d %*d %d %d", &irq_load, &softirq_load);
- if (rc < 2)
- break;