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
4040 /* If set to 1, only warn (instead of error) about missing ns imports */
4141 static int allow_missing_ns_imports;
4242
43+static bool error_occurred;
44+
4345 enum export {
4446 export_plain, export_unused, export_gpl,
4547 export_unused_gpl, export_gpl_future, export_unknown
@@ -78,6 +80,8 @@ modpost_log(enum loglevel loglevel, const char *fmt, ...) · 32 unmodified lines
7880
7981 if (loglevel == LOG_FATAL)
8082 exit(1);
83+ if (loglevel == LOG_ERROR)
84+ error_occurred = true;
8185 }
8286
8387 static 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
21742178 }
21752179 }
21762180
2177−static int check_exports(struct module *mod)
2181+static void check_exports(struct module *mod)
21782182 {
21792183 struct symbol *s, *exp;
2180− int err = 0;
21812184
21822185 for (s = mod->unres; s; s = s->next) {
21832186 const char *basename;
21842187 exp = find_symbol(s->name);
21852188 if (!exp || exp->module == mod) {
2186− if (have_vmlinux && !s->weak) {
2189+ if (have_vmlinux && !s->weak)
21872190 modpost_log(warn_unresolved ? LOG_WARN : LOG_ERROR,
21882191 "\"%s\" [%s.ko] undefined!\n",
21892192 s->name, mod->name);
2190− if (!warn_unresolved)
2191− err = 1;
2192− }
21932193 continue;
21942194 }
21952195 basename = strrchr(mod->name, '/');
@@ -2203,8 +2203,6 @@ static int check_exports(struct module *mod) · 7 unmodified lines
22032203 modpost_log(allow_missing_ns_imports ? LOG_WARN : LOG_ERROR,
22042204 "module %s uses symbol %s from namespace %s, but does not import it.\n",
22052205 basename, exp->name, exp->namespace);
2206− if (!allow_missing_ns_imports)
2207− err = 1;
22082206 add_namespace(&mod->missing_namespaces, exp->namespace);
22092207 }
22102208
@@ -2212,11 +2210,9 @@ static int check_exports(struct module *mod) · 1 unmodified line
22122210 check_for_gpl_usage(exp->export, basename, exp->name);
22132211 check_for_unused(exp->export, basename, exp->name);
22142212 }
2215−
2216− return err;
22172213 }
22182214
2219−static int check_modname_len(struct module *mod)
2215+static void check_modname_len(struct module *mod)
22202216 {
22212217 const char *mod_name;
22222218
@@ -2225,12 +2221,8 @@ static int check_modname_len(struct module *mod) · 2 unmodified lines
22252221 mod_name = mod->name;
22262222 else
22272223 mod_name++;
2228− if (strlen(mod_name) >= MODULE_NAME_LEN) {
2224+ if (strlen(mod_name) >= MODULE_NAME_LEN)
22292225 error("module name is too long [%s.ko]\n", mod->name);
2230− return 1;
2231− }
2232−
2233− return 0;
22342226 }
22352227
22362228 /**
@@ -2289,10 +2281,9 @@ static void add_staging_flag(struct buffer *b, const char *name) · 52 unmodified lines
22892281 /**
22902282 * Record CRCs for unresolved symbols
22912283 **/
2292−static int add_versions(struct buffer *b, struct module *mod)
2284+static void add_versions(struct buffer *b, struct module *mod)
22932285 {
22942286 struct symbol *s, *exp;
2295− int err = 0;
22962287
22972288 for (s = mod->unres; s; s = s->next) {
22982289 exp = find_symbol(s->name);
@@ -2304,7 +2295,7 @@ static int add_versions(struct buffer *b, struct module *mod) · 5 unmodified lines
23042295 }
23052296
23062297 if (!modversions)
2307− return err;
2298+ return;
23082299
23092300 buf_printf(b, "\n");
23102301 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
23212312 if (strlen(s->name) >= MODULE_NAME_LEN) {
23222313 error("too long symbol \"%s\" [%s.ko]\n",
23232314 s->name, mod->name);
2324− err = 1;
23252315 break;
23262316 }
23272317 buf_printf(b, "\t{ %#8x, \"%s\" },\n",
@@ -2329,8 +2319,6 @@ static int add_versions(struct buffer *b, struct module *mod) · 1 unmodified line
23292319 }
23302320
23312321 buf_printf(b, "};\n");
2332−
2333− return err;
23342322 }
23352323
23362324 static void add_depends(struct buffer *b, struct module *mod)
@@ -2554,7 +2542,6 @@ int main(int argc, char **argv) · 217 unmodified lines
25542542 char *missing_namespace_deps = NULL;
25552543 char *dump_write = NULL, *files_source = NULL;
25562544 int opt;
2557− int err;
25582545 int n;
25592546 struct dump_list *dump_read_start = NULL;
25602547 struct dump_list **dump_read_iter = &dump_read_start;
@@ -2624,8 +2611,6 @@ int main(int argc, char **argv) · 63 unmodified lines
26242611 if (!have_vmlinux)
26252612 warn("Symbol info of vmlinux is missing. Unresolved symbol check will be entirely skipped.\n");
26262613
2627− err = 0;
2628−
26292614 for (mod = modules; mod; mod = mod->next) {
26302615 char fname[PATH_MAX];
26312616
@@ -2634,14 +2619,14 @@ int main(int argc, char **argv) · 2 unmodified lines
26342619
26352620 buf.pos = 0;
26362621
2637− err |= check_modname_len(mod);
2638− err |= check_exports(mod);
2622+ check_modname_len(mod);
2623+ check_exports(mod);
26392624
26402625 add_header(&buf, mod);
26412626 add_intree_flag(&buf, !external_module);
26422627 add_retpoline(&buf);
26432628 add_staging_flag(&buf, mod->name);
2644− err |= add_versions(&buf, mod);
2629+ add_versions(&buf, mod);
26452630 add_depends(&buf, mod);
26462631 add_moddevtable(&buf, mod);
26472632 add_srcversion(&buf, mod);
@@ -2671,5 +2656,5 @@ int main(int argc, char **argv) · 23 unmodified lines
26712656
26722657 free(buf.p);
26732658
2674− return err;
2659+ return error_occurred ? 1 : 0;
26752660 }
scripts/mod/modpost.h+13−0
@@ -201,6 +201,19 @@ enum loglevel { · 200 unmodified lines
201201
202202 void modpost_log(enum loglevel loglevel, const char *fmt, ...);
203203
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+ */
204217 #define warn(fmt, args...) modpost_log(LOG_WARN, fmt, ##args)
205218 #define error(fmt, args...) modpost_log(LOG_ERROR, fmt, ##args)
206219 #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