diff options
author | Akinobu Mita <akinobu.mita@gmail.com> | 2011-10-31 20:08:07 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-10-31 20:30:47 -0400 |
commit | 798248206b59acc6e1238c778281419c041891a7 (patch) | |
tree | ff8564431367b442b18bca4a0a9732e5799e2391 /mm | |
parent | 77311139f364d7f71fc9ba88f59fd90e60205007 (diff) |
lib/string.c: introduce memchr_inv()
memchr_inv() is mainly used to check whether the whole buffer is filled
with just a specified byte.
The function name and prototype are stolen from logfs and the
implementation is from SLUB.
Signed-off-by: Akinobu Mita <akinobu.mita@gmail.com>
Acked-by: Christoph Lameter <cl@linux-foundation.org>
Acked-by: Pekka Enberg <penberg@kernel.org>
Cc: Matt Mackall <mpm@selenic.com>
Acked-by: Joern Engel <joern@logfs.org>
Cc: Marcin Slusarz <marcin.slusarz@gmail.com>
Cc: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm')
-rw-r--r-- | mm/slub.c | 47 |
1 files changed, 2 insertions, 45 deletions
@@ -655,49 +655,6 @@ static void init_object(struct kmem_cache *s, void *object, u8 val) | |||
655 | memset(p + s->objsize, val, s->inuse - s->objsize); | 655 | memset(p + s->objsize, val, s->inuse - s->objsize); |
656 | } | 656 | } |
657 | 657 | ||
658 | static u8 *check_bytes8(u8 *start, u8 value, unsigned int bytes) | ||
659 | { | ||
660 | while (bytes) { | ||
661 | if (*start != value) | ||
662 | return start; | ||
663 | start++; | ||
664 | bytes--; | ||
665 | } | ||
666 | return NULL; | ||
667 | } | ||
668 | |||
669 | static u8 *check_bytes(u8 *start, u8 value, unsigned int bytes) | ||
670 | { | ||
671 | u64 value64; | ||
672 | unsigned int words, prefix; | ||
673 | |||
674 | if (bytes <= 16) | ||
675 | return check_bytes8(start, value, bytes); | ||
676 | |||
677 | value64 = value | value << 8 | value << 16 | value << 24; | ||
678 | value64 = (value64 & 0xffffffff) | value64 << 32; | ||
679 | prefix = 8 - ((unsigned long)start) % 8; | ||
680 | |||
681 | if (prefix) { | ||
682 | u8 *r = check_bytes8(start, value, prefix); | ||
683 | if (r) | ||
684 | return r; | ||
685 | start += prefix; | ||
686 | bytes -= prefix; | ||
687 | } | ||
688 | |||
689 | words = bytes / 8; | ||
690 | |||
691 | while (words) { | ||
692 | if (*(u64 *)start != value64) | ||
693 | return check_bytes8(start, value, 8); | ||
694 | start += 8; | ||
695 | words--; | ||
696 | } | ||
697 | |||
698 | return check_bytes8(start, value, bytes % 8); | ||
699 | } | ||
700 | |||
701 | static void restore_bytes(struct kmem_cache *s, char *message, u8 data, | 658 | static void restore_bytes(struct kmem_cache *s, char *message, u8 data, |
702 | void *from, void *to) | 659 | void *from, void *to) |
703 | { | 660 | { |
@@ -712,7 +669,7 @@ static int check_bytes_and_report(struct kmem_cache *s, struct page *page, | |||
712 | u8 *fault; | 669 | u8 *fault; |
713 | u8 *end; | 670 | u8 *end; |
714 | 671 | ||
715 | fault = check_bytes(start, value, bytes); | 672 | fault = memchr_inv(start, value, bytes); |
716 | if (!fault) | 673 | if (!fault) |
717 | return 1; | 674 | return 1; |
718 | 675 | ||
@@ -805,7 +762,7 @@ static int slab_pad_check(struct kmem_cache *s, struct page *page) | |||
805 | if (!remainder) | 762 | if (!remainder) |
806 | return 1; | 763 | return 1; |
807 | 764 | ||
808 | fault = check_bytes(end - remainder, POISON_INUSE, remainder); | 765 | fault = memchr_inv(end - remainder, POISON_INUSE, remainder); |
809 | if (!fault) | 766 | if (!fault) |
810 | return 1; | 767 | return 1; |
811 | while (end > fault && end[-1] == POISON_INUSE) | 768 | while (end > fault && end[-1] == POISON_INUSE) |