Blame irqbalance.c

Packit Service 2212bb
/* 
Packit Service 2212bb
 * Copyright (C) 2006, Intel Corporation
Packit Service 2212bb
 * Copyright (C) 2012, Neil Horman <nhorman@tuxdriver.com> 
Packit Service 2212bb
 * 
Packit Service 2212bb
 * This file is part of irqbalance
Packit Service 2212bb
 *
Packit Service 2212bb
 * This program file is free software; you can redistribute it and/or modify it
Packit Service 2212bb
 * under the terms of the GNU General Public License as published by the
Packit Service 2212bb
 * Free Software Foundation; version 2 of the License.
Packit Service 2212bb
 * 
Packit Service 2212bb
 * This program is distributed in the hope that it will be useful, but WITHOUT
Packit Service 2212bb
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
Packit Service 2212bb
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
Packit Service 2212bb
 * for more details.
Packit Service 2212bb
 * 
Packit Service 2212bb
 * You should have received a copy of the GNU General Public License
Packit Service 2212bb
 * along with this program in a file named COPYING; if not, write to the 
Packit Service 2212bb
 * Free Software Foundation, Inc., 
Packit Service 2212bb
 * 51 Franklin Street, Fifth Floor, 
Packit Service 2212bb
 * Boston, MA 02110-1301 USA
Packit Service 2212bb
 */
