History

modpost: refactor error handling and clarify error/fatal difference

We have 3 log functions. fatal() is special because it lets modpost bail out immediately. The difference between warn() and error() is the only prefix parts ("WARNING:" vs "ERROR:"). In my understanding, the expected handling of error() is to propagate the return code of the function to the exit code of modpost, as check_exports() etc. already does. This is a good manner in general because we should display as many error messages as possible in a single run of modpost. What is annoying about fatal() is that it kills modpost at the first error. People would need to run Kbuild again and again until they fix all errors. But, unfortunately, people tend to do: "This case should not be allowed. Let's replace warn() with fatal()." One of the reasons is probably it is tedious to manually hoist the error code to the main() function. This commit refactors error() so any single call for it automatically makes modpost return the error code. I also added comments in modpost.h for warn(), error(), and fatal(). Please use fatal() only when you have a strong reason to do so. For example: - Memory shortage (i.e. malloc() etc. has failed) - The ELF file is broken, and there is no point to continue parsing - Something really odd has happened For general coding errors, please use error().

Masahiro Yamada committed 5 years ago

Commit 0fd3fba1 parent bc72d722 files · +27 −29Browse files

Showing the changes to scripts (2 of 2 files). Show all

Unified · Split

2 files
  1. scripts/mod/modpost.c +14 −29
  2. scripts/mod/modpost.h +13 −0
