Hello community,

here is the log from the commit of package irqbalance for openSUSE:Factory 
checked in at 2018-10-11 11:40:01
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/irqbalance (Old)
 and      /work/SRC/openSUSE:Factory/.irqbalance.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "irqbalance"

Thu Oct 11 11:40:01 2018 rev:50 rq:639963 version:1.4.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/irqbalance/irqbalance.changes    2017-11-30 
12:41:18.802814379 +0100
+++ /work/SRC/openSUSE:Factory/.irqbalance.new/irqbalance.changes       
2018-10-11 11:40:16.175182611 +0200
@@ -1,0 +2,42 @@
+Thu Oct  4 09:51:31 UTC 2018 - tr...@suse.de
+
+- Allow compilation with SLE-12 and before by:
+  * removing -std=C99 Latest compiler version does not complain
+  anymore, SLE12 SPx and before did.
+  * Fix a possible buffer overflow compiler warning
+A fix_buffer_overflow_compiler.patch
+
+-------------------------------------------------------------------
+Mon Oct  1 09:12:52 UTC 2018 - egotth...@suse.com
+
+- Removed aarch64-compile-fixes.patch because it is mainline now.
+
+- Update to version 1.4.0:
+  * Fixed an erroneous calculation of min_load that restricted candidates to a
+    subset of objects
+  * Fixed powerpc hotplug detection
+  * Cleaned up syslog target dependency
+  * Added some self test infrastructure (via make check)
+
+- Update to version 1.3.0
+  * New features in this release:
+      optimization of platform device irq detection
+      Added sample udev rules to trigger irq rescans on device add/remove
+      Made irqbalance ui an optional compile component
+      Added support for Intel CoD
+      Add -v | --version option to command line
+  * Bug fixes in this release:
+      Misc compiler warning fixes and spelling errors
+      Compilation error fix on aarch64
+      Compilation error fix when using clang in c99 mode
+      Unused variable cleanup
+      Lots of memory leak cleanup in irqbalance-ui
+      Prevent irqbalance from running in a container
+      Fix irq affinity assignment in some cases to wrong numa node
+      Fix oneshot mode
+      exclude legacy irq 255
+  * Deprecations:
+      without-glib2 is removed, we just need it enough that we can't dummy it 
up
+      anymore
+
+-------------------------------------------------------------------

Old:
----
  aarch64-compile-fixes.patch
  v1.2.0.tar.gz

New:
----
  _service
  _servicedata
  fix_buffer_overflow_compiler.patch
  v1.4.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ irqbalance.spec ++++++
--- /var/tmp/diff_new_pack.WQGlvA/_old  2018-10-11 11:40:19.447178445 +0200
+++ /var/tmp/diff_new_pack.WQGlvA/_new  2018-10-11 11:40:19.487178395 +0200
@@ -1,7 +1,7 @@
 #
 # spec file for package irqbalance
 #
-# Copyright (c) 2017 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany.
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -18,31 +18,31 @@
 
 #Compat macro for new _fillupdir macro introduced in Nov 2017
 %if ! %{defined _fillupdir}
-  %define _fillupdir /var/adm/fillup-templates
+  %define _fillupdir %{_localstatedir}/adm/fillup-templates
 %endif
-
 Name:           irqbalance
-Version:        1.2.0
+Version:        1.4.0
 Release:        0
 Summary:        Balance IRQs on SMP Machines
-License:        GPL-2.0+
+License:        GPL-2.0-or-later
 Group:          System/Daemons
 Url:            https://github.com/Irqbalance/irqbalance
 Source:         
https://github.com/Irqbalance/irqbalance/archive/v%{version}.tar.gz
 Source3:        sysconfig.irqbalance
-Patch2:         Set-fd-limit.patch
-Patch3:         install-man-pages.patch
-Patch4:         aarch64-compile-fixes.patch
+Patch1:         Set-fd-limit.patch
+Patch2:         install-man-pages.patch
+Patch3:         fix_buffer_overflow_compiler.patch
 BuildRequires:  libcap-ng-devel
 BuildRequires:  libtool
 BuildRequires:  ncurses-devel
+BuildRequires:  pkgconfig
 BuildRequires:  systemd-rpm-macros
 BuildRequires:  pkgconfig(glib-2.0)
 Requires(pre):  coreutils
 Requires(pre):  fillup
 ExcludeArch:    s390 s390x
 %{?systemd_requires}
-%ifnarch %arm
+%ifnarch %{arm}
 BuildRequires:  libnuma-devel
 %endif
 
@@ -52,14 +52,12 @@
 
 %prep
 %setup -q
-%patch2 -p1
-%patch3
-%patch4 -p1
+%autopatch -p1
 
 %build
 NOCONFIGURE=1 ./autogen.sh
 %configure
-make %{?_smp_mflags} LDFLAGS="-Wl,-z,relro,-z,now" CFLAGS="%{optflags} -fPIE 
-pie -std=c99 $(ncurses6-config --cflags)" LDFLAGS="$(ncurses6-config --libs)"
+make %{?_smp_mflags} LDFLAGS="-Wl,-z,relro,-z,now" CFLAGS="%{optflags} -fPIE 
-pie $(ncurses6-config --cflags)" LDFLAGS="$(ncurses6-config --libs)"
 cp %{SOURCE3} .
 
 %install
@@ -87,12 +85,11 @@
 %service_del_postun irqbalance.service
 
 %files
-%defattr(-,root,root,-)
 %{_sbindir}/irqbalance
 %{_sbindir}/irqbalance-ui
 %{_sbindir}/rcirqbalance
 %{_unitdir}/irqbalance.service
-%{_mandir}/man1/irqbalance.1.gz
+%{_mandir}/man1/irqbalance.1%{?ext_man}
 %{_fillupdir}/sysconfig.irqbalance
 
 %changelog

++++++ Set-fd-limit.patch ++++++
--- /var/tmp/diff_new_pack.WQGlvA/_old  2018-10-11 11:40:19.647178191 +0200
+++ /var/tmp/diff_new_pack.WQGlvA/_new  2018-10-11 11:40:19.647178191 +0200
@@ -1,7 +1,8 @@
-diff -ur irqbalance-1.0.7.orig/misc/irqbalance.service 
irqbalance-1.0.7/misc/irqbalance.service
---- irqbalance-1.0.7.orig/misc/irqbalance.service      2013-09-25 
13:32:23.000000000 +0200
-+++ irqbalance-1.0.7/misc/irqbalance.service   2016-10-14 15:30:11.873319592 
+0200
-@@ -5,6 +5,7 @@
+Index: irqbalance-1.4.0/misc/irqbalance.service
+===================================================================
+--- irqbalance-1.4.0.orig/misc/irqbalance.service
++++ irqbalance-1.4.0/misc/irqbalance.service
+@@ -5,6 +5,7 @@ ConditionVirtualization=!container
  [Service]
  EnvironmentFile=/path/to/irqbalance.env
  ExecStart=/usr/sbin/irqbalance --foreground $IRQBALANCE_ARGS

++++++ _service ++++++
<services>
  <service mode="disabled" name="tar_scm">
    <param name="url">https://github.com/Irqbalance/irqbalance.git</param>
    <param name="scm">git</param>
    <param name="changesgenerate">enable</param>
    <param name="filename">irqbalance</param>
    <param name="versionformat">1.4.0</param>
  </service>
</services>

