summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2013-09-03 12:00:44 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2013-09-04 00:13:11 -0400
commit4b6ccca701ef5977d0ffbc2c932430dea88b38b6 (patch)
treef8daa1243e24168fba2595c29805765856708673
parentcffe78d92c217a57f57ec6743f71adfe39ea543e (diff)
add formats for dentry/file pathnames
New formats: %p[dD][234]?. The next pointer is interpreted as struct dentry * or struct file * resp. ('d' => dentry, 'D' => file) and the last component(s) of pathname are printed (%pd => just the last one, %pd2 => the last two, etc.) Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--Documentation/printk-formats.txt9
-rw-r--r--lib/vsprintf.c82
2 files changed, 91 insertions, 0 deletions
diff --git a/Documentation/printk-formats.txt b/Documentation/printk-formats.txt
index 3e8cb73ac43c..9552a3299ec9 100644
--- a/Documentation/printk-formats.txt
+++ b/Documentation/printk-formats.txt
@@ -168,6 +168,15 @@ UUID/GUID addresses:
168 Where no additional specifiers are used the default little endian 168 Where no additional specifiers are used the default little endian
169 order with lower case hex characters will be printed. 169 order with lower case hex characters will be printed.
170 170
171dentry names:
172 %pd{,2,3,4}
173 %pD{,2,3,4}
174
175 For printing dentry name; if we race with d_move(), the name might be
176 a mix of old and new ones, but it won't oops. %pd dentry is a safer
177 equivalent of %s dentry->d_name.name we used to use, %pd<n> prints
178 n last components. %pD does the same thing for struct file.
179
171struct va_format: 180struct va_format:
172 181
173 %pV 182 %pV
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 739a36366b79..26559bdb4c49 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -26,6 +26,7 @@
26#include <linux/math64.h> 26#include <linux/math64.h>
27#include <linux/uaccess.h> 27#include <linux/uaccess.h>
28#include <linux/ioport.h> 28#include <linux/ioport.h>
29#include <linux/dcache.h>
29#include <net/addrconf.h> 30#include <net/addrconf.h>
30 31
31#include <asm/page.h> /* for PAGE_SIZE */ 32#include <asm/page.h> /* for PAGE_SIZE */
@@ -532,6 +533,81 @@ char *string(char *buf, char *end, const char *s, struct printf_spec spec)
532 return buf; 533 return buf;
533} 534}
534 535
536static void widen(char *buf, char *end, unsigned len, unsigned spaces)
537{
538 size_t size;
539 if (buf >= end) /* nowhere to put anything */
540 return;
541 size = end - buf;
542 if (size <= spaces) {
543 memset(buf, ' ', size);
544 return;
545 }
546 if (len) {
547 if (len > size - spaces)
548 len = size - spaces;
549 memmove(buf + spaces, buf, len);
550 }
551 memset(buf, ' ', spaces);
552}
553
554static noinline_for_stack
555char *dentry_name(char *buf, char *end, const struct dentry *d, struct printf_spec spec,
556 const char *fmt)
557{
558 const char *array[4], *s;
559 const struct dentry *p;
560 int depth;
561 int i, n;
562
563 switch (fmt[1]) {
564 case '2': case '3': case '4':
565 depth = fmt[1] - '0';
566 break;
567 default:
568 depth = 1;
569 }
570
571 rcu_read_lock();
572 for (i = 0; i < depth; i++, d = p) {
573 p = ACCESS_ONCE(d->d_parent);
574 array[i] = ACCESS_ONCE(d->d_name.name);
575 if (p == d) {
576 if (i)
577 array[i] = "";
578 i++;
579 break;
580 }
581 }
582 s = array[--i];
583 for (n = 0; n != spec.precision; n++, buf++) {
584 char c = *s++;
585 if (!c) {
586 if (!i)
587 break;
588 c = '/';
589 s = array[--i];
590 }
591 if (buf < end)
592 *buf = c;
593 }
594 rcu_read_unlock();
595 if (n < spec.field_width) {
596 /* we want to pad the sucker */
597 unsigned spaces = spec.field_width - n;
598 if (!(spec.flags & LEFT)) {
599 widen(buf - n, end, n, spaces);
600 return buf + spaces;
601 }
602 while (spaces--) {
603 if (buf < end)
604 *buf = ' ';
605 ++buf;
606 }
607 }
608 return buf;
609}
610
535static noinline_for_stack 611static noinline_for_stack
536char *symbol_string(char *buf, char *end, void *ptr, 612char *symbol_string(char *buf, char *end, void *ptr,
537 struct printf_spec spec, const char *fmt) 613 struct printf_spec spec, const char *fmt)
@@ -1253,6 +1329,12 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr,
1253 spec.base = 16; 1329 spec.base = 16;
1254 return number(buf, end, 1330 return number(buf, end,
1255 (unsigned long long) *((phys_addr_t *)ptr), spec); 1331 (unsigned long long) *((phys_addr_t *)ptr), spec);
1332 case 'd':
1333 return dentry_name(buf, end, ptr, spec, fmt);
1334 case 'D':
1335 return dentry_name(buf, end,
1336 ((const struct file *)ptr)->f_path.dentry,
1337 spec, fmt);
1256 } 1338 }
1257 spec.flags |= SMALL; 1339 spec.flags |= SMALL;
1258 if (spec.field_width == -1) { 1340 if (spec.field_width == -1) {