scripts/mod/modpost.c+14−29
@@ -40,6 +40,8 @@ static int ignore_missing_files; · 39 unmodified lines
40/* If set to 1, only warn (instead of error) about missing ns imports */40/* If set to 1, only warn (instead of error) about missing ns imports */
41static int allow_missing_ns_imports;41static int allow_missing_ns_imports;
42 42
43static bool error_occurred;
44
43enum export {45enum export {
44 export_plain, export_unused, export_gpl,46 export_plain, export_unused, export_gpl,
45 export_unused_gpl, export_gpl_future, export_unknown47 export_unused_gpl, export_gpl_future, export_unknown
@@ -78,6 +80,8 @@ modpost_log(enum loglevel loglevel, const char *fmt, ...) · 32 unmodified lines
78 80
79 if (loglevel == LOG_FATAL)81 if (loglevel == LOG_FATAL)
80 exit(1);82 exit(1);
83 if (loglevel == LOG_ERROR)
84 error_occurred = true;
81}85}
82 86
83static inline bool strends(const char *str, const char *postfix)87static inline bool strends(const char *str, const char *postfix)
@@ -2174,22 +2178,18 @@ static void check_for_unused(enum export exp, const char *m, const char *s) · 2090 unmodified lines
2174 }2178 }
2175}2179}
2176 2180
2177static int check_exports(struct module *mod)2181static void check_exports(struct module *mod)
2178{2182{
2179 struct symbol *s, *exp;2183 struct symbol *s, *exp;
2180 int err = 0;
2181 2184
2182 for (s = mod->unres; s; s = s->next) {2185 for (s = mod->unres; s; s = s->next) {
2183 const char *basename;2186 const char *basename;
2184 exp = find_symbol(s->name);2187 exp = find_symbol(s->name);
2185 if (!exp || exp->module == mod) {2188 if (!exp || exp->module == mod) {
2186 if (have_vmlinux && !s->weak) {2189 if (have_vmlinux && !s->weak)
2187 modpost_log(warn_unresolved ? LOG_WARN : LOG_ERROR,2190 modpost_log(warn_unresolved ? LOG_WARN : LOG_ERROR,
2188 "\"%s\" [%s.ko] undefined!\n",2191 "\"%s\" [%s.ko] undefined!\n",
2189 s->name, mod->name);2192 s->name, mod->name);
2190 if (!warn_unresolved)
2191 err = 1;
2192 }
2193 continue;2193 continue;
2194 }2194 }
2195 basename = strrchr(mod->name, '/');2195 basename = strrchr(mod->name, '/');
@@ -2203,8 +2203,6 @@ static int check_exports(struct module *mod) · 7 unmodified lines
2203 modpost_log(allow_missing_ns_imports ? LOG_WARN : LOG_ERROR,2203 modpost_log(allow_missing_ns_imports ? LOG_WARN : LOG_ERROR,
2204 "module %s uses symbol %s from namespace %s, but does not import it.\n",2204 "module %s uses symbol %s from namespace %s, but does not import it.\n",
2205 basename, exp->name, exp->namespace);2205 basename, exp->name, exp->namespace);
2206 if (!allow_missing_ns_imports)
2207 err = 1;
2208 add_namespace(&mod->missing_namespaces, exp->namespace);2206 add_namespace(&mod->missing_namespaces, exp->namespace);
2209 }2207 }
2210 2208
@@ -2212,11 +2210,9 @@ static int check_exports(struct module *mod) · 1 unmodified line
2212 check_for_gpl_usage(exp->export, basename, exp->name);2210 check_for_gpl_usage(exp->export, basename, exp->name);
2213 check_for_unused(exp->export, basename, exp->name);2211 check_for_unused(exp->export, basename, exp->name);
2214 }2212 }
2215
2216 return err;
2217}2213}
2218 2214
2219static int check_modname_len(struct module *mod)2215static void check_modname_len(struct module *mod)
2220{2216{
2221 const char *mod_name;2217 const char *mod_name;
2222 2218
@@ -2225,12 +2221,8 @@ static int check_modname_len(struct module *mod) · 2 unmodified lines
2225 mod_name = mod->name;2221 mod_name = mod->name;
2226 else2222 else
2227 mod_name++;2223 mod_name++;
2228 if (strlen(mod_name) >= MODULE_NAME_LEN) {2224 if (strlen(mod_name) >= MODULE_NAME_LEN)
2229 error("module name is too long [%s.ko]\n", mod->name);2225 error("module name is too long [%s.ko]\n", mod->name);
2230 return 1;
2231 }
2232
2233 return 0;
2234}2226}
2235 2227
2236/**2228/**
@@ -2289,10 +2281,9 @@ static void add_staging_flag(struct buffer *b, const char *name) · 52 unmodified lines
2289/**2281/**
2290 * Record CRCs for unresolved symbols2282 * Record CRCs for unresolved symbols
2291 **/2283 **/
2292static int add_versions(struct buffer *b, struct module *mod)2284static void add_versions(struct buffer *b, struct module *mod)
2293{2285{
2294 struct symbol *s, *exp;2286 struct symbol *s, *exp;
2295 int err = 0;
2296 2287
2297 for (s = mod->unres; s; s = s->next) {2288 for (s = mod->unres; s; s = s->next) {
2298 exp = find_symbol(s->name);2289 exp = find_symbol(s->name);
@@ -2304,7 +2295,7 @@ static int add_versions(struct buffer *b, struct module *mod) · 5 unmodified lines
2304 }2295 }
2305 2296
2306 if (!modversions)2297 if (!modversions)
2307 return err;2298 return;
2308 2299
2309 buf_printf(b, "\n");2300 buf_printf(b, "\n");
2310 buf_printf(b, "static const struct modversion_info ____versions[]\n");2301 buf_printf(b, "static const struct modversion_info ____versions[]\n");
@@ -2321,7 +2312,6 @@ static int add_versions(struct buffer *b, struct module *mod) · 10 unmodified lines
2321 if (strlen(s->name) >= MODULE_NAME_LEN) {2312 if (strlen(s->name) >= MODULE_NAME_LEN) {
2322 error("too long symbol \"%s\" [%s.ko]\n",2313 error("too long symbol \"%s\" [%s.ko]\n",
2323 s->name, mod->name);2314 s->name, mod->name);
2324 err = 1;
2325 break;2315 break;
2326 }2316 }
2327 buf_printf(b, "\t{ %#8x, \"%s\" },\n",2317 buf_printf(b, "\t{ %#8x, \"%s\" },\n",
@@ -2329,8 +2319,6 @@ static int add_versions(struct buffer *b, struct module *mod) · 1 unmodified line
2329 }2319 }
2330 2320
2331 buf_printf(b, "};\n");2321 buf_printf(b, "};\n");
2332
2333 return err;
2334}2322}
2335 2323
2336static void add_depends(struct buffer *b, struct module *mod)2324static void add_depends(struct buffer *b, struct module *mod)
@@ -2554,7 +2542,6 @@ int main(int argc, char **argv) · 217 unmodified lines
2554 char *missing_namespace_deps = NULL;2542 char *missing_namespace_deps = NULL;
2555 char *dump_write = NULL, *files_source = NULL;2543 char *dump_write = NULL, *files_source = NULL;
2556 int opt;2544 int opt;
2557 int err;
2558 int n;2545 int n;
2559 struct dump_list *dump_read_start = NULL;2546 struct dump_list *dump_read_start = NULL;
2560 struct dump_list **dump_read_iter = &dump_read_start;2547 struct dump_list **dump_read_iter = &dump_read_start;
@@ -2624,8 +2611,6 @@ int main(int argc, char **argv) · 63 unmodified lines
2624 if (!have_vmlinux)2611 if (!have_vmlinux)
2625 warn("Symbol info of vmlinux is missing. Unresolved symbol check will be entirely skipped.\n");2612 warn("Symbol info of vmlinux is missing. Unresolved symbol check will be entirely skipped.\n");
2626 2613
2627 err = 0;
2628
2629 for (mod = modules; mod; mod = mod->next) {2614 for (mod = modules; mod; mod = mod->next) {
2630 char fname[PATH_MAX];2615 char fname[PATH_MAX];
2631 2616
@@ -2634,14 +2619,14 @@ int main(int argc, char **argv) · 2 unmodified lines
2634 2619
2635 buf.pos = 0;2620 buf.pos = 0;
2636 2621
2637 err |= check_modname_len(mod);2622 check_modname_len(mod);
2638 err |= check_exports(mod);2623 check_exports(mod);
2639 2624
2640 add_header(&buf, mod);2625 add_header(&buf, mod);
2641 add_intree_flag(&buf, !external_module);2626 add_intree_flag(&buf, !external_module);
2642 add_retpoline(&buf);2627 add_retpoline(&buf);
2643 add_staging_flag(&buf, mod->name);2628 add_staging_flag(&buf, mod->name);
2644 err |= add_versions(&buf, mod);2629 add_versions(&buf, mod);
2645 add_depends(&buf, mod);2630 add_depends(&buf, mod);
2646 add_moddevtable(&buf, mod);2631 add_moddevtable(&buf, mod);
2647 add_srcversion(&buf, mod);2632 add_srcversion(&buf, mod);
@@ -2671,5 +2656,5 @@ int main(int argc, char **argv) · 23 unmodified lines
2671 2656
2672 free(buf.p);2657 free(buf.p);
2673 2658
2674 return err;2659 return error_occurred ? 1 : 0;
2675}2660}
scripts/mod/modpost.h+13−0
@@ -201,6 +201,19 @@ enum loglevel { · 200 unmodified lines
201 201
202void modpost_log(enum loglevel loglevel, const char *fmt, ...);202void modpost_log(enum loglevel loglevel, const char *fmt, ...);
203 203
204/*
205 * warn - show the given message, then let modpost continue running, still
206 * allowing modpost to exit successfully. This should be used when
207 * we still allow to generate vmlinux and modules.
208 *
209 * error - show the given message, then let modpost continue running, but fail
210 * in the end. This should be used when we should stop building vmlinux
211 * or modules, but we can continue running modpost to catch as many
212 * issues as possible.
213 *
214 * fatal - show the given message, and bail out immediately. This should be
215 * used when there is no point to continue running modpost.
216 */
204#define warn(fmt, args...) modpost_log(LOG_WARN, fmt, ##args)217#define warn(fmt, args...) modpost_log(LOG_WARN, fmt, ##args)
205#define error(fmt, args...) modpost_log(LOG_ERROR, fmt, ##args)218#define error(fmt, args...) modpost_log(LOG_ERROR, fmt, ##args)
206#define fatal(fmt, args...) modpost_log(LOG_FATAL, fmt, ##args)219#define fatal(fmt, args...) modpost_log(LOG_FATAL, fmt, ##args)

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t