aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/logfs/logfs.h1
-rw-r--r--fs/logfs/super.c22
-rw-r--r--include/linux/string.h1
-rw-r--r--lib/string.c54
-rw-r--r--mm/slub.c47
5 files changed, 57 insertions, 68 deletions
diff --git a/fs/logfs/logfs.h b/fs/logfs/logfs.h
index f22d108bfa5d..398ecff6e548 100644
--- a/fs/logfs/logfs.h
+++ b/fs/logfs/logfs.h
@@ -618,7 +618,6 @@ static inline int logfs_buf_recover(struct logfs_area *area, u64 ofs,
618struct page *emergency_read_begin(struct address_space *mapping, pgoff_t index); 618struct page *emergency_read_begin(struct address_space *mapping, pgoff_t index);
619void emergency_read_end(struct page *page); 619void emergency_read_end(struct page *page);
620void logfs_crash_dump(struct super_block *sb); 620void logfs_crash_dump(struct super_block *sb);
621void *memchr_inv(const void *s, int c, size_t n);
622int logfs_statfs(struct dentry *dentry, struct kstatfs *stats); 621int logfs_statfs(struct dentry *dentry, struct kstatfs *stats);
623int logfs_check_ds(struct logfs_disk_super *ds); 622int logfs_check_ds(struct logfs_disk_super *ds);
624int logfs_write_sb(struct super_block *sb); 623int logfs_write_sb(struct super_block *sb);
diff --git a/fs/logfs/super.c b/fs/logfs/super.c
index ce03a182c771..f2697e4df109 100644
--- a/fs/logfs/super.c
+++ b/fs/logfs/super.c
@@ -91,28 +91,6 @@ void logfs_crash_dump(struct super_block *sb)
91} 91}
92 92
93/* 93/*
94 * TODO: move to lib/string.c
95 */
96/**
97 * memchr_inv - Find a character in an area of memory.
98 * @s: The memory area
99 * @c: The byte to search for
100 * @n: The size of the area.
101 *
102 * returns the address of the first character other than @c, or %NULL
103 * if the whole buffer contains just @c.
104 */
105void *memchr_inv(const void *s, int c, size_t n)
106{
107 const unsigned char *p = s;
108 while (n-- != 0)
109 if ((unsigned char)c != *p++)
110 return (void *)(p - 1);
111
112 return NULL;
113}
114
115/*
116 * FIXME: There should be a reserve for root, similar to ext2. 94 * FIXME: There should be a reserve for root, similar to ext2.
117 */ 95 */
118int logfs_statfs(struct dentry *dentry, struct kstatfs *stats) 96int logfs_statfs(struct dentry *dentry, struct kstatfs *stats)
diff --git a/include/linux/string.h b/include/linux/string.h
index a176db2f2c85..e033564f10ba 100644
--- a/include/linux/string.h
+++ b/include/linux/string.h
@@ -114,6 +114,7 @@ extern int memcmp(const void *,const void *,__kernel_size_t);
114#ifndef __HAVE_ARCH_MEMCHR 114#ifndef __HAVE_ARCH_MEMCHR
115extern void * memchr(const void *,int,__kernel_size_t); 115extern void * memchr(const void *,int,__kernel_size_t);
116#endif 116#endif
117void *memchr_inv(const void *s, int c, size_t n);
117 118
118extern char *kstrdup(const char *s, gfp_t gfp); 119extern char *kstrdup(const char *s, gfp_t gfp);
119extern char *kstrndup(const char *s, size_t len, gfp_t gfp); 120extern char *kstrndup(const char *s, size_t len, gfp_t gfp);
diff --git a/lib/string.c b/lib/string.c
index 01fad9b203e1..11df54325fb8 100644
--- a/lib/string.c
+++ b/lib/string.c
@@ -756,3 +756,57 @@ void *memchr(const void *s, int c, size_t n)
756} 756}
757EXPORT_SYMBOL(memchr); 757EXPORT_SYMBOL(memchr);
758#endif 758#endif
759
760static void *check_bytes8(const u8 *start, u8 value, unsigned int bytes)
761{
762 while (bytes) {
763 if (*start != value)
764 return (void *)start;
765 start++;
766 bytes--;
767 }
768 return NULL;
769}
770
771/**
772 * memchr_inv - Find an unmatching character in an area of memory.
773 * @start: The memory area
774 * @c: Find a character other than c
775 * @bytes: The size of the area.
776 *
777 * returns the address of the first character other than @c, or %NULL
778 * if the whole buffer contains just @c.
779 */
780void *memchr_inv(const void *start, int c, size_t bytes)
781{
782 u8 value = c;
783 u64 value64;
784 unsigned int words, prefix;
785
786 if (bytes <= 16)
787 return check_bytes8(start, value, bytes);
788
789 value64 = value | value << 8 | value << 16 | value << 24;
790 value64 = (value64 & 0xffffffff) | value64 << 32;
791 prefix = 8 - ((unsigned long)start) % 8;
792
793 if (prefix) {
794 u8 *r = check_bytes8(start, value, prefix);
795 if (r)
796 return r;
797 start += prefix;
798 bytes -= prefix;
799 }
800
801 words = bytes / 8;
802
803 while (words) {
804 if (*(u64 *)start != value64)
805 return check_bytes8(start, value, 8);
806 start += 8;
807 words--;
808 }
809
810 return check_bytes8(start, value, bytes % 8);
811}
812EXPORT_SYMBOL(memchr_inv);
diff --git a/mm/slub.c b/mm/slub.c
index 95215aa6a75e..7d2a996c307e 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -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
658static 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
669static 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
701static void restore_bytes(struct kmem_cache *s, char *message, u8 data, 658static 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)