#include #include #include #include #include #include #include #include #include #include "subcmd-util.h" #include "help.h" #include "exec-cmd.h" void add_cmdname(struct cmdnames *cmds, const char *name, size_t len) { struct cmdname *ent = malloc(sizeof(*ent) + len + 1); ent->len = len; memcpy(ent->name, name, len); ent->name[len] = 0; ALLOC_GROW(cmds->names, cmds->cnt + 1, cmds->alloc); cmds->names[cmds->cnt++] = ent; } void clean_cmdnames(struct cmdnames *cmds) { unsigned int i; for (i = 0; i < cmds->cnt; ++i) zfree(&cmds->names[i]); zfree(&cmds->names); cmds->cnt = 0; cmds->alloc = 0; } int cmdname_compare(const void *a_, const void *b_) { struct cmdname *a = *(struct cmdname **)a_; struct cmdname *b = *(struct cmdname **)b_; return strcmp(a->name, b->name); } void uniq(struct cmdnames *cmds) { unsigned int i, j; if (!cmds->cnt) return; for (i = j = 1; i < cmds->cnt; i++) if (strcmp(cmds->names[i]->name, cmds->names[i-1]->name)) cmds->names[j++] = cmds->names[i]; cmds->cnt = j; } void exclude_cmds(struct cmdnames *cmds, struct cmdnames *excludes) { size_t ci, cj, ei; int cmp; ci = cj = ei = 0; while (ci < cmds->cnt && ei < excludes->cnt) { cmp = strcmp(cmds->names[ci]->name, excludes->names[ei]->name); if (cmp < 0) cmds->names[cj++] = cmds->names[ci++]; else if (cmp == 0) ci++, ei++; else if (cmp > 0) ei++; } while (ci < cmds->cnt) cmds->names[cj++] = cmds->names[ci++]; cmds->cnt = cj; } static void get_term_dimensions(struct winsize *ws) { char *s = getenv("LINES"); if (s != NULL) { ws->ws_row = atoi(s); s = getenv("COLUMNS"); if (s != NULL) { ws->ws_col = atoi(s); if (ws->ws_row && ws->ws_col) return; } } #ifdef TIOCGWINSZ if (ioctl(1, TIOCGWINSZ, ws) == 0 && ws->ws_row && ws->ws_col) return; #endif ws->ws_row = 25; ws->ws_col = 80; } static void pretty_print_string_list(struct cmdnames *cmds, int longest) { int cols = 1, rows; int space = longest + 1; /* min 1 SP between words */ struct winsize win; int max_cols; int i, j; get_term_dimensions(&win); max_cols = win.ws_col - 1; /* don't print *on* the edge */ if (space < max_cols) cols = max_cols / space; rows = (cmds->cnt + cols - 1) / cols; for (i = 0; i < rows; i++) { printf(" "); for (j = 0; j < cols; j++) { unsigned int n = j * rows + i; unsigned int size = space; if (n >= cmds->cnt) break; if (j == cols-1 || n + rows >= cmds->cnt) size = 1; printf("%-*s", size, cmds->names[n]->name); } putchar('\n'); } } static int is_executable(const char *name) { struct stat st; if (stat(name, &st) || /* stat, not lstat */ !S_ISREG(st.st_mode)) return 0; return st.st_mode & S_IXUSR; } static int has_extension(const char *filename, const char *ext) { size_t len = strlen(filename); size_t extlen = strlen(ext); return len > extlen && !memcmp(filename + len - extlen, ext, extlen); } static void list_commands_in_dir(struct cmdnames *cmds, const char *path, const char *prefix) { int prefix_len; DIR *dir = opendir(path); struct dirent *de; char *buf = NULL; if (!dir) return; if (!prefix) prefix = "perf-"; prefix_len = strlen(prefix); astrcatf(&buf, "%s/", path); while ((de = readdir(dir)) != NULL) { int entlen; if (prefixcmp(de->d_name, prefix)) continue; astrcat(&buf, de->d_name); if (!is_executable(buf)) continue; entlen = strlen(de->d_name) - prefix_len; if (has_extension(de->d_name, ".exe")) entlen -= 4; add_cmdname(cmds, de->d_name + prefix_len, entlen); } closedir(dir); free(buf); } void load_command_list(const char *prefix, struct cmdnames *main_cmds, struct cmdnames *other_cmds) { const char *env_path = getenv("PATH"); char *exec_path = get_argv_exec_path(); if (exec_path) { list_commands_in_dir(main_cmds, exec_path, prefix); qsort(main_cmds->names, main_cmds->cnt, sizeof(*main_cmds->names), cmdname_compare); uniq(main_cmds); } if (env_path) { char *paths, *path, *colon; path = paths = strdup(env_path); while (1) { if ((colon = strchr(path, ':'))) *colon = 0; if (!exec_path || strcmp(path, exec_path)) list_commands_in_dir(other_cmds, path, prefix); if (!colon) break; path = colon + 1; } free(paths); qsort(other_cmds->names, other_cmds->cnt, sizeof(*other_cmds->names), cmdname_compare); uniq(other_cmds); } free(exec_path); exclude_cmds(other_cmds, main_cmds); } void list_commands(const char *title, struct cmdnames *main_cmds, struct cmdnames *other_cmds) { unsigned int i, longest = 0; for (i = 0; i < main_cmds->cnt; i++) if (longest < main_cmds->names[i]->len) longest = main_cmds->names[i]->len; for (i = 0; i < other_cmds->cnt; i++) if (longest < other_cmds->names[i]->len) longest = other_cmds->names[i]->len; if (main_cmds->cnt) { char *exec_path = get_argv_exec_path(); printf("available %s in '%s'\n", title, exec_path); printf("----------------"); mput_char('-', strlen(title) + strlen(exec_path)); putchar('\n'); pretty_print_string_list(main_cmds, longest); putchar('\n'); free(exec_path); } if (other_cmds->cnt) { printf("%s available from elsewhere on your $PATH\n", title); printf("---------------------------------------"); mput_char('-', strlen(title)); putchar('\n'); pretty_print_string_list(other_cmds, longest); putchar('\n'); } } int is_in_cmdlist(struct cmdnames *c, const char *s) { unsigned int i; for (i = 0; i < c->cnt; i++) if (!strcmp(s, c->names[i]->name)) return 1; return 0; } ecc0ae5b42828785b589f686725ff5bc3b9b25&id2=24c2503255d35c269b67162c397a1a1c1e02f6ce'>diff)
x86/mce: Make timer handling more robust
Erik reported that on a preproduction hardware a CMCI storm triggers the BUG_ON in add_timer_on(). The reason is that the per CPU MCE timer is started by the CMCI logic before the MCE CPU hotplug callback starts the timer with add_timer_on(). So the timer is already queued which triggers the BUG. Using add_timer_on() is pretty pointless in this code because the timer is strictlty per CPU, initialized as pinned and all operations which arm the timer happen on the CPU to which the timer belongs. Simplify the whole machinery by using mod_timer() instead of add_timer_on() which avoids the problem because mod_timer() can handle already queued timers. Use __start_timer() everywhere so the earliest armed expiry time is preserved. Reported-by: Erik Veijola <erik.veijola@intel.com> Tested-by: Borislav Petkov <bp@alien8.de> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Reviewed-by: Borislav Petkov <bp@alien8.de> Cc: Tony Luck <tony.luck@intel.com> Link: http://lkml.kernel.org/r/alpine.DEB.2.20.1701310936080.3457@nanos Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'net/batman-adv/tvlv.h')