Browse Source

Don't use Netlink. Regular IRQ rescan

Serj Kalichev 10 years ago
parent
commit
83a5e875eb
5 changed files with 33 additions and 232 deletions
  1. 3 5
      Makefile.am
  2. 20 76
      birq.c
  3. 10 6
      irq_parse.c
  4. 0 133
      nl.c
  5. 0 12
      nl.h

+ 3 - 5
Makefile.am

@@ -15,22 +15,20 @@ lib_LIBRARIES =
 
 noinst_HEADERS = \
 	birq.h \
-	irq.h \
-	nl.h \
-	cpumask.h \
 	bitmap.h \
 	non-atomic.h \
+	cpumask.h \
+	irq.h \
 	cpu.h \
 	statistics.h \
 	balance.h
 
 birq_SOURCES = \
 	birq.c \
-	nl.c \
+	bitmap.c \
 	irq_parse.c \
 	cpu_parse.c \
 	statistics.c \
-	bitmap.c \
 	balance.c
 
 birq_LDADD = liblub.a

+ 20 - 76
birq.c

@@ -23,17 +23,11 @@
 #include <getopt.h>
 #endif
 
-#include <sys/poll.h>
-#include <sys/socket.h>
-#include <linux/types.h>
-#include <linux/netlink.h>
-
 #include "birq.h"
 #include "lub/log.h"
 #include "lub/list.h"
 #include "irq.h"
 #include "cpu.h"
-#include "nl.h"
 #include "statistics.h"
 #include "balance.h"
 
@@ -43,12 +37,9 @@
 #define QUOTE(t) #t
 #define version(v) printf("%s\n", v)
 
-static volatile int sigterm = 0; /* Exit if 1 */
-static volatile int rescan = 1; /* IRQ rescan is needed */
-
 /* Signal handlers */
+static volatile int sigterm = 0; /* Exit if 1 */
 static void sighandler(int signo);
-static void rescan_sighandler(int signo);
 
 static void help(int status, const char *argv0);
 static struct options *opts_init(void);
@@ -75,9 +66,6 @@ int main(int argc, char **argv)
 	struct sigaction sig_act;
 	sigset_t sig_set;
 
-	/* NetLink vars */
-	nl_fds_t *nl_fds = NULL; /* NetLink socket */
-
 	/* IRQ list. It contain all found IRQs. */
 	lub_list_t *irqs;
 	/* IRQs need to be balanced */
@@ -94,10 +82,6 @@ int main(int argc, char **argv)
 	openlog(argv[0], LOG_CONS, opts->log_facility);
 	syslog(LOG_ERR, "Start daemon.\n");
 
-	/* Init NetLink socket */
-	if (!(nl_fds = nl_init()))
-		goto err;
-
 	/* Fork the daemon */
 	if (!opts->debug) {
 		/* Daemonize */
@@ -135,15 +119,6 @@ int main(int argc, char **argv)
 	sigaction(SIGINT, &sig_act, NULL);
 	sigaction(SIGQUIT, &sig_act, NULL);
 
-	/* Set rescan signal handler */
-	sigemptyset(&sig_set);
-	sigaddset(&sig_set, SIGUSR1);
-
-	sig_act.sa_flags = 0;
-	sig_act.sa_mask = sig_set;
-	sig_act.sa_handler = &rescan_sighandler;
-	sigaction(SIGUSR1, &sig_act, NULL);
-
 	/* Scan CPUs */
 	cpus = lub_list_new(cpu_list_compare);
 	scan_cpus(cpus);
@@ -155,31 +130,9 @@ int main(int argc, char **argv)
 	/* Main loop */
 	while (!sigterm) {
 		lub_list_node_t *node;
-		int n;
-
-		if (rescan) {
-			if (opts->debug)
-				fprintf(stdout, "Scanning hardware...\n");
-			rescan = 0;
-			scan_irqs(irqs, balance_irqs);
-			if (opts->debug)
-				irq_list_show(irqs);
-		}
 
-		/* Timeout and poll for new devices */
-		while ((n = nl_poll(nl_fds, interval)) != 0) {
-			if (-1 == n) {
-				fprintf(stderr,
-					"Error: Broken NetLink socket.\n");
-				goto end;
-			}
-			if (-2 == n) /* EINTR */
-				break;
-			if (n > 0) {
-				rescan = 1;
-				continue;
-			}
-		}
+		/* Rescan PCI devices for new IRQs. */
+		scan_irqs(irqs, balance_irqs);
 
 		/* Gather statistics on CPU load and number of interrupts. */
 		gather_statistics(cpus, irqs);
@@ -191,24 +144,27 @@ int main(int argc, char **argv)
 				opts->threshold);
 		}
 		/* If nothing to balance */
