Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

lib/vsprintf: Add specifier for printing struct timespec64

A handful drivers want to print a content of the struct timespec64
in a format of %lld:%09ld. In order to make their lives easier, add
the respecting specifier directly to the printf() implementation.

Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Reviewed-by: Petr Mladek <pmladek@suse.com>
Tested-by: Petr Mladek <pmladek@suse.com>
Link: https://patch.msgid.link/20251113150217.3030010-2-andriy.shevchenko@linux.intel.com
Signed-off-by: Petr Mladek <pmladek@suse.com>

authored by

Andy Shevchenko and committed by
Petr Mladek
bccd5937 48e3694a

+40 -3
+9 -2
Documentation/core-api/printk-formats.rst
··· 547 547 %pt[RT]s YYYY-mm-dd HH:MM:SS 548 548 %pt[RT]d YYYY-mm-dd 549 549 %pt[RT]t HH:MM:SS 550 - %pt[RT][dt][r][s] 550 + %ptSp <seconds>.<nanoseconds> 551 + %pt[RST][dt][r][s] 551 552 552 553 For printing date and time as represented by:: 553 554 554 - R struct rtc_time structure 555 + R content of struct rtc_time 556 + S content of struct timespec64 555 557 T time64_t type 556 558 557 559 in human readable format. ··· 564 562 The %pt[RT]s (space) will override ISO 8601 separator by using ' ' (space) 565 563 instead of 'T' (Capital T) between date and time. It won't have any effect 566 564 when date or time is omitted. 565 + 566 + The %ptSp is equivalent to %lld.%09ld for the content of the struct timespec64. 567 + When the other specifiers are given, it becomes the respective equivalent of 568 + %ptT[dt][r][s].%09ld. In other words, the seconds are being printed in 569 + the human readable format followed by a dot and nanoseconds. 567 570 568 571 Passed by reference. 569 572
+4
lib/tests/printf_kunit.c
··· 504 504 }; 505 505 /* 2019-01-04T15:32:23 */ 506 506 time64_t t = 1546615943; 507 + struct timespec64 ts = { .tv_sec = t, .tv_nsec = 11235813 }; 507 508 508 509 test("(%pt?)", "%pt", &tm); 509 510 test("2018-11-26T05:35:43", "%ptR", &tm); ··· 523 522 test("0119-00-04 15:32:23", "%ptTsr", &t); 524 523 test("15:32:23|2019-01-04", "%ptTts|%ptTds", &t, &t); 525 524 test("15:32:23|0119-00-04", "%ptTtrs|%ptTdrs", &t, &t); 525 + 526 + test("2019-01-04T15:32:23.011235813", "%ptS", &ts); 527 + test("1546615943.011235813", "%ptSp", &ts); 526 528 } 527 529 528 530 static void
+27 -1
lib/vsprintf.c
··· 1993 1993 } 1994 1994 1995 1995 static noinline_for_stack 1996 + char *timespec64_str(char *buf, char *end, const struct timespec64 *ts, 1997 + struct printf_spec spec, const char *fmt) 1998 + { 1999 + static const struct printf_spec default_dec09_spec = { 2000 + .base = 10, 2001 + .field_width = 9, 2002 + .precision = -1, 2003 + .flags = ZEROPAD, 2004 + }; 2005 + 2006 + if (fmt[2] == 'p') 2007 + buf = number(buf, end, ts->tv_sec, default_dec_spec); 2008 + else 2009 + buf = time64_str(buf, end, ts->tv_sec, spec, fmt); 2010 + if (buf < end) 2011 + *buf = '.'; 2012 + buf++; 2013 + 2014 + return number(buf, end, ts->tv_nsec, default_dec09_spec); 2015 + } 2016 + 2017 + static noinline_for_stack 1996 2018 char *time_and_date(char *buf, char *end, void *ptr, struct printf_spec spec, 1997 2019 const char *fmt) 1998 2020 { 1999 2021 switch (fmt[1]) { 2000 2022 case 'R': 2001 2023 return rtc_str(buf, end, (const struct rtc_time *)ptr, spec, fmt); 2024 + case 'S': 2025 + return timespec64_str(buf, end, (const struct timespec64 *)ptr, spec, fmt); 2002 2026 case 'T': 2003 2027 return time64_str(buf, end, *(const time64_t *)ptr, spec, fmt); 2004 2028 default: ··· 2486 2462 * - 'd[234]' For a dentry name (optionally 2-4 last components) 2487 2463 * - 'D[234]' Same as 'd' but for a struct file 2488 2464 * - 'g' For block_device name (gendisk + partition number) 2489 - * - 't[RT][dt][r][s]' For time and date as represented by: 2465 + * - 't[RST][dt][r][s]' For time and date as represented by: 2490 2466 * R struct rtc_time 2467 + * S struct timespec64 2491 2468 * T time64_t 2469 + * - 'tSp' For time represented by struct timespec64 printed as <seconds>.<nanoseconds> 2492 2470 * - 'C' For a clock, it prints the name (Common Clock Framework) or address 2493 2471 * (legacy clock framework) of the clock 2494 2472 * - 'G' For flags to be printed as a collection of symbolic strings that would