add irq hotplug feature for irqbalance

This commit is contained in:
hejingxian 00273181 2020-12-04 10:52:57 +08:00
parent 004c7abcdb
commit 0ba4a60a2a
4 changed files with 125 additions and 65 deletions

View file

@ -619,7 +619,7 @@ static void add_new_irq(char *path, struct irq_info *hint, GList *proc_interrupt
/*
* Figures out which interrupt(s) relate to the device we"re looking at in dirname
*/
static void build_one_dev_entry(const char *dirname, GList *tmp_irqs)
static void build_one_dev_entry(const char *dirname, GList *tmp_irqs, int build_irq)
{
struct dirent *entry;
DIR *msidir;
@ -642,10 +642,14 @@ static void build_one_dev_entry(const char *dirname, GList *tmp_irqs)
if (!entry)
break;
irqnum = strtol(entry->d_name, NULL, 10);
if (irqnum) {
/* If build_irq is valid, only add irq when it's number equals to build_irq */
if (irqnum && ((build_irq < 0) || (irqnum == build_irq))) {
printf("add irq:%d %d for %s\n", irqnum, build_irq, path);
hint.irq = irqnum;
hint.type = IRQ_TYPE_MSIX;
add_new_irq(devpath, &hint, tmp_irqs);
if (build_irq >= 0)
break;
}
} while (entry != NULL);
closedir(msidir);
@ -665,9 +669,12 @@ static void build_one_dev_entry(const char *dirname, GList *tmp_irqs)
#else
if (irqnum) {
#endif
hint.irq = irqnum;
hint.type = IRQ_TYPE_LEGACY;
add_new_irq(devpath, &hint, tmp_irqs);
/* If build_irq is valid, only add irq when it's number equals to build_irq */
if ((build_irq < 0) || (irqnum == build_irq)) {
hint.irq = irqnum;
hint.type = IRQ_TYPE_LEGACY;
add_new_irq(devpath, &hint, tmp_irqs);
}
}
done:
@ -712,31 +719,60 @@ static void free_tmp_irqs(gpointer data)
free(info);
}
void rebuild_irq_db(void)
static struct irq_info * build_dev_irqs(GList *tmp_irqs, int build_irq)
{
DIR *devdir;
struct dirent *entry;
struct irq_info *new_irq = NULL;
devdir = opendir(SYSPCI_DIR);
if (devdir) {
do {
entry = readdir(devdir);
if (!entry)
break;
/* when hotplug irqs, we add one irq at one time */
build_one_dev_entry(entry->d_name, tmp_irqs, build_irq);
if (build_irq >= 0) {
new_irq = get_irq_info(build_irq);
if (new_irq)
break;
}
} while (entry != NULL);
closedir(devdir);
}
return new_irq;
}
int proc_irq_hotplug(char *savedline, int irq, struct irq_info **pinfo)
{
struct irq_info tmp_info = {0};
/* firstly, init irq info by read device info */
*pinfo = build_dev_irqs(interrupts_db, irq);
if (*pinfo == NULL) {
/* secondly, init irq info by parse savedline */
init_irq_class_and_type(savedline, &tmp_info, irq);
add_new_irq(NULL, &tmp_info, interrupts_db);
*pinfo = get_irq_info(irq);
}
if (*pinfo == NULL) {
return -1;
}
force_rebalance_irq(*pinfo, NULL);
return 0;
}
void rebuild_irq_db(void)
{
GList *tmp_irqs = NULL;
free_irq_db();
tmp_irqs = collect_full_irq_list();
devdir = opendir(SYSPCI_DIR);
if (devdir) {
do {
entry = readdir(devdir);
if (!entry)
break;
build_one_dev_entry(entry->d_name, tmp_irqs);
} while (entry != NULL);
closedir(devdir);
}
build_dev_irqs(tmp_irqs, -1);
for_each_irq(tmp_irqs, add_missing_irq, interrupts_db);

View file

@ -249,7 +249,7 @@ static void dump_object_tree(void)
for_each_object(numa_nodes, dump_numa_node_info, NULL);
}
static void force_rebalance_irq(struct irq_info *info, void *data __attribute__((unused)))
void force_rebalance_irq(struct irq_info *info, void *data __attribute__((unused)))
{
if (info->level == BALANCE_NONE)
return;

View file

@ -40,8 +40,11 @@ extern GList* collect_full_irq_list();
extern void parse_proc_stat(void);
extern void set_interrupt_count(int number, uint64_t count);
extern void set_msi_interrupt_numa(int number);
extern void init_irq_class_and_type(char *savedline, struct irq_info *info, int irq);
extern int proc_irq_hotplug(char *line, int irq, struct irq_info **pinfo);
extern GList *rebalance_irq_list;
extern void force_rebalance_irq(struct irq_info *info, void *data __attribute__((unused)));
void update_migration_status(void);
void dump_workloads(void);
@ -52,7 +55,6 @@ void dump_tree(void);
void activate_mappings(void);
void clear_cpu_tree(void);
void free_cpu_topo(gpointer data);
/*===================NEW BALANCER FUNCTIONS============================*/
/*

View file

@ -145,16 +145,59 @@ static void guess_arm_irq_hints(char *name, struct irq_info *info)
}
#endif
void init_irq_class_and_type(char *savedline, struct irq_info *info, int irq)
{
char *irq_name = NULL;
char *irq_mod = NULL;
char *savedptr = NULL;
char *last_token = NULL;
char *p = NULL;
int is_xen_dyn = 0;
#ifdef AARCH64
char *tmp = NULL;
#endif
irq_name = strtok_r(savedline, " ", &savedptr);
if (strstr(irq_name, "xen-dyn") != NULL)
is_xen_dyn = 1;
last_token = strtok_r(NULL, " ", &savedptr);
while ((p = strtok_r(NULL, " ", &savedptr))) {
irq_name = last_token;
if (strstr(irq_name, "xen-dyn") != NULL)
is_xen_dyn = 1;
last_token = p;
}
#ifdef AARCH64
irq_name = last_token;
tmp = strchr(irq_name, '\n');
if (tmp)
*tmp = 0;
#endif
irq_mod = last_token;
info->irq = irq;
if (strstr(irq_name, "-event") != NULL && is_xen_dyn == 1) {
info->type = IRQ_TYPE_VIRT_EVENT;
info->class = IRQ_VIRT_EVENT;
} else {
#ifdef AARCH64
guess_arm_irq_hints(irq_name, info);
#else
info->type = IRQ_TYPE_LEGACY;
info->class = IRQ_OTHER;
#endif
}
info->numa_node = get_numa_node(0);
info->name = strdup(irq_mod);
}
GList* collect_full_irq_list()
{
GList *tmp_list = NULL;
FILE *file;
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)
@ -169,7 +212,6 @@ GList* collect_full_irq_list()
while (!feof(file)) {
int number;
int is_xen_dyn = 0;
struct irq_info *info;
char *c;
char *savedline = NULL;
@ -191,44 +233,12 @@ GList* collect_full_irq_list()
savedline = strdup(line);
if (!savedline)
break;
irq_name = strtok_r(savedline, " ", &savedptr);
if (strstr(irq_name, "xen-dyn") != NULL)
is_xen_dyn = 1;
last_token = strtok_r(NULL, " ", &savedptr);
while ((p = strtok_r(NULL, " ", &savedptr))) {
irq_name = last_token;
if (strstr(irq_name, "xen-dyn") != NULL)
is_xen_dyn = 1;
last_token = p;
}
#ifdef AARCH64
/* Of course the formatting for /proc/interrupts is different on different arches */
irq_name = last_token;
tmp = strchr(irq_name, '\n');
if (tmp)
*tmp = 0;
#endif
irq_mod = last_token;
*c = 0;
number = strtoul(line, NULL, 10);
info = calloc(1, sizeof(struct irq_info));
if (info) {
info->irq = number;
if (strstr(irq_name, "-event") != NULL && is_xen_dyn == 1) {
info->type = IRQ_TYPE_VIRT_EVENT;
info->class = IRQ_VIRT_EVENT;
} else {
#ifdef AARCH64
guess_arm_irq_hints(irq_name, info);
#else
info->type = IRQ_TYPE_LEGACY;
info->class = IRQ_OTHER;
#endif
}
info->name = strdup(irq_mod);
init_irq_class_and_type(savedline, info, number);
tmp_list = g_list_append(tmp_list, info);
}
free(savedline);
@ -238,11 +248,13 @@ GList* collect_full_irq_list()
return tmp_list;
}
void parse_proc_interrupts(void)
{
FILE *file;
char *line = NULL;
size_t size = 0;
int ret;
file = fopen("/proc/interrupts", "r");
if (!file)
@ -261,6 +273,7 @@ void parse_proc_interrupts(void)
uint64_t count;
char *c, *c2;
struct irq_info *info;
char *savedline = NULL;
if (getline(&line, &size, file)<=0)
break;
@ -280,15 +293,24 @@ void parse_proc_interrupts(void)
if (!c)
continue;
savedline = strdup(line);
if (!savedline)
break;
*c = 0;
c++;
number = strtoul(line, NULL, 10);
info = get_irq_info(number);
if (!info) {
need_rescan = 1;
break;
ret = proc_irq_hotplug(savedline, number, &info);
if (ret < 0) {
/* hotplug fail, need to rescan */
need_rescan = 1;
free(savedline);
break;
}
}
free(savedline);
count = 0;
cpunr = 0;
@ -316,7 +338,7 @@ void parse_proc_interrupts(void)
break;
}
info->last_irq_count = info->irq_count;
info->last_irq_count = info->irq_count;
info->irq_count = count;
/* is interrupt MSI based? */