-		if (lub_list_len(balance_irqs) == 0) {
+		if (lub_list_len(balance_irqs) != 0) {
+			/* Set short interval to make balancing faster. */
+			interval = BIRQ_SHORT_INTERVAL;
+			/* Choose new CPU for IRQs need to be balanced. */
+			balance(cpus, balance_irqs, opts->threshold);
+			/* Write new values to /proc/irq/<IRQ>/smp_affinity */
+			apply_affinity(balance_irqs);
+			/* Free list of balanced IRQs */
+			while ((node = lub_list__get_tail(balance_irqs))) {
+				lub_list_del(balance_irqs, node);
+				lub_list_node_free(node);
+			}
+		} else {
+			/* If nothing to balance */
 			interval = BIRQ_LONG_INTERVAL;
-			continue;
-		}
-		/* Set short interval to make balancing faster. */
-		interval = BIRQ_SHORT_INTERVAL;
-		/* Choose new CPU for IRQs need to be balanced. */
-		balance(cpus, balance_irqs, opts->threshold);
-		/* Write new values to /proc/irq/<IRQ>/smp_affinity */
-		apply_affinity(balance_irqs);
-		/* Free list of balanced IRQs */
-		while ((node = lub_list__get_tail(balance_irqs))) {
-			lub_list_del(balance_irqs, node);
-			lub_list_node_free(node);
 		}
+		
+		/* Wait before nex iteration */
+		sleep(interval);
 	}
 
-end:
 	/* Free data structures */
 	irq_list_free(irqs);
 	lub_list_free(balance_irqs);
@@ -216,9 +172,6 @@ end:
 
 	retval = 0;
 err:
-	/* Close NetLink socket */
-	nl_close(nl_fds);
-
 	/* Remove pidfile */
 	if (pidfd >= 0) {
 		if (unlink(opts->pidfile) < 0) {
@@ -243,15 +196,6 @@ static void sighandler(int signo)
 	sigterm = 1;
 }
 
-/*--------------------------------------------------------- */
-/*
- * Force IRQ rescan (SIGUSR1)
- */
-static void rescan_sighandler(int signo)
-{
-	rescan = 1;
-}
-
 /*--------------------------------------------------------- */
 /* Initialize option structure by defaults */
 static struct options *opts_init(void)

+ 10 - 6
irq_parse.c

@@ -218,6 +218,9 @@ int scan_irqs(lub_list_t *irqs, lub_list_t *balance_irqs)
 			irq = irq_list_add(irqs, num);
 		}
 
+		/* Set refresh flag because IRQ was found */
+		irq->refresh = 1;
+
 		/* Find IRQ type - first non-digital and non-space */
 		while (*endptr && !isalpha(*endptr))
 			endptr++;
@@ -236,13 +239,11 @@ int scan_irqs(lub_list_t *irqs, lub_list_t *balance_irqs)
 		free(irq->desc);
 		irq->desc = strndup(tok, endptr - tok);
 
-		/* Set refresh flag because IRQ was found */
-		irq->refresh = 1;
-
-		/* By default all CPUs are local for IRQ */
-		cpus_setall(irq->local_cpus);
-
 		if (new) {
+			/* By default all CPUs are local for IRQ. Real local
+			   CPUs will be find while sysfs scan. */
+			cpus_setall(irq->local_cpus);
+
 			lub_list_add(balance_irqs, irq);
 			printf("Add IRQ %3d %s\n", irq->irq, STR(irq->desc));
 		}
@@ -268,6 +269,9 @@ int scan_irqs(lub_list_t *irqs, lub_list_t *balance_irqs)
 		}
 	}
 
+	/* No new IRQs were found. It doesn't need to scan sysfs. */
+	if (lub_list_len(balance_irqs) == 0)
+		return 0;
 	/* Add IRQ info from sysfs */
 	parse_sysfs(irqs);
 

+ 0 - 133
nl.c