++++++ _servicedata ++++++
<servicedata>
<service name="tar_scm">
                <param 
name="url">https://github.com/Irqbalance/irqbalance.git</param>
              <param 
name="changesrevision">5a1c7b89f7c9b928f6307ea50fc46fd7ce0cd061</param></service></servicedata>++++++
 fix_buffer_overflow_compiler.patch ++++++
From: Thomas Renninger <tr...@suse.de>

Fix compiler warning

Avoid:
In function ‘snprintf’,
    inlined from ‘sock_handle’ at irqbalance.c:457:12:
/usr/include/bits/stdio2.h:64:3: warning: call to __builtin___snprintf_chk will 
always overflow destination buffer [enabled by default]
   return __builtin___snprintf_chk (__s, __n, __USE_FORTIFY_LEVEL - 1,


Index: irqbalance-1.4.0/irqbalance.c
===================================================================
--- irqbalance-1.4.0.orig/irqbalance.c  2018-05-14 21:06:54.000000000 +0200
+++ irqbalance-1.4.0/irqbalance.c       2018-10-04 14:16:54.982803686 +0200
@@ -454,7 +454,7 @@ gboolean sock_handle(gint fd, GIOConditi
                if (!strncmp(buff, "setup", strlen("setup"))) {
                        char banned[512];
                        char *setup = calloc(strlen("SLEEP  ") + 11 +1, 1);
-                       snprintf(setup, 2048, "SLEEP %d ", sleep_interval);
+                       sprintf(setup, "SLEEP %d ", sleep_interval);
                        if(g_list_length(cl_banned_irqs) > 0) {
                                for_each_irq(cl_banned_irqs, get_irq_data, 
setup);
                        }
++++++ install-man-pages.patch ++++++
--- /var/tmp/diff_new_pack.WQGlvA/_old  2018-10-11 11:40:20.075177646 +0200
+++ /var/tmp/diff_new_pack.WQGlvA/_new  2018-10-11 11:40:20.087177631 +0200
@@ -1,9 +1,11 @@
---- Makefile.am
-+++ Makefile.am
-@@ -36,7 +36,7 @@
- irqbalance_ui_SOURCES = $(UI_DIR)/helpers.c $(UI_DIR)/irqbalance-ui.c \
-       $(UI_DIR)/ui.c
- irqbalance_ui_LDADD = $(GLIB_LIBS) $(CURSES_LIBS)
+Index: irqbalance-1.4.0/Makefile.am
+===================================================================
+--- irqbalance-1.4.0.orig/Makefile.am
++++ irqbalance-1.4.0/Makefile.am
+@@ -46,7 +46,7 @@ irqbalance_ui_SOURCES = $(UI_DIR)/helper
+ irqbalance_ui_LDADD = $(GLIB2_LIBS) $(CURSES_LIBS)
+ endif
+ 
 -dist_man_MANS = irqbalance.1
 +man_MANS = irqbalance.1
  

++++++ v1.2.0.tar.gz -> v1.4.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/irqbalance-1.2.0/.travis.yml 
new/irqbalance-1.4.0/.travis.yml
--- old/irqbalance-1.2.0/.travis.yml    1970-01-01 01:00:00.000000000 +0100
+++ new/irqbalance-1.4.0/.travis.yml    2018-05-14 21:06:54.000000000 +0200
@@ -0,0 +1,11 @@
+language: c
+dist: trusty
+
+compiler:
+  - clang
+  - gcc
+
+script: ./autogen.sh && ./configure && make && make check
+
+after_script: cat ./tests/runoneshot.sh.log
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/irqbalance-1.2.0/Makefile.am 
new/irqbalance-1.4.0/Makefile.am
--- old/irqbalance-1.2.0/Makefile.am    2017-01-09 14:41:02.000000000 +0100
+++ new/irqbalance-1.4.0/Makefile.am    2018-05-14 21:06:54.000000000 +0200
@@ -24,18 +24,28 @@
 ACLOCAL_AMFLAGS = -I m4
 EXTRA_DIST = COPYING autogen.sh misc/irqbalance.service misc/irqbalance.env
 
+SUBDIRS = tests
+
 UI_DIR = ui
-AM_CFLAGS = $(LIBCAP_NG_CFLAGS) $(GLIB_CFLAGS)
+AM_CFLAGS = $(LIBCAP_NG_CFLAGS) $(GLIB2_CFLAGS)
 AM_CPPFLAGS = -I${top_srcdir} -W -Wall -Wshadow -Wformat -Wundef -D_GNU_SOURCE
 noinst_HEADERS = bitmap.h constants.h cpumask.h irqbalance.h non-atomic.h \
        types.h $(UI_DIR)/helpers.h $(UI_DIR)/irqbalance-ui.h $(UI_DIR)/ui.h
-sbin_PROGRAMS = irqbalance irqbalance-ui
+sbin_PROGRAMS = irqbalance
+
+if IRQBALANCEUI
+sbin_PROGRAMS += irqbalance-ui
+endif
+
 irqbalance_SOURCES = activate.c bitmap.c classify.c cputree.c irqbalance.c \
        irqlist.c numa.c placement.c procinterrupts.c
-irqbalance_LDADD = $(LIBCAP_NG_LIBS) $(GLIB_LIBS)
+irqbalance_LDADD = $(LIBCAP_NG_LIBS) $(GLIB2_LIBS)
+if IRQBALANCEUI
 irqbalance_ui_SOURCES = $(UI_DIR)/helpers.c $(UI_DIR)/irqbalance-ui.c \
        $(UI_DIR)/ui.c
-irqbalance_ui_LDADD = $(GLIB_LIBS) $(CURSES_LIBS)
+irqbalance_ui_LDADD = $(GLIB2_LIBS) $(CURSES_LIBS)
+endif
+
 dist_man_MANS = irqbalance.1
 
 CONFIG_CLEAN_FILES = debug*.list config/*
@@ -43,6 +53,3 @@
        rm -rf autom4te*.cache 
        rm -f *.rej *.orig *~
 
-if LOCAL_GLIB
-SUBDIRS = glib-local
-endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/irqbalance-1.2.0/README.md 
new/irqbalance-1.4.0/README.md
--- old/irqbalance-1.2.0/README.md      2017-01-09 14:41:02.000000000 +0100
+++ new/irqbalance-1.4.0/README.md      2018-05-14 21:06:54.000000000 +0200
@@ -7,7 +7,7 @@
 spread as much as possible over an entire processor set, while minimizing cache
 miss rates for irq handlers.
 
-## Building and Installing
+## Building and Installing [![Build 
Status](https://travis-ci.org/Irqbalance/irqbalance.svg?branch=master)](https://travis-ci.org/Irqbalance/irqbalance)
 
 ```bash
 ./autogen.sh
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/irqbalance-1.2.0/classify.c 
new/irqbalance-1.4.0/classify.c
--- old/irqbalance-1.2.0/classify.c     2017-01-09 14:41:02.000000000 +0100
+++ new/irqbalance-1.4.0/classify.c     2018-05-14 21:06:54.000000000 +0200
@@ -655,8 +655,13 @@
 
        /*
         * no pci device has irq 0
+        * irq 255 is invalid on x86/x64 architectures
         */
+#if defined(__i386__) || defined(__x86_64__)
+       if (irqnum && irqnum != 255) {
+#else
        if (irqnum) {
+#endif
                new = get_irq_info(irqnum);
                if (new)
                        goto done;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/irqbalance-1.2.0/configure.ac 
new/irqbalance-1.4.0/configure.ac
--- old/irqbalance-1.2.0/configure.ac   2017-01-09 14:41:02.000000000 +0100
+++ new/irqbalance-1.4.0/configure.ac   2018-05-14 21:06:54.000000000 +0200
@@ -1,4 +1,4 @@
-AC_INIT(irqbalance,1.2.0)
+AC_INIT(irqbalance,1.3.0)
 AC_PREREQ(2.12)dnl
 AM_CONFIG_HEADER(config.h)
 
@@ -26,12 +26,27 @@
 AC_CHECK_LIB(numa, numa_available)
 AC_CHECK_LIB(m, floor)
 
-AC_CHECK_LIB(curses, mvprintw)
+PKG_CHECK_MODULES([GLIB2], [glib-2.0], [], [AC_MSG_ERROR([glib-2.0 is 
required])])
+
+PKG_CHECK_MODULES([NCURSESW], [ncursesw], [has_ncursesw=yes], 
[AC_CHECK_LIB(curses, mvprintw)])
+AS_IF([test "x$has_ncursesw" = "xyes"], [
+  AC_SUBST([NCURSESW_CFLAGS])
+  AC_SUBST([NCURSESW_LIBS])
+  LIBS="$LIBS $NCURSESW_LIBS"
+  AC_SUBST([LIBS])
+])
 
 AC_C_CONST
 AC_C_INLINE
 AM_PROG_CC_C_O
 
+AC_ARG_WITH([irqbalance-ui],
+       [AC_HELP_STRING([--without-irqbalance-ui],
+                       [Dont build the irqbalance ui component])],
+                       [with_irqbalanceui=false], [with_irqbalanceui=true])
+
+AM_CONDITIONAL([IRQBALANCEUI], [test x$with_irqbalanceui = xtrue])
+
 AC_ARG_WITH([systemd],
   [ AS_HELP_STRING([--with-systemd],[Add systemd-lib support])]
 )
@@ -46,36 +61,6 @@
     AC_CHECK_LIB([systemd], [sd_journal_print])
 ])
 
-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@:>@]))
 