Packit Service 2212bb
#include "config.h"
Packit Service 2212bb
#include <unistd.h>
Packit Service 2212bb
#include <stdio.h>
Packit Service 2212bb
#include <stdlib.h>
Packit Service 2212bb
#include <malloc.h>
Packit Service 2212bb
#include <sys/time.h>
Packit Service 2212bb
#include <syslog.h>
Packit Service 2212bb
#include <unistd.h>
Packit Service 2212bb
#include <signal.h>
Packit Service 2212bb
#include <time.h>
Packit Service 2212bb
#include <sys/types.h>
Packit Service 2212bb
#include <sys/stat.h>
Packit Service 2212bb
#include <sys/socket.h>
Packit Service 2212bb
#include <sys/un.h>
Packit Service 2212bb
#include <fcntl.h>
Packit Service 2212bb
#ifdef HAVE_GETOPT_LONG 
Packit Service 2212bb
#include <getopt.h>
Packit Service 2212bb
#endif
Packit Service 2212bb
Packit Service 2212bb
#ifdef HAVE_LIBCAP_NG
Packit Service 2212bb
#include <cap-ng.h>
Packit Service 2212bb
#endif
Packit Service 2212bb
#include "irqbalance.h"
Packit Service 2212bb
Packit Service 2212bb
volatile int keep_going = 1;
Packit Service 2212bb
int socket_fd;
Packit Service 2212bb
int one_shot_mode;
Packit Service 2212bb
int debug_mode;
Packit Service 2212bb
int foreground_mode;
Packit Service 2212bb
int numa_avail;
Packit Service 2212bb
int journal_logging = 0;
Packit Service 2212bb
int need_rescan;
Packit Service 2212bb
unsigned int log_mask = TO_ALL;
Packit Service 2212bb
const char *log_indent;
Packit Service 2212bb
unsigned long power_thresh = ULONG_MAX;
Packit Service 2212bb
unsigned long deepest_cache = 2;
Packit Service 2212bb
unsigned long long cycle_count = 0;
Packit Service 2212bb
char *pidfile = NULL;
Packit Service 2212bb
char *banscript = NULL;
Packit Service 2212bb
char *polscript = NULL;
Packit Service 2212bb
long HZ;
Packit Service 2212bb
int sleep_interval = SLEEP_INTERVAL;
Packit Service 2212bb
GMainLoop *main_loop;
Packit Service 2212bb
Packit Service 2212bb
char *banned_cpumask_from_ui = NULL;
Packit Service 2212bb
Packit Service 2212bb
static void sleep_approx(int seconds)
Packit Service 2212bb
{
Packit Service 2212bb
	struct timespec ts;
Packit Service 2212bb
	struct timeval tv;
Packit Service 2212bb
	gettimeofday(&tv, NULL);
Packit Service 2212bb
	ts.tv_sec = seconds;
Packit Service 2212bb
	ts.tv_nsec = -tv.tv_usec*1000;
Packit Service 2212bb
	while (ts.tv_nsec < 0) {
Packit Service 2212bb
		ts.tv_sec--;
Packit Service 2212bb
		ts.tv_nsec += 1000000000;
Packit Service 2212bb
	}
Packit Service 2212bb
	nanosleep(&ts, NULL);
Packit Service 2212bb
}
Packit Service 2212bb
Packit Service 2212bb
#ifdef HAVE_GETOPT_LONG
Packit Service 2212bb
struct option lopts[] = {
Packit Service 2212bb
	{"oneshot", 0, NULL, 'o'},
Packit Service 2212bb
	{"debug", 0, NULL, 'd'},
Packit Service 2212bb
	{"foreground", 0, NULL, 'f'},
Packit Service 2212bb
	{"hintpolicy", 1, NULL, 'h'},
Packit Service 2212bb
	{"powerthresh", 1, NULL, 'p'},
Packit Service 2212bb
	{"banirq", 1 , NULL, 'i'},
Packit Service 2212bb
	{"banscript", 1, NULL, 'b'},
Packit Service 2212bb
	{"deepestcache", 1, NULL, 'c'},
Packit Service 2212bb
	{"policyscript", 1, NULL, 'l'},
Packit Service 2212bb
	{"pid", 1, NULL, 's'},
Packit Service 2212bb
	{"journal", 0, NULL, 'j'},
Packit Service 2212bb
	{"banmod", 1 , NULL, 'm'},
Packit Service 2212bb
	{"interval", 1 , NULL, 't'},
Packit Service 2212bb
	{"version", 0, NULL, 'V'},
Packit Service 2212bb
	{0, 0, 0, 0}
Packit Service 2212bb
};
Packit Service 2212bb
Packit Service 2212bb
static void usage(void)
Packit Service 2212bb
{
Packit Service 2212bb
	log(TO_CONSOLE, LOG_INFO, "irqbalance [--oneshot | -o] [--debug | -d] [--foreground | -f] [--journal | -j] [--hintpolicy= | -h [exact|subset|ignore]]\n");
Packit Service 2212bb
	log(TO_CONSOLE, LOG_INFO, "	[--powerthresh= | -p <off> | <n>] [--banirq= | -i <n>] [--banmod= | -m <module>] [--policyscript= | -l <script>]\n");
Packit Service 2212bb
	log(TO_CONSOLE, LOG_INFO, "	[--pid= | -s <file>] [--deepestcache= | -c <n>] [--interval= | -t <n>]\n");
Packit Service 2212bb
}
Packit Service 2212bb
Packit Service 2212bb
static void version(void)
Packit Service 2212bb
{
Packit Service 2212bb
	log(TO_CONSOLE, LOG_INFO, "irqbalance version " VERSION "\n");
Packit Service 2212bb
}
Packit Service 2212bb
Packit Service 2212bb
static void parse_command_line(int argc, char **argv)
Packit Service 2212bb
{
Packit Service 2212bb
	int opt;
Packit Service 2212bb
	int longind;
Packit Service 2212bb
	unsigned long val;
Packit Service 2212bb
Packit Service 2212bb
	while ((opt = getopt_long(argc, argv,
Packit Service 2212bb
		"odfji:p:s:c:b:l:m:t:V",
Packit Service 2212bb
		lopts, &longind)) != -1) {
Packit Service 2212bb
Packit Service 2212bb
		switch(opt) {
Packit Service 2212bb
			case '?':
Packit Service 2212bb
				usage();
Packit Service 2212bb
				exit(1);
Packit Service 2212bb
				break;
Packit Service 2212bb
			case 'V':
Packit Service 2212bb
				version();
Packit Service 2212bb
				exit(1);
Packit Service 2212bb
				break;
Packit Service 2212bb
			case 'b':
Packit Service 2212bb
#ifndef INCLUDE_BANSCRIPT
Packit Service 2212bb
				/*
Packit Service 2212bb
				 * Banscript is no longer supported unless
Packit Service 2212bb
				 * explicitly enabled
Packit Service 2212bb
				 */
Packit Service 2212bb
				log(TO_CONSOLE, LOG_INFO, "--banscript is not supported on this version of irqbalance, please use --policyscript\n");
Packit Service 2212bb
				usage();
Packit Service 2212bb
				exit(1);
Packit Service 2212bb
#endif
Packit Service 2212bb
				banscript = strdup(optarg);
Packit Service 2212bb
				break;
Packit Service 2212bb
			case 'c':
Packit Service 2212bb
				deepest_cache = strtoul(optarg, NULL, 10);
Packit Service 2212bb
				if (deepest_cache == ULONG_MAX || deepest_cache < 1) {
Packit Service 2212bb
					usage();
Packit Service 2212bb
					exit(1);
Packit Service 2212bb
				}
Packit Service 2212bb
				break;
Packit Service 2212bb
			case 'd':
Packit Service 2212bb
				debug_mode=1;
Packit Service 2212bb
				foreground_mode=1;
Packit Service 2212bb
				break;
Packit Service 2212bb
			case 'f':
Packit Service 2212bb
				foreground_mode=1;
Packit Service 2212bb
				break;
Packit Service 2212bb
			case 'i':
Packit Service 2212bb
				val = strtoull(optarg, NULL, 10);
Packit Service 2212bb
				if (val == ULONG_MAX) {
Packit Service 2212bb
					usage();
Packit Service 2212bb
					exit(1);
Packit Service 2212bb
				}
Packit Service 2212bb
				add_cl_banned_irq((int)val);
Packit Service 2212bb
				break;
Packit Service 2212bb
			case 'l':
Packit Service 2212bb
				polscript = strdup(optarg);
Packit Service 2212bb
				break;
Packit Service 2212bb
			case 'm':
Packit Service 2212bb
				add_cl_banned_module(optarg);
Packit Service 2212bb
				break;
Packit Service 2212bb
			case 'p':
Packit Service 2212bb
				if (!strncmp(optarg, "off", strlen(optarg)))
Packit Service 2212bb
					power_thresh = ULONG_MAX;
Packit Service 2212bb
				else {
Packit Service 2212bb
					power_thresh = strtoull(optarg, NULL, 10);
Packit Service 2212bb
					if (power_thresh == ULONG_MAX) {
Packit Service 2212bb
						usage();
Packit Service 2212bb
						exit(1);
Packit Service 2212bb
					}
Packit Service 2212bb
				}
Packit Service 2212bb
				break;
Packit Service 2212bb
			case 'o':
Packit Service 2212bb
				one_shot_mode=1;
Packit Service 2212bb
				break;
Packit Service 2212bb
			case 's':
Packit Service 2212bb
				pidfile = optarg;
Packit Service 2212bb
				break;
Packit Service 2212bb
			case 'j':
Packit Service 2212bb
				journal_logging=1;
Packit Service 2212bb
				foreground_mode=1;
Packit Service 2212bb
				break;
Packit Service 2212bb
			case 't':
Packit Service 2212bb
				sleep_interval = strtol(optarg, NULL, 10);
Packit Service 2212bb
				if (sleep_interval < 1) {
Packit Service 2212bb
					usage();
Packit Service 2212bb
					exit(1);
Packit Service 2212bb
				}
Packit Service 2212bb
				break;
Packit Service 2212bb
		}
Packit Service 2212bb
	}
Packit Service 2212bb
}
Packit Service 2212bb
#endif
Packit Service 2212bb
Packit Service 2212bb
/*
Packit Service 2212bb
 * This builds our object tree.  The Heirarchy is typically pretty
Packit Service 2212bb
 * straightforward.
Packit Service 2212bb
 * At the top are numa_nodes
Packit Service 2212bb
 * CPU packages belong to a single numa_node, unless the cache domains are in
Packit Service 2212bb
 * separate nodes.  In that case, the cache domain's parent is the package, but
Packit Service 2212bb
 * the numa nodes point to the cache domains instead of the package as their
Packit Service 2212bb
 * children.  This allows us to maintain the CPU hierarchy while adjusting for
Packit Service 2212bb
 * alternate memory topologies that are present on recent processor.
Packit Service 2212bb
 * All Cache domains belong to a CPU package
Packit Service 2212bb
 * All CPU cores belong to a cache domain
Packit Service 2212bb
 *
Packit Service 2212bb
 * Objects are built in that order (top down)
Packit Service 2212bb
 *
Packit Service 2212bb
 * Object workload is the aggregate sum of the
Packit Service 2212bb
 * workload of the objects below it
Packit Service 2212bb
 */
