diff options
| author | Timo Teräs <timo.teras@iki.fi> | 2015-11-05 18:54:55 +0100 |
|---|---|---|
| committer | Denys Vlasenko <vda.linux@googlemail.com> | 2015-11-05 18:54:55 +0100 |
| commit | 48dc80bbba994eee24ed94ae4532a1cce76d7cb7 (patch) | |
| tree | 051e7aacf5538ffc07310bb4261a693a047311d2 /modutils | |
| parent | 34adecc2b049f6941c5e075ffb58fe2183823da3 (diff) | |
| download | busybox-w32-48dc80bbba994eee24ed94ae4532a1cce76d7cb7.tar.gz busybox-w32-48dc80bbba994eee24ed94ae4532a1cce76d7cb7.tar.bz2 busybox-w32-48dc80bbba994eee24ed94ae4532a1cce76d7cb7.zip | |
modutils: merge module_entry and module_info to common
This merges the in-memory module info structures of modprobe
and depmod. This allows sharing hashing by modulename code
improving depmod runtime with almost factor of 2x.
function old new delta
get_or_add_modentry - 17 +17
do_modprobe 590 601 +11
moddb_get_or_create - 10 +10
load_modules_dep 195 205 +10
moddb_get - 7 +7
add_probe 81 78 -3
modprobe_main 721 714 -7
depmod_main 553 543 -10
config_file_action 434 421 -13
helper_get_module 160 144 -16
parse_module 343 320 -23
order_dep_list 105 82 -23
------------------------------------------------------------------------------
(add/remove: 3/0 grow/shrink: 2/7 up/down: 55/-95) Total: -40 bytes
Signed-off-by: Timo Teräs <timo.teras@iki.fi>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'modutils')
| -rw-r--r-- | modutils/depmod.c | 86 | ||||
| -rw-r--r-- | modutils/modprobe.c | 66 | ||||
| -rw-r--r-- | modutils/modutils.c | 51 | ||||
| -rw-r--r-- | modutils/modutils.h | 30 |
4 files changed, 113 insertions, 120 deletions
diff --git a/modutils/depmod.c b/modutils/depmod.c index 9713aef92..e5f0e3d2b 100644 --- a/modutils/depmod.c +++ b/modutils/depmod.c | |||
| @@ -21,21 +21,13 @@ | |||
| 21 | * for each depends, look through our list of full paths and emit if found | 21 | * for each depends, look through our list of full paths and emit if found |
| 22 | */ | 22 | */ |
| 23 | 23 | ||
| 24 | typedef struct module_info { | ||
| 25 | struct module_info *next; | ||
| 26 | char *name, *modname; | ||
| 27 | llist_t *dependencies; | ||
| 28 | llist_t *aliases; | ||
| 29 | llist_t *symbols; | ||
| 30 | struct module_info *dnext, *dprev; | ||
| 31 | } module_info; | ||
| 32 | |||
| 33 | static int FAST_FUNC parse_module(const char *fname, struct stat *sb UNUSED_PARAM, | 24 | static int FAST_FUNC parse_module(const char *fname, struct stat *sb UNUSED_PARAM, |
| 34 | void *data, int depth UNUSED_PARAM) | 25 | void *data, int depth UNUSED_PARAM) |
| 35 | { | 26 | { |
| 36 | module_info **first = (module_info **) data; | 27 | module_db *modules = data; |
| 37 | char *image, *ptr; | 28 | char *image, *ptr; |
| 38 | module_info *info; | 29 | module_entry *e; |
| 30 | |||
| 39 | /* Arbitrary. Was sb->st_size, but that breaks .gz etc */ | 31 | /* Arbitrary. Was sb->st_size, but that breaks .gz etc */ |
| 40 | size_t len = (64*1024*1024 - 4096); | 32 | size_t len = (64*1024*1024 - 4096); |
| 41 | 33 | ||
| @@ -43,17 +35,10 @@ static int FAST_FUNC parse_module(const char *fname, struct stat *sb UNUSED_PARA | |||
| 43 | return TRUE; | 35 | return TRUE; |
| 44 | 36 | ||
| 45 | image = xmalloc_open_zipped_read_close(fname, &len); | 37 | image = xmalloc_open_zipped_read_close(fname, &len); |
| 46 | info = xzalloc(sizeof(*info)); | ||
| 47 | 38 | ||
| 48 | info->next = *first; | 39 | e = moddb_get_or_create(modules, bb_get_last_path_component_nostrip(fname)); |
| 49 | *first = info; | 40 | e->name = xstrdup(fname + 2); /* skip "./" */ |
| 50 | 41 | ||
| 51 | info->dnext = info->dprev = info; | ||
| 52 | info->name = xstrdup(fname + 2); /* skip "./" */ | ||
| 53 | info->modname = filename2modname( | ||
| 54 | bb_get_last_path_component_nostrip(fname), | ||
| 55 | NULL | ||
| 56 | ); | ||
| 57 | for (ptr = image; ptr < image + len - 10; ptr++) { | 42 | for (ptr = image; ptr < image + len - 10; ptr++) { |
| 58 | if (is_prefixed_with(ptr, "depends=")) { | 43 | if (is_prefixed_with(ptr, "depends=")) { |
| 59 | char *u; | 44 | char *u; |
| @@ -62,11 +47,11 @@ static int FAST_FUNC parse_module(const char *fname, struct stat *sb UNUSED_PARA | |||
| 62 | for (u = ptr; *u; u++) | 47 | for (u = ptr; *u; u++) |
| 63 | if (*u == '-') | 48 | if (*u == '-') |
| 64 | *u = '_'; | 49 | *u = '_'; |
| 65 | ptr += string_to_llist(ptr, &info->dependencies, ","); | 50 | ptr += string_to_llist(ptr, &e->deps, ","); |
| 66 | } else if (ENABLE_FEATURE_MODUTILS_ALIAS | 51 | } else if (ENABLE_FEATURE_MODUTILS_ALIAS |
| 67 | && is_prefixed_with(ptr, "alias=") | 52 | && is_prefixed_with(ptr, "alias=") |
| 68 | ) { | 53 | ) { |
| 69 | llist_add_to(&info->aliases, xstrdup(ptr + 6)); | 54 | llist_add_to(&e->aliases, xstrdup(ptr + 6)); |
| 70 | ptr += strlen(ptr); | 55 | ptr += strlen(ptr); |
| 71 | } else if (ENABLE_FEATURE_MODUTILS_SYMBOLS | 56 | } else if (ENABLE_FEATURE_MODUTILS_SYMBOLS |
| 72 | && is_prefixed_with(ptr, "__ksymtab_") | 57 | && is_prefixed_with(ptr, "__ksymtab_") |
| @@ -77,7 +62,7 @@ static int FAST_FUNC parse_module(const char *fname, struct stat *sb UNUSED_PARA | |||
| 77 | ) { | 62 | ) { |
| 78 | continue; | 63 | continue; |
| 79 | } | 64 | } |
| 80 | llist_add_to(&info->symbols, xstrdup(ptr)); | 65 | llist_add_to(&e->symbols, xstrdup(ptr)); |
| 81 | ptr += strlen(ptr); | 66 | ptr += strlen(ptr); |
| 82 | } | 67 | } |
| 83 | } | 68 | } |
| @@ -86,24 +71,13 @@ static int FAST_FUNC parse_module(const char *fname, struct stat *sb UNUSED_PARA | |||
| 86 | return TRUE; | 71 | return TRUE; |
| 87 | } | 72 | } |
| 88 | 73 | ||
| 89 | static module_info *find_module(module_info *modules, const char *modname) | 74 | static void order_dep_list(module_db *modules, module_entry *start, llist_t *add) |
| 90 | { | ||
| 91 | module_info *m; | ||
| 92 | |||
| 93 | for (m = modules; m != NULL; m = m->next) | ||
| 94 | if (strcmp(m->modname, modname) == 0) | ||
| 95 | return m; | ||
| 96 | return NULL; | ||
| 97 | } | ||
| 98 | |||
| 99 | static void order_dep_list(module_info *modules, module_info *start, | ||
| 100 | llist_t *add) | ||
| 101 | { | 75 | { |
| 102 | module_info *m; | 76 | module_entry *m; |
| 103 | llist_t *n; | 77 | llist_t *n; |
| 104 | 78 | ||
| 105 | for (n = add; n != NULL; n = n->link) { | 79 | for (n = add; n != NULL; n = n->link) { |
| 106 | m = find_module(modules, n->data); | 80 | m = moddb_get(modules, n->data); |
| 107 | if (m == NULL) | 81 | if (m == NULL) |
| 108 | continue; | 82 | continue; |
| 109 | 83 | ||
| @@ -118,7 +92,7 @@ static void order_dep_list(module_info *modules, module_info *start, | |||
| 118 | start->dprev = m; | 92 | start->dprev = m; |
| 119 | 93 | ||
| 120 | /* recurse */ | 94 | /* recurse */ |
| 121 | order_dep_list(modules, start, m->dependencies); | 95 | order_dep_list(modules, start, m->deps); |
| 122 | } | 96 | } |
| 123 | } | 97 | } |
| 124 | 98 | ||
| @@ -184,10 +158,12 @@ enum { | |||
| 184 | int depmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 158 | int depmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
| 185 | int depmod_main(int argc UNUSED_PARAM, char **argv) | 159 | int depmod_main(int argc UNUSED_PARAM, char **argv) |
| 186 | { | 160 | { |
| 187 | module_info *modules, *m, *dep; | 161 | module_db modules; |
| 162 | module_entry *m, *dep; | ||
| 188 | const char *moddir_base = "/"; | 163 | const char *moddir_base = "/"; |
| 189 | char *moddir, *version; | 164 | char *moddir, *version; |
| 190 | struct utsname uts; | 165 | struct utsname uts; |
| 166 | unsigned i; | ||
| 191 | int tmp; | 167 | int tmp; |
| 192 | 168 | ||
| 193 | getopt32(argv, "aAb:eF:nruqC:", &moddir_base, NULL, NULL); | 169 | getopt32(argv, "aAb:eF:nruqC:", &moddir_base, NULL, NULL); |
| @@ -211,7 +187,7 @@ int depmod_main(int argc UNUSED_PARAM, char **argv) | |||
| 211 | free(moddir); | 187 | free(moddir); |
| 212 | 188 | ||
| 213 | /* Scan modules */ | 189 | /* Scan modules */ |
| 214 | modules = NULL; | 190 | memset(&modules, 0, sizeof(modules)); |
| 215 | if (*argv) { | 191 | if (*argv) { |
| 216 | do { | 192 | do { |
| 217 | parse_module(*argv, /*sb (unused):*/ NULL, &modules, 0); | 193 | parse_module(*argv, /*sb (unused):*/ NULL, &modules, 0); |
| @@ -224,10 +200,11 @@ int depmod_main(int argc UNUSED_PARAM, char **argv) | |||
| 224 | /* Generate dependency and alias files */ | 200 | /* Generate dependency and alias files */ |
| 225 | if (!(option_mask32 & OPT_n)) | 201 | if (!(option_mask32 & OPT_n)) |
| 226 | xfreopen_write(CONFIG_DEFAULT_DEPMOD_FILE, stdout); | 202 | xfreopen_write(CONFIG_DEFAULT_DEPMOD_FILE, stdout); |
| 227 | for (m = modules; m != NULL; m = m->next) { | 203 | |
| 204 | moddb_foreach_module(&modules, m, i) { | ||
| 228 | printf("%s:", m->name); | 205 | printf("%s:", m->name); |
| 229 | 206 | ||
| 230 | order_dep_list(modules, m, m->dependencies); | 207 | order_dep_list(&modules, m, m->deps); |
| 231 | while (m->dnext != m) { | 208 | while (m->dnext != m) { |
| 232 | dep = m->dnext; | 209 | dep = m->dnext; |
| 233 | printf(" %s", dep->name); | 210 | printf(" %s", dep->name); |
| @@ -243,10 +220,7 @@ int depmod_main(int argc UNUSED_PARAM, char **argv) | |||
| 243 | #if ENABLE_FEATURE_MODUTILS_ALIAS | 220 | #if ENABLE_FEATURE_MODUTILS_ALIAS |
| 244 | if (!(option_mask32 & OPT_n)) | 221 | if (!(option_mask32 & OPT_n)) |
| 245 | xfreopen_write("modules.alias", stdout); | 222 | xfreopen_write("modules.alias", stdout); |
| 246 | for (m = modules; m != NULL; m = m->next) { | 223 | moddb_foreach_module(&modules, m, i) { |
| 247 | char modname[MODULE_NAME_LEN]; | ||
| 248 | const char *fname = bb_basename(m->name); | ||
| 249 | filename2modname(fname, modname); | ||
| 250 | while (m->aliases) { | 224 | while (m->aliases) { |
| 251 | /* | 225 | /* |
| 252 | * Last word used to be a basename | 226 | * Last word used to be a basename |
| @@ -256,34 +230,24 @@ int depmod_main(int argc UNUSED_PARAM, char **argv) | |||
| 256 | */ | 230 | */ |
| 257 | printf("alias %s %s\n", | 231 | printf("alias %s %s\n", |
| 258 | (char*)llist_pop(&m->aliases), | 232 | (char*)llist_pop(&m->aliases), |
| 259 | modname); | 233 | m->modname); |
| 260 | } | 234 | } |
| 261 | } | 235 | } |
| 262 | #endif | 236 | #endif |
| 263 | #if ENABLE_FEATURE_MODUTILS_SYMBOLS | 237 | #if ENABLE_FEATURE_MODUTILS_SYMBOLS |
| 264 | if (!(option_mask32 & OPT_n)) | 238 | if (!(option_mask32 & OPT_n)) |
| 265 | xfreopen_write("modules.symbols", stdout); | 239 | xfreopen_write("modules.symbols", stdout); |
| 266 | for (m = modules; m != NULL; m = m->next) { | 240 | moddb_foreach_module(&modules, m, i) { |
| 267 | char modname[MODULE_NAME_LEN]; | ||
| 268 | const char *fname = bb_basename(m->name); | ||
| 269 | filename2modname(fname, modname); | ||
| 270 | while (m->symbols) { | 241 | while (m->symbols) { |
| 271 | printf("alias symbol:%s %s\n", | 242 | printf("alias symbol:%s %s\n", |
| 272 | (char*)llist_pop(&m->symbols), | 243 | (char*)llist_pop(&m->symbols), |
| 273 | modname); | 244 | m->modname); |
| 274 | } | 245 | } |
| 275 | } | 246 | } |
| 276 | #endif | 247 | #endif |
| 277 | 248 | ||
| 278 | if (ENABLE_FEATURE_CLEAN_UP) { | 249 | if (ENABLE_FEATURE_CLEAN_UP) |
| 279 | while (modules) { | 250 | moddb_free(&modules); |
| 280 | module_info *old = modules; | ||
| 281 | modules = modules->next; | ||
| 282 | free(old->name); | ||
| 283 | free(old->modname); | ||
| 284 | free(old); | ||
| 285 | } | ||
| 286 | } | ||
| 287 | 251 | ||
| 288 | return EXIT_SUCCESS; | 252 | return EXIT_SUCCESS; |
| 289 | } | 253 | } |
diff --git a/modutils/modprobe.c b/modutils/modprobe.c index 05bf02cf8..ec490b74d 100644 --- a/modutils/modprobe.c +++ b/modutils/modprobe.c | |||
| @@ -150,19 +150,6 @@ static const char modprobe_longopts[] ALIGN1 = | |||
| 150 | #define MODULE_FLAG_FOUND_IN_MODDEP 0x0004 | 150 | #define MODULE_FLAG_FOUND_IN_MODDEP 0x0004 |
| 151 | #define MODULE_FLAG_BLACKLISTED 0x0008 | 151 | #define MODULE_FLAG_BLACKLISTED 0x0008 |
| 152 | 152 | ||
| 153 | struct module_entry { /* I'll call it ME. */ | ||
| 154 | unsigned flags; | ||
| 155 | char *modname; /* stripped of /path/, .ext and s/-/_/g */ | ||
| 156 | const char *probed_name; /* verbatim as seen on cmdline */ | ||
| 157 | char *options; /* options from config files */ | ||
| 158 | llist_t *realnames; /* strings. if this module is an alias, */ | ||
| 159 | /* real module name is one of these. */ | ||
| 160 | //Can there really be more than one? Example from real kernel? | ||
| 161 | llist_t *deps; /* strings. modules we depend on */ | ||
| 162 | }; | ||
| 163 | |||
| 164 | #define DB_HASH_SIZE 256 | ||
| 165 | |||
| 166 | struct globals { | 153 | struct globals { |
| 167 | llist_t *probes; /* MEs of module(s) requested on cmdline */ | 154 | llist_t *probes; /* MEs of module(s) requested on cmdline */ |
| 168 | char *cmdline_mopts; /* module options from cmdline */ | 155 | char *cmdline_mopts; /* module options from cmdline */ |
| @@ -170,7 +157,7 @@ struct globals { | |||
| 170 | /* bool. "Did we have 'symbol:FOO' requested on cmdline?" */ | 157 | /* bool. "Did we have 'symbol:FOO' requested on cmdline?" */ |
| 171 | smallint need_symbols; | 158 | smallint need_symbols; |
| 172 | struct utsname uts; | 159 | struct utsname uts; |
| 173 | llist_t *db[DB_HASH_SIZE]; /* MEs of all modules ever seen (caching for speed) */ | 160 | module_db db; |
| 174 | } FIX_ALIASING; | 161 | } FIX_ALIASING; |
| 175 | #define G (*ptr_to_globals) | 162 | #define G (*ptr_to_globals) |
| 176 | #define INIT_G() do { \ | 163 | #define INIT_G() do { \ |
| @@ -195,51 +182,9 @@ static char *gather_options_str(char *opts, const char *append) | |||
| 195 | return opts; | 182 | return opts; |
| 196 | } | 183 | } |
| 197 | 184 | ||
| 198 | /* These three functions called many times, optimizing for speed. | 185 | static struct module_entry *get_or_add_modentry(const char *module) |
| 199 | * Users reported minute-long delays when they runn iptables repeatedly | ||
| 200 | * (iptables use modprobe to install needed kernel modules). | ||
| 201 | */ | ||
| 202 | static struct module_entry *helper_get_module(const char *module, int create) | ||
| 203 | { | ||
| 204 | char modname[MODULE_NAME_LEN]; | ||
| 205 | struct module_entry *e; | ||
| 206 | llist_t *l; | ||
| 207 | unsigned i; | ||
| 208 | unsigned hash; | ||
| 209 | |||
| 210 | filename2modname(module, modname); | ||
| 211 | |||
| 212 | hash = 0; | ||
| 213 | for (i = 0; modname[i]; i++) | ||
| 214 | hash = ((hash << 5) + hash) + modname[i]; | ||
| 215 | hash %= DB_HASH_SIZE; | ||
| 216 | |||
| 217 | for (l = G.db[hash]; l; l = l->link) { | ||
| 218 | e = (struct module_entry *) l->data; | ||
| 219 | if (strcmp(e->modname, modname) == 0) | ||
| 220 | return e; | ||
| 221 | } | ||
| 222 | if (!create) | ||
| 223 | return NULL; | ||
| 224 | |||
| 225 | e = xzalloc(sizeof(*e)); | ||
| 226 | e->modname = xstrdup(modname); | ||
| 227 | llist_add_to(&G.db[hash], e); | ||
| 228 | |||
| 229 | return e; | ||
| 230 | } | ||
| 231 | static ALWAYS_INLINE struct module_entry *get_or_add_modentry(const char *module) | ||
| 232 | { | 186 | { |
| 233 | return helper_get_module(module, 1); | 187 | return moddb_get_or_create(&G.db, module); |
| 234 | } | ||
| 235 | /* So far this function always gets a module pathname, never an alias name. | ||
| 236 | * The crucial difference is that pathname needs dirname stripping, | ||
| 237 | * while alias name must NOT do it! | ||
| 238 | * Testcase where dirname stripping is likely to go wrong: "modprobe devname:snd/timer" | ||
| 239 | */ | ||
| 240 | static ALWAYS_INLINE struct module_entry *get_modentry(const char *pathname) | ||
| 241 | { | ||
| 242 | return helper_get_module(bb_get_last_path_component_nostrip(pathname), 0); | ||
| 243 | } | 188 | } |
| 244 | 189 | ||
| 245 | static void add_probe(const char *name) | 190 | static void add_probe(const char *name) |
| @@ -536,7 +481,7 @@ static void load_modules_dep(void) | |||
| 536 | continue; | 481 | continue; |
| 537 | *colon = '\0'; | 482 | *colon = '\0'; |
| 538 | 483 | ||
| 539 | m = get_modentry(tokens[0]); | 484 | m = moddb_get(&G.db, bb_get_last_path_component_nostrip(tokens[0])); |
| 540 | if (m == NULL) | 485 | if (m == NULL) |
| 541 | continue; | 486 | continue; |
| 542 | 487 | ||
| @@ -697,5 +642,8 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv) | |||
| 697 | } while (me->realnames != NULL); | 642 | } while (me->realnames != NULL); |
| 698 | } | 643 | } |
| 699 | 644 | ||
| 645 | if (ENABLE_FEATURE_CLEAN_UP) | ||
| 646 | moddb_free(&G.db); | ||
| 647 | |||
| 700 | return (rc != 0); | 648 | return (rc != 0); |
| 701 | } | 649 | } |
diff --git a/modutils/modutils.c b/modutils/modutils.c index ef4134af5..8e9eef72d 100644 --- a/modutils/modutils.c +++ b/modutils/modutils.c | |||
| @@ -16,6 +16,57 @@ extern int delete_module(const char *module, unsigned int flags); | |||
| 16 | # define delete_module(mod, flags) syscall(__NR_delete_module, mod, flags) | 16 | # define delete_module(mod, flags) syscall(__NR_delete_module, mod, flags) |
| 17 | #endif | 17 | #endif |
| 18 | 18 | ||
| 19 | static module_entry *helper_get_module(module_db *db, const char *module, int create) | ||
| 20 | { | ||
| 21 | char modname[MODULE_NAME_LEN]; | ||
| 22 | struct module_entry *e; | ||
| 23 | unsigned i, hash; | ||
| 24 | |||
| 25 | filename2modname(module, modname); | ||
| 26 | |||
| 27 | hash = 0; | ||
| 28 | for (i = 0; modname[i]; i++) | ||
| 29 | hash = ((hash << 5) + hash) + modname[i]; | ||
| 30 | hash %= MODULE_HASH_SIZE; | ||
| 31 | |||
| 32 | for (e = db->buckets[hash]; e; e = e->next) | ||
| 33 | if (strcmp(e->modname, modname) == 0) | ||
| 34 | return e; | ||
| 35 | if (!create) | ||
| 36 | return NULL; | ||
| 37 | |||
| 38 | e = xzalloc(sizeof(*e)); | ||
| 39 | e->modname = xstrdup(modname); | ||
| 40 | e->next = db->buckets[hash]; | ||
| 41 | db->buckets[hash] = e; | ||
| 42 | e->dnext = e->dprev = e; | ||
| 43 | |||
| 44 | return e; | ||
| 45 | } | ||
| 46 | module_entry* FAST_FUNC moddb_get(module_db *db, const char *module) | ||
| 47 | { | ||
| 48 | return helper_get_module(db, module, 0); | ||
| 49 | } | ||
| 50 | module_entry* FAST_FUNC moddb_get_or_create(module_db *db, const char *module) | ||
| 51 | { | ||
| 52 | return helper_get_module(db, module, 1); | ||
| 53 | } | ||
| 54 | |||
| 55 | void FAST_FUNC moddb_free(module_db *db) | ||
| 56 | { | ||
| 57 | module_entry *e, *n; | ||
| 58 | unsigned i; | ||
| 59 | |||
| 60 | for (i = 0; i < MODULE_HASH_SIZE; i++) { | ||
| 61 | for (e = db->buckets[i]; e; e = n) { | ||
| 62 | n = e->next; | ||
| 63 | free(e->name); | ||
| 64 | free(e->modname); | ||
| 65 | free(e); | ||
| 66 | } | ||
| 67 | } | ||
| 68 | } | ||
| 69 | |||
| 19 | void FAST_FUNC replace(char *s, char what, char with) | 70 | void FAST_FUNC replace(char *s, char what, char with) |
| 20 | { | 71 | { |
| 21 | while (*s) { | 72 | while (*s) { |
diff --git a/modutils/modutils.h b/modutils/modutils.h index 5f059c716..2cbd1448a 100644 --- a/modutils/modutils.h +++ b/modutils/modutils.h | |||
| @@ -16,6 +16,36 @@ PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN | |||
| 16 | /* linux/include/linux/module.h has 64, but this is also used | 16 | /* linux/include/linux/module.h has 64, but this is also used |
| 17 | * internally for the maximum alias name length, which can be quite long */ | 17 | * internally for the maximum alias name length, which can be quite long */ |
| 18 | #define MODULE_NAME_LEN 256 | 18 | #define MODULE_NAME_LEN 256 |
| 19 | #define MODULE_HASH_SIZE 256 | ||
| 20 | |||
| 21 | typedef struct module_entry { | ||
| 22 | struct module_entry *next; | ||
| 23 | char *name, *modname; | ||
| 24 | llist_t *deps; | ||
| 25 | IF_MODPROBE( | ||
| 26 | llist_t *realnames; | ||
| 27 | unsigned flags; | ||
| 28 | const char *probed_name; /* verbatim as seen on cmdline */ | ||
| 29 | char *options; /* options from config files */ | ||
| 30 | ) | ||
| 31 | IF_DEPMOD( | ||
| 32 | llist_t *aliases; | ||
| 33 | llist_t *symbols; | ||
| 34 | struct module_entry *dnext, *dprev; | ||
| 35 | ) | ||
| 36 | } module_entry; | ||
| 37 | |||
| 38 | typedef struct module_db { | ||
| 39 | module_entry *buckets[MODULE_HASH_SIZE]; | ||
| 40 | } module_db; | ||
| 41 | |||
| 42 | #define moddb_foreach_module(db, module, index) \ | ||
| 43 | for ((index) = 0; (index) < MODULE_HASH_SIZE; (index)++) \ | ||
| 44 | for (module = (db)->buckets[index]; module; module = module->next) | ||
| 45 | |||
| 46 | module_entry *moddb_get(module_db *db, const char *s) FAST_FUNC; | ||
| 47 | module_entry *moddb_get_or_create(module_db *db, const char *s) FAST_FUNC; | ||
| 48 | void moddb_free(module_db *db) FAST_FUNC; | ||
| 19 | 49 | ||
| 20 | void replace(char *s, char what, char with) FAST_FUNC; | 50 | void replace(char *s, char what, char with) FAST_FUNC; |
| 21 | char *replace_underscores(char *s) FAST_FUNC; | 51 | char *replace_underscores(char *s) FAST_FUNC; |