@@ -96,7 +81,7 @@
   ]
 )
 
-AC_OUTPUT(Makefile glib-local/Makefile)
+AC_OUTPUT(Makefile tests/Makefile)
 
 AC_MSG_NOTICE()
 AC_MSG_NOTICE([irqbalance Version:     $VERSION])
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/irqbalance-1.2.0/cputree.c 
new/irqbalance-1.4.0/cputree.c
--- old/irqbalance-1.2.0/cputree.c      2017-01-09 14:41:02.000000000 +0100
+++ new/irqbalance-1.4.0/cputree.c      2018-05-14 21:06:54.000000000 +0200
@@ -121,8 +121,32 @@
        log(TO_CONSOLE, LOG_INFO, "Banned CPUs: %s\n", buffer);
 }
 
-static struct topo_obj* add_cache_domain_to_package(struct topo_obj *cache, 
-                                                   int packageid, cpumask_t 
package_mask)
+static void add_numa_node_to_topo_obj(struct topo_obj *obj, int nodeid)
+{
+       GList *entry;
+       struct topo_obj *node;
+       struct topo_obj *cand_node;
+
+       node = get_numa_node(nodeid);
+       if (!node || node->number == -1)
+               return;
+
+       entry = g_list_first(obj->numa_nodes);
+       while (entry) {
+               cand_node = entry->data;
+               if (cand_node == node)
+                       break;
+               entry = g_list_next(entry);
+       }
+
+       if (!entry)
+               obj->numa_nodes = g_list_append(obj->numa_nodes, node);
+}
+
+static struct topo_obj* add_cache_domain_to_package(struct topo_obj *cache,
+                                                   int packageid,
+                                                   cpumask_t package_mask,
+                                                   int nodeid)
 {
        GList *entry;
        struct topo_obj *package;
@@ -165,10 +189,14 @@
                cache->parent = package;
        }
 
+       if (nodeid > -1)
+               add_numa_node_to_topo_obj(package, nodeid);
+
        return package;
 }
 static struct topo_obj* add_cpu_to_cache_domain(struct topo_obj *cpu,
-                                                   cpumask_t cache_mask)
+                                                   cpumask_t cache_mask,
+                                                   int nodeid)
 {
        GList *entry;
        struct topo_obj *cache;
@@ -208,6 +236,9 @@
                cpu->parent = (struct topo_obj *)cache;
        }
 
+       if (nodeid > -1)
+               add_numa_node_to_topo_obj(cache, nodeid);
+
        return cache;
 }
  
@@ -218,7 +249,6 @@
        char new_path[PATH_MAX];
        cpumask_t cache_mask, package_mask;
        struct topo_obj *cache;
-       struct topo_obj *package;
        DIR *dir;
        struct dirent *entry;
        int nodeid;
@@ -324,6 +354,8 @@
 
        nodeid=-1;
        if (numa_avail) {
+               struct topo_obj *node;
+
                dir = opendir(path);
                do {
                        entry = readdir(dir);
@@ -335,6 +367,14 @@
                        }
                } while (entry);
                closedir(dir);