@@ -1,133 +0,0 @@
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <asm/types.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <linux/netlink.h>
-#include <sys/select.h>
-#include <sys/time.h>
-#include <unistd.h>
-
-#include "nl.h"
-
-nl_fds_t * nl_init(void)
-{
-	struct sockaddr_nl nl_addr;
-	nl_fds_t *nl_fds;
-
-	nl_fds = malloc(sizeof(*nl_fds) * NL_FDS_LEN);
-	if (!nl_fds)
-		return NULL;
-
-	memset(&nl_addr, 0, sizeof(nl_addr));
-	nl_addr.nl_family = AF_NETLINK;
-	nl_addr.nl_pad = 0;
-	nl_addr.nl_pid = 0; /* Let kernel to assign id */
-	nl_addr.nl_groups = -1; /* Listen all multicast */
-
-	/* NETLINK_KOBJECT_UEVENT for PCI events */
-	if ((nl_fds[0] = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT)) < 0) {
-		fprintf(stderr, "Error: Can't create socket for NETLINK_KOBJECT_UEVENT.\n");
-		return NULL;
-	}
-	if (bind(nl_fds[0], (void *)&nl_addr, sizeof(nl_addr))) {
-		fprintf(stderr, "Error: Can't bind NETLINK_KOBJECT_UEVENT.\n");
-		return NULL;
-	}
-
-	/* NETLINK_ROUTER for network events like interface up/down */
-	if ((nl_fds[1] = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE)) < 0) {
-		fprintf(stderr, "Error: Can't create socket for NETLINK_ROUTER\n");
-		return NULL;
-	}
-	if (bind(nl_fds[1], (void *)&nl_addr, sizeof(nl_addr))) {
-		fprintf(stderr, "Error: Can't bind NETLINK_ROUTER\n");
-		return NULL;
-	}
-
-	/* TODO: Parse NETWORK events to filter many unneeded events */
-	/* Temporarily disable network events */
-	close(nl_fds[1]);
-	nl_fds[1] = -1;
-
-	return nl_fds;
-}
-
-void nl_close(nl_fds_t *nl_fds)
-{
-	int i;
-
-	if (!nl_fds)
-		return;
-
-	for (i = 0; i < NL_FDS_LEN; i++) {
-		if (nl_fds[i] >= 0)
-			close(nl_fds[i]);
-	}
-
-	free(nl_fds);
-}
-
-int nl_poll(nl_fds_t *nl_fds, int timeout)
-{
-	fd_set set;
-	char buf[10];
-	int n;
-	int i;
-	int nfds = 0;
-	struct timeval tv;
-
-	if (!nl_fds)
-		return -1;
-
-	/* Initialize the set of active sockets. */
-	FD_ZERO(&set);
-	for (i = 0; i < NL_FDS_LEN; i++) {
-		if (nl_fds[i] < 0)
-			continue;
-		FD_SET(nl_fds[i], &set);
-		if (nl_fds[i] > nfds)
-			nfds = nl_fds[i];
-	}
-	nfds++;
-
-	/* Wait up to five seconds. */
-	tv.tv_sec = timeout;
-	tv.tv_usec = 0;
-
-	n = select(nfds, &set, NULL, NULL, &tv);
-	if (n < 0) {
-		if (EINTR == errno)
-			return -2;
-		return -1;
-	}
-	if (0 == n)
-		return n;
-
-	/* Service all the sockets with input pending. */
-	for (i = 0; i < NL_FDS_LEN; i++) {
-		char *evtype = NULL;
-		if (nl_fds[i] < 0)
-			continue;
-		if (!FD_ISSET(nl_fds[i], &set))
-			continue;
-		switch (i) {
-		case 0:
-			evtype = "kernel";
-			break;
-		case 1:
-			evtype = "network";
-			break;
-		default:
-			evtype = "unknown";
-			break;
-		}
-		printf("Receive %s event\n", evtype);
-		/* Read all messages. We don't need a message content. */
-		while (recv(nl_fds[i], buf, sizeof(buf), MSG_DONTWAIT) > 0);
-	}
-
-	return n;
-}

+ 0 - 12
nl.h

@@ -1,12 +0,0 @@
-#ifndef _nl_h
-#define _nl_h
-
-#define NL_FDS_LEN 2
-
-typedef int nl_fds_t;
-
-nl_fds_t * nl_init(void);
-void nl_close(nl_fds_t *nl_fds);
-int nl_poll(nl_fds_t *nl_fds, int timeout);
-
-#endif