Packit Service 2212bb
static void build_object_tree(void)
Packit Service 2212bb
{
Packit Service 2212bb
	build_numa_node_list();
Packit Service 2212bb
	parse_cpu_tree();
Packit Service 2212bb
	rebuild_irq_db();
Packit Service 2212bb
}
Packit Service 2212bb
Packit Service 2212bb
static void free_object_tree(void)
Packit Service 2212bb
{
Packit Service 2212bb
	free_numa_node_list();
Packit Service 2212bb
	clear_cpu_tree();
Packit Service 2212bb
	free_irq_db();
Packit Service 2212bb
}
Packit Service 2212bb
Packit Service 2212bb
static void dump_object_tree(void)
Packit Service 2212bb
{
Packit Service 2212bb
	for_each_object(numa_nodes, dump_numa_node_info, NULL);
Packit Service 2212bb
}
Packit Service 2212bb
Packit Service 2212bb
static void force_rebalance_irq(struct irq_info *info, void *data __attribute__((unused)))
Packit Service 2212bb
{
Packit Service 2212bb
	if (info->level == BALANCE_NONE)
Packit Service 2212bb
		return;
Packit Service 2212bb
Packit Service 2212bb
	if (info->assigned_obj == NULL)
Packit Service 2212bb
		rebalance_irq_list = g_list_append(rebalance_irq_list, info);
Packit Service 2212bb
	else
Packit Service 2212bb
		migrate_irq(&info->assigned_obj->interrupts, &rebalance_irq_list, info);
Packit Service 2212bb
Packit Service 2212bb
	info->assigned_obj = NULL;
Packit Service 2212bb
}
Packit Service 2212bb
Packit Service 2212bb
gboolean handler(gpointer data __attribute__((unused)))
Packit Service 2212bb
{
Packit Service 2212bb
	keep_going = 0;
Packit Service 2212bb
	g_main_loop_quit(main_loop);
Packit Service 2212bb
	return TRUE;
Packit Service 2212bb
}
Packit Service 2212bb
Packit Service 2212bb
gboolean force_rescan(gpointer data __attribute__((unused)))
Packit Service 2212bb
{
Packit Service 2212bb
	if (cycle_count)
Packit Service 2212bb
		need_rescan = 1;
Packit Service 2212bb
	return TRUE;
Packit Service 2212bb
}
Packit Service 2212bb
Packit Service 2212bb
gboolean scan(gpointer data)
Packit Service 2212bb
{
Packit Service 2212bb
	log(TO_CONSOLE, LOG_INFO, "\n\n\n-----------------------------------------------------------------------------\n");
Packit Service 2212bb
	clear_work_stats();
Packit Service 2212bb
	parse_proc_interrupts();
Packit Service 2212bb
Packit Service 2212bb
Packit Service 2212bb
	/* cope with cpu hotplug -- detected during /proc/interrupts parsing */
Packit Service 2212bb
	if (need_rescan) {
Packit Service 2212bb
		need_rescan = 0;
Packit Service 2212bb
		cycle_count = 0;
Packit Service 2212bb
		log(TO_CONSOLE, LOG_INFO, "Rescanning cpu topology \n");
Packit Service 2212bb
		clear_work_stats();
Packit Service 2212bb
Packit Service 2212bb
		free_object_tree();
Packit Service 2212bb
		build_object_tree();
Packit Service 2212bb
		for_each_irq(NULL, force_rebalance_irq, NULL);
Packit Service 2212bb
		parse_proc_interrupts();
Packit Service 2212bb
		parse_proc_stat();
Packit Service 2212bb
		sleep_approx(sleep_interval);
Packit Service 2212bb
		clear_work_stats();
Packit Service 2212bb
		parse_proc_interrupts();
Packit Service 2212bb
	}
Packit Service 2212bb
Packit Service 2212bb
	parse_proc_stat();
Packit Service 2212bb
Packit Service 2212bb
	if (cycle_count)	
Packit Service 2212bb
		update_migration_status();
Packit Service 2212bb
Packit Service 2212bb
	calculate_placement();
Packit Service 2212bb
	activate_mappings();
Packit Service 2212bb
Packit Service 2212bb
	if (debug_mode)
Packit Service 2212bb
		dump_tree();
Packit Service 2212bb
	if (one_shot_mode)
Packit Service 2212bb
		keep_going = 0;
Packit Service 2212bb
	cycle_count++;
Packit Service 2212bb
Packit Service 2212bb
	if (data != &sleep_interval) {
Packit Service 2212bb
		data = &sleep_interval;
Packit Service 2212bb
		g_timeout_add_seconds(sleep_interval, scan, data);
Packit Service 2212bb
		return FALSE;
Packit Service 2212bb
	}
Packit Service 2212bb
Packit Service 2212bb
	if (keep_going) {
Packit Service 2212bb
		return TRUE;
Packit Service 2212bb
	} else {
Packit Service 2212bb
		g_main_loop_quit(main_loop);
Packit Service 2212bb
		return FALSE;
Packit Service 2212bb
	}
Packit Service 2212bb
}
Packit Service 2212bb
Packit Service 2212bb
void get_irq_data(struct irq_info *irq, void *data)
Packit Service 2212bb
{
Packit Service 2212bb
	char **irqdata = (char **)data;
Packit Service 2212bb
	if (!*irqdata)
Packit Service 2212bb
		*irqdata = calloc(24 + 1 + 11 + 20 + 20 + 11, 1);
Packit Service 2212bb
	else
Packit Service 2212bb
		*irqdata = realloc(*irqdata, strlen(*irqdata) + 24 + 1 + 11 + 20 + 20 + 11);
Packit Service 2212bb
Packit Service 2212bb
	sprintf(*irqdata + strlen(*irqdata),
Packit Service 2212bb
			"IRQ %d LOAD %lu DIFF %lu CLASS %d ", irq->irq, irq->load,
Packit Service 2212bb
			(irq->irq_count - irq->last_irq_count), irq->class);
Packit Service 2212bb
}
Packit Service 2212bb
Packit Service 2212bb
void get_object_stat(struct topo_obj *object, void *data)
Packit Service 2212bb
{
Packit Service 2212bb
	char **stats = (char **)data;	
Packit Service 2212bb
	char *irq_data = NULL;
Packit Service 2212bb
	size_t irqdlen;
Packit Service 2212bb
Packit Service 2212bb
	if (g_list_length(object->interrupts) > 0) {
Packit Service 2212bb
		for_each_irq(object->interrupts, get_irq_data, &irq_data);
Packit Service 2212bb
	}
Packit Service 2212bb
Packit Service 2212bb
	irqdlen = irq_data ? strlen(irq_data) : 0;
Packit Service 2212bb
	/*
Packit Service 2212bb
	 * Note, the size in both conditional branches below is made up as follows:
Packit Service 2212bb
	 * strlen(irq_data) - self explanitory
Packit Service 2212bb
	 * 31 - The size of "TYPE  NUMBER  LOAD  SAVE_MODE  "
Packit Service 2212bb
	 * 11 - The maximal size of a %d printout
Packit Service 2212bb
	 * 20 - The maximal size of a %lu printout
Packit Service 2212bb
	 * 1 - The trailing string terminator
Packit Service 2212bb
	 * This should be adjusted if the string in the sprintf is changed
Packit Service 2212bb
	 */
Packit Service 2212bb
	if (!*stats) {
Packit Service 2212bb
		*stats = calloc(irqdlen + 31 + 11 + 20 + 11 + 1, 1);
Packit Service 2212bb
	} else {
Packit Service 2212bb
		*stats = realloc(*stats, strlen(*stats) + irqdlen + 31 + 11 + 20 + 11 + 1);
Packit Service 2212bb
	}
Packit Service 2212bb
Packit Service 2212bb
	sprintf(*stats + strlen(*stats), "TYPE %d NUMBER %d LOAD %lu SAVE_MODE %d %s",
Packit Service 2212bb
			object->obj_type, object->number, object->load,
Packit Service 2212bb
			object->powersave_mode, irq_data ? irq_data : "");
Packit Service 2212bb
	free(irq_data);
Packit Service 2212bb
	if (object->obj_type != OBJ_TYPE_CPU) {
Packit Service 2212bb
		for_each_object(object->children, get_object_stat, data);
Packit Service 2212bb
	}
Packit Service 2212bb
}
Packit Service 2212bb
Packit Service 2212bb
gboolean sock_handle(gint fd, GIOCondition condition, gpointer user_data __attribute__((unused)))
Packit Service 2212bb
{
Packit Service 2212bb
	char buff[500];
Packit Service 2212bb
	int sock;
Packit Service 2212bb
	int recv_size = 0;
Packit Service 2212bb
	int valid_user = 0;
Packit Service 2212bb
Packit Service 2212bb
	struct iovec iov = { buff, 500 };
Packit Service 2212bb
	struct msghdr msg = { 0 };
Packit Service 2212bb
	msg.msg_iov = &iov;
Packit Service 2212bb
	msg.msg_iovlen = 1;
Packit Service 2212bb
	msg.msg_control = malloc(CMSG_SPACE(sizeof(struct ucred)));
Packit Service 2212bb
	msg.msg_controllen = CMSG_SPACE(sizeof(struct ucred));
Packit Service 2212bb
Packit Service 2212bb
	struct cmsghdr *cmsg;
Packit Service 2212bb
Packit Service 2212bb
	if (condition == G_IO_IN) {
Packit Service 2212bb
		sock = accept(fd, NULL, NULL);
Packit Service 2212bb
		if (sock < 0) {
Packit Service 2212bb
			log(TO_ALL, LOG_WARNING, "Connection couldn't be accepted.\n");
Packit Service 54b776
			goto out;
Packit Service 2212bb
		}
Packit Service 2212bb
		if ((recv_size = recvmsg(sock, &msg, 0)) < 0) {
Packit Service 2212bb
			log(TO_ALL, LOG_WARNING, "Error while receiving data.\n");
Packit Service 14d45b
			goto out_close;
Packit Service 2212bb
		}
Packit Service 2212bb
		cmsg = CMSG_FIRSTHDR(&msg;;
Packit Service 2212bb
		if ((cmsg->cmsg_level == SOL_SOCKET) &&
Packit Service 2212bb
				(cmsg->cmsg_type == SCM_CREDENTIALS)) {
Packit Service 2212bb
			struct ucred *credentials = (struct ucred *) CMSG_DATA(cmsg);
Packit Service 2212bb
			if (!credentials->uid) {
Packit Service 2212bb
				valid_user = 1;
Packit Service 2212bb
			}
Packit Service 2212bb
		}
Packit Service 2212bb
		if (!valid_user) {
Packit Service 2212bb
			log(TO_ALL, LOG_INFO, "Permission denied for user to connect to socket.\n");
Packit Service 14d45b
			goto out_close;
Packit Service 2212bb
		}
Packit Service 2212bb
Packit Service 2212bb
		if (!strncmp(buff, "stats", strlen("stats"))) {
Packit Service 2212bb
			char *stats = NULL;
Packit Service 2212bb
			for_each_object(numa_nodes, get_object_stat, &stats);
Packit Service 2212bb
			send(sock, stats, strlen(stats), 0);
Packit Service 2212bb
			free(stats);
Packit Service 2212bb
		}
Packit Service 2212bb
		if (!strncmp(buff, "settings ", strlen("settings "))) {
Packit Service 2212bb
			if (!(strncmp(buff + strlen("settings "), "sleep ",
Packit Service 2212bb
							strlen("sleep ")))) {
Packit Service 2212bb
				char *sleep_string = malloc(
Packit Service 2212bb
						sizeof(char) * (recv_size - strlen("settings sleep ")));
Packit Service 2212bb
				strncpy(sleep_string, buff + strlen("settings sleep "),
Packit Service 2212bb
						recv_size - strlen("settings sleep "));
Packit Service 2212bb
				int new_iterval = strtoul(sleep_string, NULL, 10);
Packit Service 2212bb
				if (new_iterval >= 1) {
Packit Service 2212bb
					sleep_interval = new_iterval;
Packit Service 2212bb
				}
Packit Service 54b776
				free(sleep_string);
Packit Service 2212bb
			} else if (!(strncmp(buff + strlen("settings "), "ban irqs ",
Packit Service 2212bb
							strlen("ban irqs ")))) {
Packit Service 2212bb
				char *end;
Packit Service 2212bb
				char *irq_string = malloc(
Packit Service 2212bb
						sizeof(char) * (recv_size - strlen("settings ban irqs ")));
Packit Service 2212bb
				strncpy(irq_string, buff + strlen("settings ban irqs "),
Packit Service 2212bb
						recv_size - strlen("settings ban irqs "));
Packit Service 2212bb
				g_list_free_full(cl_banned_irqs, free);
Packit Service 2212bb
				cl_banned_irqs = NULL;
Packit Service 2212bb
				need_rescan = 1;
Packit Service 2212bb
				if (!strncmp(irq_string, "NONE", strlen("NONE"))) {
Packit Service 54b776
					free(irq_string);
Packit Service 14d45b
					goto out_close;
Packit Service 2212bb
				}
Packit Service 2212bb
				int irq = strtoul(irq_string, &end, 10);
Packit Service 2212bb
				do {
Packit Service 2212bb
					add_cl_banned_irq(irq);
Packit Service 2212bb
				} while((irq = strtoul(end, &end, 10)));
Packit Service 54b776
				free(irq_string);
Packit Service 2212bb
			} else if (!(strncmp(buff + strlen("settings "), "cpus ",
Packit Service 2212bb
							strlen("cpus")))) {
Packit Service 2212bb
				char *cpu_ban_string = malloc(
Packit Service 2212bb
						sizeof(char) * (recv_size - strlen("settings cpus ")));
Packit Service 2212bb
				strncpy(cpu_ban_string, buff + strlen("settings cpus "),
Packit Service 2212bb
						recv_size - strlen("settings cpus "));
Packit Service 2212bb
				banned_cpumask_from_ui = strtok(cpu_ban_string, " ");
Packit Service 2212bb
				if (!strncmp(banned_cpumask_from_ui, "NULL", strlen("NULL"))) {
Packit Service 2212bb
					banned_cpumask_from_ui = NULL;
Packit Service 2212bb
				}
Packit Service 2212bb
				need_rescan = 1;
Packit Service 54b776
				free(cpu_ban_string);
Packit Service 2212bb
			}
Packit Service 2212bb
		}
Packit Service 2212bb
		if (!strncmp(buff, "setup", strlen("setup"))) {
Packit Service 2212bb
			char banned[512];
Packit Service 97e4d9
			char *setup = calloc(strlen("SLEEP  ") + 11 + 1, 1);
Packit Service 97e4d9
			snprintf(setup, strlen("SLEEP  ") + 11 + 1, "SLEEP %d ", sleep_interval);
Packit Service 2212bb
			if(g_list_length(cl_banned_irqs) > 0) {
Packit Service 2212bb
				for_each_irq(cl_banned_irqs, get_irq_data, setup);
Packit Service 2212bb
			}
Packit Service 2212bb
			cpumask_scnprintf(banned, 512, banned_cpus);
Packit Service 2212bb
			setup = realloc(setup, strlen(setup) + strlen(banned) + 7 + 1);
Packit Service 2212bb
			snprintf(setup + strlen(setup), strlen(banned) + 7 + 1,
Packit Service 2212bb
					"BANNED %s", banned);
Packit Service 2212bb
			send(sock, setup, strlen(setup), 0);
Packit Service 54b776
			free(setup);
Packit Service 2212bb
		}
Packit Service 2212bb
Packit Service 14d45b
out_close:
Packit Service 2212bb
		close(sock);
Packit Service 2212bb
	}
Packit Service 54b776
Packit Service 54b776
out:
Packit Service 54b776
	free(msg.msg_control);
Packit Service 2212bb
	return TRUE;
Packit Service 2212bb
}
Packit Service 2212bb
Packit Service 2212bb
int init_socket(char *socket_name)
Packit Service 2212bb
{
Packit Service 2212bb
	struct sockaddr_un addr;
Packit Service 2212bb
	memset(&addr, 0, sizeof(struct sockaddr_un));
Packit Service 2212bb
Packit Service 2212bb
	socket_fd = socket(AF_LOCAL, SOCK_STREAM, 0);
Packit Service 2212bb
	if (socket_fd < 0) {
Packit Service 2212bb
		log(TO_ALL, LOG_WARNING, "Socket couldn't be created.\n");
Packit Service 2212bb
		return 1;
Packit Service 2212bb
	}
Packit Service 2212bb
Packit Service 2212bb
	addr.sun_family = AF_UNIX;
Packit Service 2212bb
	addr.sun_path[0] = '\0';
Packit Service 2212bb
	strncpy(addr.sun_path + 1, socket_name, strlen(socket_name));
Packit Service 2212bb
	if (bind(socket_fd, (struct sockaddr *)&addr,
Packit Service 2212bb
				sizeof(sa_family_t) + strlen(socket_name) + 1) < 0) {
Packit Service 2212bb
		log(TO_ALL, LOG_WARNING, "Daemon couldn't be bound to the socket.\n");
Packit Service 2212bb
		return 1;
Packit Service 2212bb
	}
Packit Service 2212bb
	int optval = 1;
Packit Service 2212bb
	if (setsockopt(socket_fd, SOL_SOCKET, SO_PASSCRED, &optval, sizeof(optval)) < 0) {
Packit Service 2212bb
		log(TO_ALL, LOG_WARNING, "Unable to set socket options.\n");
Packit Service 2212bb
		return 1;
Packit Service 2212bb
	}
Packit Service 2212bb
	listen(socket_fd, 1);
Packit Service 2212bb
	g_unix_fd_add(socket_fd, G_IO_IN, sock_handle, NULL);
Packit Service 2212bb
	return 0;
Packit Service 2212bb
}
Packit Service 2212bb
Packit Service 2212bb
int main(int argc, char** argv)
Packit Service 2212bb
{
Packit Service 2212bb
	sigset_t sigset, old_sigset;
Packit Service 2212bb
Packit Service 2212bb
	sigemptyset(&sigset);
Packit Service 2212bb
	sigaddset(&sigset,SIGINT);
Packit Service 2212bb
	sigaddset(&sigset,SIGHUP);
Packit Service 2212bb
	sigaddset(&sigset,SIGTERM);
Packit Service 2212bb
	sigaddset(&sigset,SIGUSR1);
Packit Service 2212bb
	sigaddset(&sigset,SIGUSR2);
Packit Service 2212bb
	sigprocmask(SIG_BLOCK, &sigset, &old_sigset);
Packit Service 2212bb
#ifdef HAVE_GETOPT_LONG
Packit Service 2212bb
	parse_command_line(argc, argv);
Packit Service 2212bb
#else /* ! HAVE_GETOPT_LONG */
Packit Service 2212bb
	if (argc>1 && strstr(argv[1],"--debug")) {
Packit Service 2212bb
		debug_mode=1;
Packit Service 2212bb
		foreground_mode=1;
Packit Service 2212bb
	}
Packit Service 2212bb
	if (argc>1 && strstr(argv[1],"--foreground"))
Packit Service 2212bb
		foreground_mode=1;
Packit Service 2212bb
	if (argc>1 && strstr(argv[1],"--oneshot"))
Packit Service 2212bb
		one_shot_mode=1;
Packit Service 2212bb
	if (argc>1 && strstr(argv[1],"--journal")) {
Packit Service 2212bb
		journal_logging=1;
Packit Service 2212bb
		foreground_mode=1;
Packit Service 2212bb
	}
Packit Service 2212bb
#endif /* HAVE_GETOPT_LONG */
Packit Service 2212bb
Packit Service 2212bb
	/*
Packit Service 2212bb
 	 * Open the syslog connection
Packit Service 2212bb
 	 */
Packit Service 2212bb
	openlog(argv[0], 0, LOG_DAEMON);
Packit Service 2212bb
Packit Service 2212bb
	if (getenv("IRQBALANCE_ONESHOT")) 
Packit Service 2212bb
		one_shot_mode=1;
Packit Service 2212bb
Packit Service 2212bb
	if (getenv("IRQBALANCE_DEBUG")) {
Packit Service 2212bb
		debug_mode=1;
Packit Service 2212bb
		foreground_mode=1;
Packit Service 2212bb
	}
Packit Service 2212bb
Packit Service 2212bb
	/*
Packit Service 2212bb
 	 * If we are't in debug mode, don't dump anything to the console
Packit Service 2212bb
 	 * note that everything goes to the console before we check this
Packit Service 2212bb
 	 */
Packit Service 2212bb
	if (journal_logging)
Packit Service 2212bb
		log_indent = "....";
Packit Service 2212bb
	else
Packit Service 2212bb
		log_indent = "    ";
Packit Service 2212bb
Packit Service 2212bb
	if (!debug_mode)
Packit Service 2212bb
		log_mask &= ~TO_CONSOLE;
Packit Service 2212bb
Packit Service 2212bb
	if (numa_available() > -1) {
Packit Service 2212bb
		numa_avail = 1;
Packit Service 2212bb
	} else 
Packit Service 2212bb
		log(TO_CONSOLE, LOG_INFO, "This machine seems not NUMA capable.\n");
Packit Service 2212bb
Packit Service 2212bb
	if (geteuid() != 0)
Packit Service 2212bb
		log(TO_ALL, LOG_WARNING, "Irqbalance hasn't been executed under root privileges, thus it won't in fact balance interrupts.\n");
Packit Service 2212bb
Packit Service 2212bb
	if (banscript) {
Packit Service 2212bb
		char *note = "Please note that --banscript is deprecated, please use --policyscript instead";
Packit Service 2212bb
		log(TO_ALL, LOG_WARNING, "%s\n", note);
Packit Service 2212bb
	}
Packit Service 2212bb
Packit Service 2212bb
	HZ = sysconf(_SC_CLK_TCK);
Packit Service 2212bb
	if (HZ == -1) {
Packit Service 2212bb
		log(TO_ALL, LOG_WARNING, "Unable to determin HZ defaulting to 100\n");
Packit Service 2212bb
		HZ = 100;
Packit Service 2212bb
	}
Packit Service 2212bb
Packit Service 2212bb
	build_object_tree();
Packit Service 2212bb
	if (debug_mode)
Packit Service 2212bb
		dump_object_tree();
Packit Service 2212bb
Packit Service 2212bb
Packit Service 2212bb
	/* On single core UP systems irqbalance obviously has no work to do */
Packit Service 2212bb
	if (core_count<2) {
Packit Service 2212bb
		char *msg = "Balancing is ineffective on systems with a "
Packit Service 2212bb
			    "single cpu.  Shutting down\n";
Packit Service 2212bb
Packit Service 2212bb
		log(TO_ALL, LOG_WARNING, "%s", msg);
Packit Service 2212bb
		exit(EXIT_SUCCESS);
Packit Service 2212bb
	}
Packit Service 2212bb
Packit Service 2212bb
	if (!foreground_mode) {
Packit Service 2212bb
		int pidfd = -1;
Packit Service 2212bb
		if (daemon(0,0))
Packit Service 2212bb
			exit(EXIT_FAILURE);
Packit Service 2212bb
		/* Write pidfile */
Packit Service 2212bb
		if (pidfile && (pidfd = open(pidfile,
Packit Service 2212bb
			O_WRONLY | O_CREAT | O_EXCL | O_TRUNC,
Packit Service 2212bb
			S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) >= 0) {
Packit Service 2212bb
			char str[16];
Packit Service 2212bb
			snprintf(str, sizeof(str), "%u\n", getpid());
Packit Service 2212bb
			write(pidfd, str, strlen(str));
Packit Service 2212bb
			close(pidfd);
Packit Service 2212bb
		}
Packit Service 2212bb
	}
Packit Service 2212bb
Packit Service 2212bb
	g_unix_signal_add(SIGINT, handler, NULL);
Packit Service 2212bb
	g_unix_signal_add(SIGTERM, handler, NULL);
Packit Service 2212bb
	g_unix_signal_add(SIGUSR1, handler, NULL);
Packit Service 2212bb
	g_unix_signal_add(SIGUSR2, handler, NULL);
Packit Service 2212bb
	g_unix_signal_add(SIGHUP, force_rescan, NULL);
Packit Service 2212bb
	sigprocmask(SIG_SETMASK, &old_sigset, NULL);
Packit Service 2212bb
Packit Service 2212bb
#ifdef HAVE_LIBCAP_NG
Packit Service 2212bb
	// Drop capabilities
Packit Service 2212bb
	capng_clear(CAPNG_SELECT_BOTH);
Packit Service 2212bb
	capng_lock();
Packit Service 2212bb
	capng_apply(CAPNG_SELECT_BOTH);
Packit Service 2212bb
#endif
Packit Service 2212bb
	for_each_irq(NULL, force_rebalance_irq, NULL);
Packit Service 2212bb
Packit Service 2212bb
	parse_proc_interrupts();
Packit Service 2212bb
	parse_proc_stat();
Packit Service 2212bb
Packit Service 2212bb
	char socket_name[64];
Packit Service 2212bb
	snprintf(socket_name, 64, "%s%d.sock", SOCKET_PATH, getpid());
Packit Service 2212bb
Packit Service 2212bb
	if (init_socket(socket_name)) {
Packit Service 2212bb
		return EXIT_FAILURE;
Packit Service 2212bb
	}
Packit Service 2212bb
	main_loop = g_main_loop_new(NULL, FALSE);
Packit Service 2212bb
	int *last_interval = &sleep_interval;
Packit Service 2212bb
	g_timeout_add_seconds(sleep_interval, scan, last_interval);
Packit Service 2212bb
	g_main_loop_run(main_loop);
Packit Service 2212bb
Packit Service 2212bb
	g_main_loop_quit(main_loop);
Packit Service 2212bb
Packit Service 2212bb
	free_object_tree();
Packit Service 2212bb
	free_cl_opts();
Packit Service 2212bb
Packit Service 2212bb
	/* Remove pidfile */
Packit Service 2212bb
	if (!foreground_mode && pidfile)
Packit Service 2212bb
		unlink(pidfile);
Packit Service 2212bb
	/* Remove socket */
Packit Service 2212bb
	close(socket_fd);
Packit Service 2212bb
Packit Service 2212bb
	return EXIT_SUCCESS;
Packit Service 2212bb
}