+
+               /*
+                * In case of multiple NUMA nodes within a CPU package,
+                * we override package_mask with node mask.
+                */
+               node = get_numa_node(nodeid);
+               if (node && (cpus_weight(package_mask) > 
cpus_weight(node->mask)))
+                       cpus_and(package_mask, package_mask, node->mask);
        }
 
        /*
@@ -344,9 +384,9 @@
        cpus_and(cache_mask, cache_mask, unbanned_cpus);
        cpus_and(package_mask, package_mask, unbanned_cpus);
 
-       cache = add_cpu_to_cache_domain(cpu, cache_mask);
-       package = add_cache_domain_to_package(cache, packageid, package_mask);
-       add_package_to_node(package, nodeid);
+       cache = add_cpu_to_cache_domain(cpu, cache_mask, nodeid);
+       add_cache_domain_to_package(cache, packageid, package_mask,
+           nodeid);
 
        cpu->obj_type_list = &cpus;
        cpus = g_list_append(cpus, cpu);
@@ -368,12 +408,18 @@
        free(indent);
 }
 
+static void dump_numa_node_num(struct topo_obj *p, void *data 
__attribute__((unused)))
+{
+       log(TO_CONSOLE, LOG_INFO, "%d ", p->number);
+}
+
 static void dump_balance_obj(struct topo_obj *d, void *data 
__attribute__((unused)))
 {
        struct topo_obj *c = (struct topo_obj *)d;
-       log(TO_CONSOLE, LOG_INFO, "%s%s%s%sCPU number %i  numa_node is %d (load 
%lu)\n",
-           log_indent, log_indent, log_indent, log_indent,
-           c->number, cpu_numa_node(c)->number , (unsigned long)c->load);
+       log(TO_CONSOLE, LOG_INFO, "%s%s%s%sCPU number %i  numa_node is ",
+           log_indent, log_indent, log_indent, log_indent, c->number);
+       for_each_object(cpu_numa_node(c), dump_numa_node_num, NULL);
+       log(TO_CONSOLE, LOG_INFO, "(load %lu)\n", (unsigned long)c->load);
        if (c->interrupts)
                for_each_irq(c->interrupts, dump_irq, (void *)18);
 }
@@ -382,9 +428,11 @@
 {
        char *buffer = data;
        cpumask_scnprintf(buffer, 4095, d->mask);
-       log(TO_CONSOLE, LOG_INFO, "%s%sCache domain %i:  numa_node is %d cpu 
mask is %s  (load %lu) \n",
-           log_indent, log_indent,
-           d->number, cache_domain_numa_node(d)->number, buffer, (unsigned 
long)d->load);
+       log(TO_CONSOLE, LOG_INFO, "%s%sCache domain %i:  numa_node is ",
+           log_indent, log_indent, d->number);
+       for_each_object(d->numa_nodes, dump_numa_node_num, NULL);
+       log(TO_CONSOLE, LOG_INFO, "cpu mask is %s  (load %lu) \n", buffer,
+           (unsigned long)d->load);
        if (d->children)
                for_each_object(d->children, dump_balance_obj, NULL);
        if (g_list_length(d->interrupts) > 0)
@@ -395,8 +443,10 @@
 {
        char *buffer = data;
        cpumask_scnprintf(buffer, 4096, d->mask);
-       log(TO_CONSOLE, LOG_INFO, "Package %i:  numa_node is %d cpu mask is %s 
(load %lu)\n",
-           d->number, package_numa_node(d)->number, buffer, (unsigned 
long)d->load);
+       log(TO_CONSOLE, LOG_INFO, "Package %i:  numa_node ", d->number);
+       for_each_object(d->numa_nodes, dump_numa_node_num, NULL);
+       log(TO_CONSOLE, LOG_INFO, "cpu mask is %s (load %lu)\n",
+           buffer, (unsigned long)d->load);
        if (d->children)
                for_each_object(d->children, dump_cache_domain, buffer);
        if (g_list_length(d->interrupts) > 0)
@@ -448,9 +498,9 @@
                char pad;
                entry = readdir(dir);
                /*
-                * We only want to count real cpus, not cpufreq and
-                * cpuidle
-                */
+                * We only want to count real cpus, not cpufreq and
+                * cpuidle
+                */
                if (entry &&
                    sscanf(entry->d_name, "cpu%d%c", &num, &pad) == 1 &&
                    !strchr(entry->d_name, ' ')) {
@@ -459,7 +509,8 @@
                        do_one_cpu(new_path);
                }
        } while (entry);
-       closedir(dir);  
+       closedir(dir);
+       for_each_object(packages, connect_cpu_mem_topo, NULL);
 
        if (debug_mode)
                dump_tree();
@@ -483,6 +534,7 @@
                package = item->data;
                g_list_free(package->children);
                g_list_free(package->interrupts);
+               g_list_free(package->numa_nodes);
                free(package);
                packages = g_list_delete_link(packages, item);
        }
@@ -493,6 +545,7 @@
                cache_domain = item->data;
                g_list_free(cache_domain->children);
                g_list_free(cache_domain->interrupts);
+               g_list_free(cache_domain->numa_nodes);
                free(cache_domain);
                cache_domains = g_list_delete_link(cache_domains, item);
        }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/irqbalance-1.2.0/glib-local/Makefile.am 
new/irqbalance-1.4.0/glib-local/Makefile.am
--- old/irqbalance-1.2.0/glib-local/Makefile.am 2017-01-09 14:41:02.000000000 
+0100
+++ new/irqbalance-1.4.0/glib-local/Makefile.am 1970-01-01 01:00:00.000000000 
+0100
@@ -1,8 +0,0 @@
-## 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 -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/irqbalance-1.2.0/glib-local/glib.h 
new/irqbalance-1.4.0/glib-local/glib.h
--- old/irqbalance-1.2.0/glib-local/glib.h      2017-01-09 14:41:02.000000000 
+0100
+++ new/irqbalance-1.4.0/glib-local/glib.h      1970-01-01 01:00:00.000000000 
+0100
@@ -1 +0,0 @@
-#include <glist.h>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/irqbalance-1.2.0/glib-local/glist.c 
new/irqbalance-1.4.0/glib-local/glist.c
--- old/irqbalance-1.2.0/glib-local/glist.c     2017-01-09 14:41:02.000000000 
+0100
+++ new/irqbalance-1.4.0/glib-local/glist.c     1970-01-01 01:00:00.000000000 
+0100
@@ -1,415 +0,0 @@
-#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;
-}
-
-/**
- * g_list_remove:
- * @list: a #GList
- * @data: the data of the element to remove
- *
- * Removes an element from a #GList.
- * If two elements contain the same data, only the first is removed.
- * If none of the elements contain the data, the #GList is unchanged.
- *
- * Returns: the new start of the #GList
- */
-GList*
-g_list_remove (GList         *list,
-               gconstpointer  data)
-{
-  GList *tmp;
- 
-  tmp = list;
-  while (tmp)
-    {
-      if (tmp->data != data)
-        tmp = tmp->next;
-      else
-        {
-          list = _g_list_remove_link(list, tmp);
-          g_list_free(tmp);
-
-          break;
-        }
-    }
-  return list;
-}
-
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/irqbalance-1.2.0/glib-local/glist.h 
new/irqbalance-1.4.0/glib-local/glist.h
--- old/irqbalance-1.2.0/glib-local/glist.h     2017-01-09 14:41:02.000000000 
+0100
+++ new/irqbalance-1.4.0/glib-local/glist.h     1970-01-01 01:00:00.000000000 
+0100
@@ -1,58 +0,0 @@
-#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);
-GList*   g_list_remove                  (GList            *list,
-                                         gconstpointer     data);
-
-#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 -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/irqbalance-1.2.0/irqbalance.c 
new/irqbalance-1.4.0/irqbalance.c
--- old/irqbalance-1.2.0/irqbalance.c   2017-01-09 14:41:02.000000000 +0100
+++ new/irqbalance-1.4.0/irqbalance.c   2018-05-14 21:06:54.000000000 +0200
@@ -94,6 +94,7 @@
        {"journal", 0, NULL, 'j'},
        {"banmod", 1 , NULL, 'm'},
        {"interval", 1 , NULL, 't'},
+       {"version", 0, NULL, 'V'},
        {0, 0, 0, 0}
 };
 
@@ -104,6 +105,11 @@
        log(TO_CONSOLE, LOG_INFO, "     [--pid= | -s <file>] [--deepestcache= | 
-c <n>] [--interval= | -t <n>]\n");
 }
 
