pr_info("probing failed (%dE)\n", ret); expands to probing failed (EIO) if ret holds -EIO (or EIO). This introduces an array of error codes. If the error code is missing, %dE falls back to %d and so prints the plain number. Signed-off-by: Uwe Kleine-König <uwe@xxxxxxxxxxxxxxxxx> --- Hello there are many code sites that benefit from this. Just grep for "(%d)" ... As an example the follow up patch converts a printk to use this new format escape. Best regards Uwe Documentation/core-api/printk-formats.rst | 3 + lib/vsprintf.c | 193 +++++++++++++++++++++- 2 files changed, 195 insertions(+), 1 deletion(-) diff --git a/Documentation/core-api/printk-formats.rst b/Documentation/core-api/printk-formats.rst index c6224d039bcb..81002414f956 100644 --- a/Documentation/core-api/printk-formats.rst +++ b/Documentation/core-api/printk-formats.rst @@ -35,6 +35,9 @@ Integer types u64 %llu or %llx +To print the name that corresponds to an integer error constant, use %dE and +pass the int. + If <type> is dependent on a config option for its size (e.g., sector_t, blkcnt_t) or is architecture-dependent for its size (e.g., tcflag_t), use a format specifier of its largest possible type and explicitly cast to it. diff --git a/lib/vsprintf.c b/lib/vsprintf.c index b0967cf17137..672eab8dab84 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -533,6 +533,192 @@ char *number(char *buf, char *end, unsigned long long num, return buf; } +#define ERRORCODE(x) { .str = #x, .err = x } + +static const struct { + const char *str; + int err; +} errorcodes[] = { + ERRORCODE(EPERM), + ERRORCODE(ENOENT), + ERRORCODE(ESRCH), + ERRORCODE(EINTR), + ERRORCODE(EIO), + ERRORCODE(ENXIO), + ERRORCODE(E2BIG), + ERRORCODE(ENOEXEC), + ERRORCODE(EBADF), + ERRORCODE(ECHILD), + ERRORCODE(EAGAIN), + ERRORCODE(ENOMEM), + ERRORCODE(EACCES), + ERRORCODE(EFAULT), + ERRORCODE(ENOTBLK), + ERRORCODE(EBUSY), + ERRORCODE(EEXIST), + ERRORCODE(EXDEV), + ERRORCODE(ENODEV), + ERRORCODE(ENOTDIR), + ERRORCODE(EISDIR), + ERRORCODE(EINVAL), + ERRORCODE(ENFILE), + ERRORCODE(EMFILE), + ERRORCODE(ENOTTY), + ERRORCODE(ETXTBSY), + ERRORCODE(EFBIG), + ERRORCODE(ENOSPC), + ERRORCODE(ESPIPE), + ERRORCODE(EROFS), + ERRORCODE(EMLINK), + ERRORCODE(EPIPE), + ERRORCODE(EDOM), + ERRORCODE(ERANGE), + ERRORCODE(EDEADLK), + ERRORCODE(ENAMETOOLONG), + ERRORCODE(ENOLCK), + ERRORCODE(ENOSYS), + ERRORCODE(ENOTEMPTY), + ERRORCODE(ELOOP), + ERRORCODE(EWOULDBLOCK), + ERRORCODE(ENOMSG), + ERRORCODE(EIDRM), + ERRORCODE(ECHRNG), + ERRORCODE(EL2NSYNC), + ERRORCODE(EL3HLT), + ERRORCODE(EL3RST), + ERRORCODE(ELNRNG), + ERRORCODE(EUNATCH), + ERRORCODE(ENOCSI), + ERRORCODE(EL2HLT), + ERRORCODE(EBADE), + ERRORCODE(EBADR), + ERRORCODE(EXFULL), + ERRORCODE(ENOANO), + ERRORCODE(EBADRQC), + ERRORCODE(EBADSLT), + ERRORCODE(EBFONT), + ERRORCODE(ENOSTR), + ERRORCODE(ENODATA), + ERRORCODE(ETIME), + ERRORCODE(ENOSR), + ERRORCODE(ENONET), + ERRORCODE(ENOPKG), + ERRORCODE(EREMOTE), + ERRORCODE(ENOLINK), + ERRORCODE(EADV), + ERRORCODE(ESRMNT), + ERRORCODE(ECOMM), + ERRORCODE(EPROTO), + ERRORCODE(EMULTIHOP), + ERRORCODE(EDOTDOT), + ERRORCODE(EBADMSG), + ERRORCODE(EOVERFLOW), + ERRORCODE(ENOTUNIQ), + ERRORCODE(EBADFD), + ERRORCODE(EREMCHG), + ERRORCODE(ELIBACC), + ERRORCODE(ELIBBAD), + ERRORCODE(ELIBSCN), + ERRORCODE(ELIBMAX), + ERRORCODE(ELIBEXEC), + ERRORCODE(EILSEQ), + ERRORCODE(ERESTART), + ERRORCODE(ESTRPIPE), + ERRORCODE(EUSERS), + ERRORCODE(ENOTSOCK), + ERRORCODE(EDESTADDRREQ), + ERRORCODE(EMSGSIZE), + ERRORCODE(EPROTOTYPE), + ERRORCODE(ENOPROTOOPT), + ERRORCODE(EPROTONOSUPPORT), + ERRORCODE(ESOCKTNOSUPPORT), + ERRORCODE(EOPNOTSUPP), + ERRORCODE(EPFNOSUPPORT), + ERRORCODE(EAFNOSUPPORT), + ERRORCODE(EADDRINUSE), + ERRORCODE(EADDRNOTAVAIL), + ERRORCODE(ENETDOWN), + ERRORCODE(ENETUNREACH), + ERRORCODE(ENETRESET), + ERRORCODE(ECONNABORTED), + ERRORCODE(ECONNRESET), + ERRORCODE(ENOBUFS), + ERRORCODE(EISCONN), + ERRORCODE(ENOTCONN), + ERRORCODE(ESHUTDOWN), + ERRORCODE(ETOOMANYREFS), + ERRORCODE(ETIMEDOUT), + ERRORCODE(ECONNREFUSED), + ERRORCODE(EHOSTDOWN), + ERRORCODE(EHOSTUNREACH), + ERRORCODE(EALREADY), + ERRORCODE(EINPROGRESS), + ERRORCODE(ESTALE), + ERRORCODE(EUCLEAN), + ERRORCODE(ENOTNAM), + ERRORCODE(ENAVAIL), + ERRORCODE(EISNAM), + ERRORCODE(EREMOTEIO), + ERRORCODE(EDQUOT), + ERRORCODE(ENOMEDIUM), + ERRORCODE(EMEDIUMTYPE), + ERRORCODE(ECANCELED), + ERRORCODE(ENOKEY), + ERRORCODE(EKEYEXPIRED), + ERRORCODE(EKEYREVOKED), + ERRORCODE(EKEYREJECTED), + ERRORCODE(EOWNERDEAD), + ERRORCODE(ENOTRECOVERABLE), + ERRORCODE(ERFKILL), + ERRORCODE(EHWPOISON), + ERRORCODE(ERESTARTSYS), + ERRORCODE(ERESTARTNOINTR), + ERRORCODE(ERESTARTNOHAND), + ERRORCODE(ENOIOCTLCMD), + ERRORCODE(ERESTART_RESTARTBLOCK), + ERRORCODE(EPROBE_DEFER), + ERRORCODE(EOPENSTALE), + ERRORCODE(ENOPARAM), + ERRORCODE(EBADHANDLE), + ERRORCODE(ENOTSYNC), + ERRORCODE(EBADCOOKIE), + ERRORCODE(ENOTSUPP), + ERRORCODE(ETOOSMALL), + ERRORCODE(ESERVERFAULT), + ERRORCODE(EBADTYPE), + ERRORCODE(EJUKEBOX), + ERRORCODE(EIOCBQUEUED), + ERRORCODE(ERECALLCONFLICT), +}; + +static noinline_for_stack +char *errstr(char *buf, char *end, unsigned long long num, + struct printf_spec spec) +{ + char *errname = NULL; + size_t errnamelen, copy; + int i; + + for (i = 0; i < ARRAY_SIZE(errorcodes); ++i) { + if (num == errorcodes[i].err || num == -errorcodes[i].err) { + errname = errorcodes[i].str; + break; + } + } + + if (!errname) { + /* fall back to ordinary number */ + return number(buf, end, num, spec); + } + + copy = errnamelen = strlen(errname); + if (copy > end - buf) + copy = end - buf; + buf = memcpy(buf, errname, copy); + + return buf + errnamelen; +} + static noinline_for_stack char *special_hex_number(char *buf, char *end, unsigned long long num, int size) { @@ -2566,7 +2752,12 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args) num = va_arg(args, unsigned int); } - str = number(str, end, num, spec); + if (spec.type == FORMAT_TYPE_INT && *fmt == 'E') { + fmt++; + str = errstr(str, end, num, spec); + } else { + str = number(str, end, num, spec); + } } } -- 2.20.1