Commit 4b6ccca7 authored by Al Viro's avatar Al Viro

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: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent cffe78d9
...@@ -168,6 +168,15 @@ UUID/GUID addresses: ...@@ -168,6 +168,15 @@ UUID/GUID addresses:
Where no additional specifiers are used the default little endian Where no additional specifiers are used the default little endian
order with lower case hex characters will be printed. order with lower case hex characters will be printed.
dentry names:
%pd{,2,3,4}
%pD{,2,3,4}
For printing dentry name; if we race with d_move(), the name might be
a mix of old and new ones, but it won't oops. %pd dentry is a safer
equivalent of %s dentry->d_name.name we used to use, %pd<n> prints
n last components. %pD does the same thing for struct file.
struct va_format: struct va_format:
%pV %pV
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <linux/math64.h> #include <linux/math64.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/dcache.h>
#include <net/addrconf.h> #include <net/addrconf.h>
#include <asm/page.h> /* for PAGE_SIZE */ #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,6 +533,81 @@ char *string(char *buf, char *end, const char *s, struct printf_spec spec)
return buf; return buf;
} }
static void widen(char *buf, char *end, unsigned len, unsigned spaces)
{
size_t size;
if (buf >= end) /* nowhere to put anything */
return;
size = end - buf;
if (size <= spaces) {
memset(buf, ' ', size);
return;
}
if (len) {
if (len > size - spaces)
len = size - spaces;
memmove(buf + spaces, buf, len);
}
memset(buf, ' ', spaces);
}
static noinline_for_stack
char *dentry_name(char *buf, char *end, const struct dentry *d, struct printf_spec spec,
const char *fmt)
{
const char *array[4], *s;
const struct dentry *p;
int depth;
int i, n;
switch (fmt[1]) {
case '2': case '3': case '4':
depth = fmt[1] - '0';
break;
default:
depth = 1;
}
rcu_read_lock();
for (i = 0; i < depth; i++, d = p) {
p = ACCESS_ONCE(d->d_parent);
array[i] = ACCESS_ONCE(d->d_name.name);
if (p == d) {
if (i)
array[i] = "";
i++;
break;
}
}
s = array[--i];
for (n = 0; n != spec.precision; n++, buf++) {
char c = *s++;
if (!c) {
if (!i)
break;
c = '/';
s = array[--i];
}
if (buf < end)
*buf = c;
}
rcu_read_unlock();
if (n < spec.field_width) {
/* we want to pad the sucker */
unsigned spaces = spec.field_width - n;
if (!(spec.flags & LEFT)) {
widen(buf - n, end, n, spaces);
return buf + spaces;
}
while (spaces--) {
if (buf < end)
*buf = ' ';
++buf;
}
}
return buf;
}
static noinline_for_stack static noinline_for_stack
char *symbol_string(char *buf, char *end, void *ptr, char *symbol_string(char *buf, char *end, void *ptr,
struct printf_spec spec, const char *fmt) struct printf_spec spec, const char *fmt)
...@@ -1253,6 +1329,12 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr, ...@@ -1253,6 +1329,12 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr,
spec.base = 16; spec.base = 16;
return number(buf, end, return number(buf, end,
(unsigned long long) *((phys_addr_t *)ptr), spec); (unsigned long long) *((phys_addr_t *)ptr), spec);
case 'd':
return dentry_name(buf, end, ptr, spec, fmt);
case 'D':
return dentry_name(buf, end,
((const struct file *)ptr)->f_path.dentry,
spec, fmt);
} }
spec.flags |= SMALL; spec.flags |= SMALL;
if (spec.field_width == -1) { if (spec.field_width == -1) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment