summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-09-05 11:50:26 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-09-05 11:50:26 -0400
commit45d9a2220f6004b47c362cc7fc7cf9a73cb6353a (patch)
tree4e2217464c5cd71674a6ffff1f3dddaeb52556b7 /lib
parent2386a3b0fbb0c2dcf29694c7df9a72cb268458f0 (diff)
parent02afc27faec94c9e068517a22acf55400976c698 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull vfs pile 1 from Al Viro: "Unfortunately, this merge window it'll have a be a lot of small piles - my fault, actually, for not keeping #for-next in anything that would resemble a sane shape ;-/ This pile: assorted fixes (the first 3 are -stable fodder, IMO) and cleanups + %pd/%pD formats (dentry/file pathname, up to 4 last components) + several long-standing patches from various folks. There definitely will be a lot more (starting with Miklos' check_submount_and_drop() series)" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (26 commits) direct-io: Handle O_(D)SYNC AIO direct-io: Implement generic deferred AIO completions add formats for dentry/file pathnames kvm eventfd: switch to fdget powerpc kvm: use fdget switch fchmod() to fdget switch epoll_ctl() to fdget switch copy_module_from_fd() to fdget git simplify nilfs check for busy subtree ibmasmfs: don't bother passing superblock when not needed don't pass superblock to hypfs_{mkdir,create*} don't pass superblock to hypfs_diag_create_files don't pass superblock to hypfs_vm_create_files() oprofile: get rid of pointless forward declarations of struct super_block oprofilefs_create_...() do not need superblock argument oprofilefs_mkdir() doesn't need superblock argument don't bother with passing superblock to oprofile_create_stats_files() oprofile: don't bother with passing superblock to ->create_files() don't bother passing sb to oprofile_create_files() coh901318: don't open-code simple_read_from_buffer() ...
Diffstat (limited to 'lib')
-rw-r--r--lib/vsprintf.c82
1 files changed, 82 insertions, 0 deletions
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) {