+static void version(void)
+{
+       log(TO_CONSOLE, LOG_INFO, "irqbalance version " VERSION "\n");
+}
+
 static void parse_command_line(int argc, char **argv)
 {
        int opt;
@@ -111,7 +117,7 @@
        unsigned long val;
 
        while ((opt = getopt_long(argc, argv,
-               "odfji:p:s:c:b:l:m:t:",
+               "odfji:p:s:c:b:l:m:t:V",
                lopts, &longind)) != -1) {
 
                switch(opt) {
@@ -119,6 +125,10 @@
                                usage();
                                exit(1);
                                break;
+                       case 'V':
+                               version();
+                               exit(1);
+                               break;
                        case 'b':
 #ifndef INCLUDE_BANSCRIPT
                                /*
@@ -193,9 +203,14 @@
 #endif
 
 /*
- * This builds our object tree.  The Heirarchy is pretty straightforward
+ * This builds our object tree.  The Heirarchy is typically pretty
+ * straightforward.
  * At the top are numa_nodes
- * All CPU packages belong to a single numa_node
+ * CPU packages belong to a single numa_node, unless the cache domains are in
+ * separate nodes.  In that case, the cache domain's parent is the package, but
+ * the numa nodes point to the cache domains instead of the package as their
+ * children.  This allows us to maintain the CPU hierarchy while adjusting for
+ * alternate memory topologies that are present on recent processor.
  * All Cache domains belong to a CPU package
  * All CPU cores belong to a cache domain
  *
@@ -255,7 +270,6 @@
        log(TO_CONSOLE, LOG_INFO, 
"\n\n\n-----------------------------------------------------------------------------\n");
        clear_work_stats();
        parse_proc_interrupts();
-       parse_proc_stat();
 
 
        /* cope with cpu hotplug -- detected during /proc/interrupts parsing */
@@ -273,8 +287,9 @@
                sleep_approx(sleep_interval);
                clear_work_stats();
                parse_proc_interrupts();
-               parse_proc_stat();
-       } 
+       }
+
+       parse_proc_stat();
 
        if (cycle_count)        
                update_migration_status();
@@ -294,29 +309,57 @@
                return FALSE;
        }
 
-       if (keep_going)
+       if (keep_going) {
                return TRUE;
-       else
+       } else {
+               g_main_loop_quit(main_loop);
                return FALSE;
+       }
 }
 
 void get_irq_data(struct irq_info *irq, void *data)
 {
-       sprintf(data + strlen(data),
+       char **irqdata = (char **)data;
+       if (!*irqdata)
+               *irqdata = calloc(24 + 1 + 11 + 20 + 20 + 11, 1);
+       else
+               *irqdata = realloc(*irqdata, strlen(*irqdata) + 24 + 1 + 11 + 
20 + 20 + 11);
+
+       sprintf(*irqdata + strlen(*irqdata),
                        "IRQ %d LOAD %lu DIFF %lu CLASS %d ", irq->irq, 
irq->load,
                        (irq->irq_count - irq->last_irq_count), irq->class);
 }
 
 void get_object_stat(struct topo_obj *object, void *data)
 {
-       char irq_data[1024] = "\0";
+       char **stats = (char **)data;   
+       char *irq_data = NULL;
+       size_t irqdlen;
 
        if (g_list_length(object->interrupts) > 0) {
-               for_each_irq(object->interrupts, get_irq_data, irq_data);
+               for_each_irq(object->interrupts, get_irq_data, &irq_data);
+       }
+
+       irqdlen = irq_data ? strlen(irq_data) : 0;
+       /*
+        * Note, the size in both conditional branches below is made up as 
follows:
+        * strlen(irq_data) - self explanitory
+        * 31 - The size of "TYPE  NUMBER  LOAD  SAVE_MODE  "
+        * 11 - The maximal size of a %d printout
+        * 20 - The maximal size of a %lu printout
+        * 1 - The trailing string terminator
+        * This should be adjusted if the string in the sprintf is changed
+        */
+       if (!*stats) {
+               *stats = calloc(irqdlen + 31 + 11 + 20 + 11 + 1, 1);
+       } else {
+               *stats = realloc(*stats, strlen(*stats) + irqdlen + 31 + 11 + 
20 + 11 + 1);
        }
-       sprintf(data + strlen(data), "TYPE %d NUMBER %d LOAD %lu SAVE_MODE %d 
%s",
+
+       sprintf(*stats + strlen(*stats), "TYPE %d NUMBER %d LOAD %lu SAVE_MODE 
%d %s",
                        object->obj_type, object->number, object->load,
-                       object->powersave_mode, irq_data);
+                       object->powersave_mode, irq_data ? irq_data : "");
+       free(irq_data);
        if (object->obj_type != OBJ_TYPE_CPU) {
                for_each_object(object->children, get_object_stat, data);
        }
@@ -330,7 +373,9 @@
        int valid_user = 0;
 
        struct iovec iov = { buff, 500 };
-       struct msghdr msg = { NULL, 0, &iov, 1, NULL, 0, 0 };
+       struct msghdr msg = { 0 };
+       msg.msg_iov = &iov;
+       msg.msg_iovlen = 1;
        msg.msg_control = malloc(CMSG_SPACE(sizeof(struct ucred)));
        msg.msg_controllen = CMSG_SPACE(sizeof(struct ucred));
 
@@ -360,9 +405,10 @@
                }
 
                if (!strncmp(buff, "stats", strlen("stats"))) {
-                       char stats[2048] = "\0";
-                       for_each_object(numa_nodes, get_object_stat, stats);
+                       char *stats = NULL;
+                       for_each_object(numa_nodes, get_object_stat, &stats);
                        send(sock, stats, strlen(stats), 0);
+                       free(stats);
                }
                if (!strncmp(buff, "settings ", strlen("settings "))) {
                        if (!(strncmp(buff + strlen("settings "), "sleep ",
@@ -406,14 +452,15 @@
                        }
                }
                if (!strncmp(buff, "setup", strlen("setup"))) {
-                       char setup[2048] = "\0";
+                       char banned[512];
+                       char *setup = calloc(strlen("SLEEP  ") + 11 +1, 1);
                        snprintf(setup, 2048, "SLEEP %d ", sleep_interval);
                        if(g_list_length(cl_banned_irqs) > 0) {
                                for_each_irq(cl_banned_irqs, get_irq_data, 
setup);
                        }
-                       char banned[512];
                        cpumask_scnprintf(banned, 512, banned_cpus);
-                       snprintf(setup + strlen(setup), 2048 - strlen(setup),
+                       setup = realloc(setup, strlen(setup) + strlen(banned) + 
7 + 1);
+                       snprintf(setup + strlen(setup), strlen(banned) + 7 + 1,
                                        "BANNED %s", banned);
                        send(sock, setup, strlen(setup), 0);
                }
@@ -583,7 +630,7 @@
        g_main_loop_run(main_loop);
 
        g_main_loop_quit(main_loop);
-       
+
        free_object_tree();
        free_cl_opts();
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/irqbalance-1.2.0/irqbalance.h 
new/irqbalance-1.4.0/irqbalance.h
--- old/irqbalance-1.2.0/irqbalance.h   2017-01-09 14:41:02.000000000 +0100
+++ new/irqbalance-1.4.0/irqbalance.h   2018-05-14 21:06:54.000000000 +0200
@@ -84,26 +84,13 @@
 extern void build_numa_node_list(void);
 extern void free_numa_node_list(void);
 extern void dump_numa_node_info(struct topo_obj *node, void *data);
-extern void add_package_to_node(struct topo_obj *p, int nodeid);
+extern void connect_cpu_mem_topo(struct topo_obj *p, void *data);
 extern struct topo_obj *get_numa_node(int nodeid);
 
 /*
- * Package functions
- */
-#define package_numa_node(p) ((p)->parent)
-
-/*
- * cache_domain functions
- */
-#define cache_domain_package(c) ((c)->parent)
-#define cache_domain_numa_node(c) 
(package_numa_node(cache_domain_package((c))))
-
-/*
  * cpu core functions
  */
-#define cpu_cache_domain(cpu) ((cpu)->parent)
-#define cpu_package(cpu) (cache_domain_package(cpu_cache_domain((cpu))))
-#define cpu_numa_node(cpu) 
(package_numa_node(cache_domain_package(cpu_cache_domain((cpu)))))
+#define cpu_numa_node(cpu) ((cpu)->parent->numa_nodes)
 extern struct topo_obj *find_cpu_core(int cpunr);
 extern int get_cpu_count(void);
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/irqbalance-1.2.0/irqlist.c 
new/irqbalance-1.4.0/irqlist.c
--- old/irqbalance-1.2.0/irqlist.c      2017-01-09 14:41:02.000000000 +0100
+++ new/irqbalance-1.4.0/irqlist.c      2018-05-14 21:06:54.000000000 +0200
@@ -55,7 +55,7 @@
 {
        struct load_balance_info *info = data;
 
-       if (info->min_load == 0 || obj->load < info->min_load)
+       if (info->load_sources == 0 || obj->load < info->min_load)
                info->min_load = obj->load;
        info->total_load += obj->load;
        info->load_sources += 1;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/irqbalance-1.2.0/misc/90-irqbalance.rules 
new/irqbalance-1.4.0/misc/90-irqbalance.rules
--- old/irqbalance-1.2.0/misc/90-irqbalance.rules       1970-01-01 
01:00:00.000000000 +0100
+++ new/irqbalance-1.4.0/misc/90-irqbalance.rules       2018-05-14 
21:06:54.000000000 +0200
@@ -0,0 +1,5 @@
+# Udev rules for irqbalance.  On every device add or remove, we want to rescan
+# our irq list to make sure it hasn't changed
+#
+
+ACTION=="add|remove", RUN+="/usr/bin/killall -SIGHUP irqbalance"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/irqbalance-1.2.0/misc/irqbalance.service 
new/irqbalance-1.4.0/misc/irqbalance.service
--- old/irqbalance-1.2.0/misc/irqbalance.service        2017-01-09 
14:41:02.000000000 +0100
+++ new/irqbalance-1.4.0/misc/irqbalance.service        2018-05-14 
21:06:54.000000000 +0200
@@ -1,6 +1,6 @@
 [Unit]
 Description=irqbalance daemon
-After=syslog.target
+ConditionVirtualization=!container
 
 [Service]
 EnvironmentFile=/path/to/irqbalance.env
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/irqbalance-1.2.0/numa.c new/irqbalance-1.4.0/numa.c
--- old/irqbalance-1.2.0/numa.c 2017-01-09 14:41:02.000000000 +0100
+++ new/irqbalance-1.4.0/numa.c 2018-05-14 21:06:54.000000000 +0200
@@ -146,22 +146,38 @@
        return (ai->number == bi->number) ? 0 : 1;
 }
 
-void add_package_to_node(struct topo_obj *p, int nodeid)
+void connect_cpu_mem_topo(struct topo_obj *p, void *data 
__attribute__((unused)))
 {
+       GList *entry;
        struct topo_obj *node;
+       struct topo_obj *lchild;
+       int len;
 
-       node = get_numa_node(nodeid);
+       len = g_list_length(p->numa_nodes);
 
-       if (!node) {
-               log(TO_CONSOLE, LOG_INFO, "Could not find numa node for node id 
%d\n", nodeid);
+       if (len == 0) {
+               return;
+       } else if (len > 1) {
+               for_each_object(p->children, connect_cpu_mem_topo, NULL);
                return;
        }
 
+       entry = g_list_first(p->numa_nodes);
+       node = entry->data;
 
-       if (!p->parent) {
-               node->children = g_list_append(node->children, p);
+       if (p->obj_type == OBJ_TYPE_PACKAGE && !p->parent)
                p->parent = node;
+
+       entry = g_list_first(node->children);
+       while (entry) {
+               lchild = entry->data;
+               if (lchild == p)
+                       break;
+               entry = g_list_next(entry);
        }
+
+       if (!entry)
+               node->children = g_list_append(node->children, p);
 }
 
 void dump_numa_node_info(struct topo_obj *d, void *unused 
__attribute__((unused)))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/irqbalance-1.2.0/procinterrupts.c 
new/irqbalance-1.4.0/procinterrupts.c
--- old/irqbalance-1.2.0/procinterrupts.c       2017-01-09 14:41:02.000000000 
+0100
+++ new/irqbalance-1.4.0/procinterrupts.c       2018-05-14 21:06:54.000000000 
+0200
@@ -57,7 +57,17 @@
        DIR *dirfd;
        char path[512];
        struct dirent *ent;
-       int rc = -ENOENT;
+       int rc = -ENOENT, i;
+       static struct pdev_irq_info {
+               char *d_name;
+               int type;
+               int class;
+       } pdev_irq_info[] = {
+               {"ata", IRQ_TYPE_LEGACY, IRQ_SCSI},
+               {"net", IRQ_TYPE_LEGACY, IRQ_ETH},
+               {"usb", IRQ_TYPE_LEGACY, IRQ_OTHER},
+               {NULL},
+       };
 
        memset(path, 0, 512);
 
@@ -74,21 +84,13 @@
        while ((ent = readdir(dirfd)) != NULL) {
 
                log(TO_ALL, LOG_DEBUG, "Checking entry %s\n", ent->d_name);
-               if (!strncmp(ent->d_name, "ata", strlen("ata"))) {
-                       info->type = IRQ_TYPE_LEGACY;
-                       info->class = IRQ_SCSI;
-                       rc = 0;
-                       goto out;
-               } else if (!strncmp(ent->d_name, "net", strlen("net"))) {
-                       info->type = IRQ_TYPE_LEGACY;
-                       info->class = IRQ_ETH;
-                       rc = 0;
-                       goto out;
-               } else if (!strncmp(ent->d_name, "usb", strlen("net"))) {
-                       info->type = IRQ_TYPE_LEGACY;
-                       info->class = IRQ_OTHER;
-                       rc = 0;
-                       goto out;
+               for (i = 0; pdev_irq_info[i].d_name != NULL; i++) {
+                       if (!strncmp(ent->d_name, pdev_irq_info[i].d_name, 
strlen(pdev_irq_info[i].d_name))) {
+                               info->type = pdev_irq_info[i].type;
+                               info->class = pdev_irq_info[i].class;
+                               rc = 0;
+                               goto out;
+                       }
                }
        }
 
@@ -148,6 +150,9 @@
        char *line = NULL;
        size_t size = 0;
        char *irq_name, *irq_mod, *savedptr, *last_token, *p;
+#ifdef AARCH64
+       char *tmp;
+#endif
 
        file = fopen("/proc/interrupts", "r");
        if (!file)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/irqbalance-1.2.0/tests/Makefile.am 
new/irqbalance-1.4.0/tests/Makefile.am
--- old/irqbalance-1.2.0/tests/Makefile.am      1970-01-01 01:00:00.000000000 
+0100
+++ new/irqbalance-1.4.0/tests/Makefile.am      2018-05-14 21:06:54.000000000 
+0200
@@ -0,0 +1,2 @@
+check_SCRIPTS = runoneshot.sh 
+TESTS = runoneshot.sh
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/irqbalance-1.2.0/tests/runoneshot.sh 
new/irqbalance-1.4.0/tests/runoneshot.sh
--- old/irqbalance-1.2.0/tests/runoneshot.sh    1970-01-01 01:00:00.000000000 
+0100
+++ new/irqbalance-1.4.0/tests/runoneshot.sh    2018-05-14 21:06:54.000000000 
+0200
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+exec ../irqbalance --debug --oneshot --foreground
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/irqbalance-1.2.0/types.h new/irqbalance-1.4.0/types.h
--- old/irqbalance-1.2.0/types.h        2017-01-09 14:41:02.000000000 +0100
+++ new/irqbalance-1.4.0/types.h        2018-05-14 21:06:54.000000000 +0200
@@ -54,6 +54,7 @@
        GList *interrupts;
        struct topo_obj *parent;
        GList *children;
+       GList *numa_nodes;
        GList **obj_type_list;
 };
 
@@ -65,14 +66,11 @@
        int flags;
        struct topo_obj *numa_node;
        cpumask_t cpumask;
-       cpumask_t affinity_hint;
-       int hint_policy;
        uint64_t irq_count;
        uint64_t last_irq_count;
        uint64_t load;
        int moved;
        struct topo_obj *assigned_obj;
-       unsigned int warned;
        char *name;
 };
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/irqbalance-1.2.0/ui/helpers.c 
new/irqbalance-1.4.0/ui/helpers.c
--- old/irqbalance-1.2.0/ui/helpers.c   2017-01-09 14:41:02.000000000 +0100
+++ new/irqbalance-1.4.0/ui/helpers.c   2018-05-14 21:06:54.000000000 +0200
@@ -75,7 +75,8 @@
 
        char *bitmap = malloc(5 * sizeof(char));
        bitmap[4] = '\0';
-       for(int i = 3; i >= 0; i--) {
+       int i;
+       for(i = 3; i >= 0; i--) {
                bitmap[i] = digit % 2 ? '1' : '0';
                digit /= 2;
        }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/irqbalance-1.2.0/ui/irqbalance-ui.c 
new/irqbalance-1.4.0/ui/irqbalance-ui.c
--- old/irqbalance-1.2.0/ui/irqbalance-ui.c     2017-01-09 14:41:02.000000000 
+0100
+++ new/irqbalance-1.4.0/ui/irqbalance-ui.c     2018-05-14 21:06:54.000000000 
+0200
@@ -3,6 +3,7 @@
 #include <errno.h>
 #include <netdb.h>
 #include <stdio.h>
+#include <string.h>
 #include <stdlib.h>
 #include <sys/socket.h>
 #include <sys/types.h>
@@ -105,8 +106,13 @@
        msg->msg_iov = &iov;
        sendmsg(socket_fd, msg, 0);
 
-       char *data = malloc(2048 * sizeof(char));
-       int len = recv(socket_fd, data, 2048, 0);
+       /*
+        * This is just...horrible.  Mental note to replace this
+        * With a select, ioctl to determine size, and malloc based
+        * on that
+        */
+       char *data = malloc(8192);
+       int len = recv(socket_fd, data, 8192, 0);
        close(socket_fd);
        data[len] = '\0';
        return data;
@@ -115,39 +121,43 @@
 void parse_setup(char *setup_data)
 {
        char *token, *ptr;
+       int i,j;
+       char *copy;
        if((setup_data == NULL) || (strlen(setup_data) == 0)) return;
-       char copy[strlen(setup_data) + 1];
-       strncpy(copy, setup_data, strlen(setup_data) + 1);
+       copy = strdup(setup_data);
+       if (!copy)
+               return;
+
        setup.banned_irqs = NULL;
        setup.banned_cpus = NULL;
        token = strtok_r(copy, " ", &ptr);
        if(strncmp(token, "SLEEP", strlen("SLEEP"))) goto out;
-       setup.sleep = strtol(strtok_r(ptr, " ", &ptr), NULL, 10);
-       token = strtok_r(ptr, " ", &ptr);
+       setup.sleep = strtol(strtok_r(NULL, " ", &ptr), NULL, 10);
+       token = strtok_r(NULL, " ", &ptr);
        /* Parse banned IRQ data */
        while(!strncmp(token, "IRQ", strlen("IRQ"))) {
                irq_t *new_irq = malloc(sizeof(irq_t));
-               new_irq->vector = strtol(strtok_r(ptr, " ", &ptr), NULL, 10);
-               token = strtok_r(ptr, " ", &ptr);
+               new_irq->vector = strtol(strtok_r(NULL, " ", &ptr), NULL, 10);
+               token = strtok_r(NULL, " ", &ptr);
                if(strncmp(token, "LOAD", strlen("LOAD"))) goto out;
-               new_irq->load = strtol(strtok_r(ptr, " ", &ptr), NULL, 10);
-               token = strtok_r(ptr, " ", &ptr);
+               new_irq->load = strtol(strtok_r(NULL, " ", &ptr), NULL, 10);
+               token = strtok_r(NULL, " ", &ptr);
                if(strncmp(token, "DIFF", strlen("DIFF"))) goto out;
-               new_irq->diff = strtol(strtok_r(ptr, " ", &ptr), NULL, 10);
+               new_irq->diff = strtol(strtok_r(NULL, " ", &ptr), NULL, 10);
                token = strtok_r(ptr, " ", &ptr);
                if(strncmp(token, "CLASS", strlen("CLASS"))) goto out;
-               new_irq->class = strtol(strtok_r(ptr, " ", &ptr), NULL, 10);
+               new_irq->class = strtol(strtok_r(NULL, " ", &ptr), NULL, 10);
                new_irq->is_banned = 1;
                new_irq->assigned_to = NULL;
                setup.banned_irqs = g_list_append(setup.banned_irqs, new_irq);
-               token = strtok_r(ptr, " ", &ptr);
+               token = strtok_r(NULL, " ", &ptr);
        }
 
        if(strncmp(token, "BANNED", strlen("BANNED"))) goto out;
-       token = strtok_r(ptr, " ", &ptr);
-       for(int i = strlen(token) - 1; i >= 0; i--) {
+       token = strtok_r(NULL, " ", &ptr);
+       for(i = strlen(token) - 1; i >= 0; i--) {
                char *map = hex_to_bitmap(token[i]);
-               for(int j = 3; j >= 0; j--) {
+               for(j = 3; j >= 0; j--) {
                        if(map[j] == '1') {
                                uint64_t *banned_cpu = malloc(sizeof(uint64_t));
                                *banned_cpu = (4 * (strlen(token) - (i + 1)) + 
(4 - (j + 1)));
@@ -155,15 +165,15 @@
                                                                banned_cpu);
                        }
                }
+       
        }
+       free(copy);
        return;
 
 out: {
        /* Invalid data presented */
-       char invalid_data[128];
-       snprintf(invalid_data, 128, "Invalid data sent. Unexpected token: %s\n",
-                               token);
-       printf("%s\n", invalid_data);
+       printf("Invalid data sent.  Unexpected token: %s", token);
+       free(copy);
        g_list_free(tree);
        exit(1);
 }
@@ -226,55 +236,63 @@
 
 void parse_into_tree(char *data)
 {
-       if((data == NULL) || (strlen(data) == 0)) return;
        char *token, *ptr;
        cpu_node_t *parent = NULL;
-       char copy[strlen(data) + 1];
-       strncpy(copy, data, strlen(data) + 1);
+       char *copy;
        tree = NULL;
+       
+       if (!data || strlen(data) == 0)
+               return;
+
+       copy = strdup(data);
+       if (!copy)
+               return;
 
        token = strtok_r(copy, " ", &ptr);
        while(token != NULL) {
                /* Parse node data */
-               if(strncmp(token, "TYPE", strlen("TYPE"))) goto out;
+               if(strncmp(token, "TYPE", strlen("TYPE"))) {
+                       free(copy);
+                        goto out;
+               }
                cpu_node_t *new = malloc(sizeof(cpu_node_t));
                new->irqs = NULL;
                new->children = NULL;
                new->cpu_list = NULL;
                new->cpu_mask = NULL;
-               new->type = strtol(strtok_r(ptr, " ", &ptr), NULL, 10);
+               new->type = strtol(strtok_r(NULL, " ", &ptr), NULL, 10);
                if(new->type == OBJ_TYPE_NODE) {
                        parent = NULL;
                } else if(new->type >= parent->type) {
                        parent = parent->parent;
                }
-               token = strtok_r(ptr, " ", &ptr);
+               token = strtok_r(NULL, " ", &ptr);
                if(strncmp(token, "NUMBER", strlen("NUMBER"))) goto out;
-               new->number = strtol(strtok_r(ptr, " ", &ptr), NULL, 10);
-               token = strtok_r(ptr, " ", &ptr);
+               new->number = strtol(strtok_r(NULL, " ", &ptr), NULL, 10);
+               token = strtok_r(NULL, " ", &ptr);
                if(strncmp(token, "LOAD", strlen("LOAD"))) goto out;
-               new->load = strtol(strtok_r(ptr, " ", &ptr), NULL, 10);
-               token = strtok_r(ptr, " ", &ptr);
+               new->load = strtol(strtok_r(NULL, " ", &ptr), NULL, 10);
+               token = strtok_r(NULL, " ", &ptr);
                if(strncmp(token, "SAVE_MODE", strlen("SAVE_MODE"))) goto out;
-               new->is_powersave = strtol(strtok_r(ptr, " ", &ptr), NULL, 10);
-               token = strtok_r(ptr, " ", &ptr);
+               new->is_powersave = strtol(strtok_r(NULL, " ", &ptr), NULL, 10);
+               token = strtok_r(NULL, " ", &ptr);
 
                /* Parse assigned IRQ data */
                while((token != NULL) && (!strncmp(token, "IRQ", 
strlen("IRQ")))) {
                        irq_t *new_irq = malloc(sizeof(irq_t));
-                       new_irq->vector = strtol(strtok_r(ptr, " ", &ptr), 
NULL, 10);
-                       token = strtok_r(ptr, " ", &ptr);
+                       new_irq->vector = strtol(strtok_r(NULL, " ", &ptr), 
NULL, 10);
+                       token = strtok_r(NULL, " ", &ptr);
                        if(strncmp(token, "LOAD", strlen("LOAD"))) goto out;
-                       new_irq->load = strtol(strtok_r(ptr, " ", &ptr), NULL, 
10);
-                       token = strtok_r(ptr, " ", &ptr);
+                       new_irq->load = strtol(strtok_r(NULL, " ", &ptr), NULL, 
10);
+                       token = strtok_r(NULL, " ", &ptr);
                        if(strncmp(token, "DIFF", strlen("DIFF"))) goto out;
-                       new_irq->diff = strtol(strtok_r(ptr, " ", &ptr), NULL, 
10);
-                       token = strtok_r(ptr, " ", &ptr);
+                       new_irq->diff = strtol(strtok_r(NULL, " ", &ptr), NULL, 
10);
+                       token = strtok_r(NULL, " ", &ptr);
                        if(strncmp(token, "CLASS", strlen("CLASS"))) goto out;
-                       new_irq->class = strtol(strtok_r(ptr, " ", &ptr), NULL, 
10);
+                       new_irq->class = strtol(strtok_r(NULL, " ", &ptr), 
NULL, 10);
                        new_irq->is_banned = 0;
                        new->irqs = g_list_append(new->irqs, new_irq);
-                       token = strtok_r(ptr, " ", &ptr);
+                       token = strtok_r(NULL, " ", &ptr);
                }
 
                if((token == NULL) || (strncmp(token, "IRQ", strlen("IRQ")))) {
@@ -289,17 +307,14 @@
                        }
                }
        }
-
+       free(copy);
        for_each_node(tree, assign_cpu_lists, NULL);
        for_each_node(tree, assign_cpu_mask, NULL);
        return;
 
 out: {
        /* Invalid data presented */
-       char invalid_data[128];
-       snprintf(invalid_data, 128, "Invalid data sent. Unexpected token: %s\n",
-                               token);
-       printf("%s\n", invalid_data);
+       printf("Invalid data sent.  Unexpected token: %s\n", token);
        g_list_free(tree);
        exit(1);
 }
@@ -314,7 +329,7 @@
        if(is_tree) {
                display_tree();
        }
-
+       free(setup_data);
        return TRUE;
 }
 
@@ -361,13 +376,13 @@
                DIR *dir = opendir("/proc");
                if(dir) {
                        struct dirent *entry;
-                       char cmdfile[64];
+                       char cmdfile[512];
                        char cmdstring[256];
                        cmdstring[255] = '\0';
                        do {
                                entry = readdir(dir);
                                if(entry) {
-                                       snprintf(cmdfile, 64, 
"/proc/%s/cmdline", entry->d_name);
+                                       snprintf(cmdfile, 512, 
"/proc/%s/cmdline", entry->d_name);
                                        FILE *f = fopen(cmdfile, "r");
                                        if(f == NULL) {
                                                continue;
@@ -397,4 +412,5 @@
 
        g_main_loop_quit(main_loop);
        close_window(0);
+       return 0;
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/irqbalance-1.2.0/ui/ui.c new/irqbalance-1.4.0/ui/ui.c
--- old/irqbalance-1.2.0/ui/ui.c        2017-01-09 14:41:02.000000000 +0100
+++ new/irqbalance-1.4.0/ui/ui.c        2018-05-14 21:06:54.000000000 +0200
@@ -18,6 +18,7 @@
 
 void show_frame()
 {
+       int i;
        attrset(COLOR_PAIR(4));
        char top[COLS];
        top[0] = '\0';
@@ -25,7 +26,7 @@
                snprintf(top + strlen(top), COLS - strlen(top), " ");
        }
        mvprintw(0, 0, top);
-       for(int i = 0; i < LINES; i++) {
+       for(i = 0; i < LINES; i++) {
                mvprintw(i, 0, " ");
                mvprintw(i, COLS - 1, " ");
        }
@@ -613,6 +614,7 @@
                        break;
                }
        }
+       free(setup_data);
 }
 
 void setup_irqs()
@@ -665,6 +667,7 @@
 
 void display_tree_node(cpu_node_t *node, void *data)
 {
+       int i;
        const char *node_type_to_str[] = {
                        "CPU\0",
                        "CACHE DOMAIN\0",
@@ -674,7 +677,7 @@
        char *spaces = "    \0";
        char indent[32] = "\0";
        char *asciitree = " `--\0";
-       for(int i = node->type; i <= OBJ_TYPE_NODE; i++) {
+       for(i = node->type; i <= OBJ_TYPE_NODE; i++) {
                snprintf(indent + strlen(indent), 32 - strlen(indent), "%s", 
spaces);
                if(i != OBJ_TYPE_NODE) {
                        snprintf(indent + strlen(indent), 32 - strlen(indent), 
"   ");
@@ -726,4 +729,6 @@
        show_frame();
        show_footer();
        refresh();
+       free(setup_data);
+       free(irqbalance_data);
 }


Reply via email to