diff options
-rw-r--r-- | fs/logfs/logfs.h | 1 | ||||
-rw-r--r-- | fs/logfs/super.c | 22 | ||||
-rw-r--r-- | include/linux/string.h | 1 | ||||
-rw-r--r-- | lib/string.c | 54 | ||||
-rw-r--r-- | mm/slub.c | 47 |
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, | |||
618 | struct page *emergency_read_begin(struct address_space *mapping, pgoff_t index); | 618 | struct page *emergency_read_begin(struct address_space *mapping, pgoff_t index); |
619 | void emergency_read_end(struct page *page); | 619 | void emergency_read_end(struct page *page); |
620 | void logfs_crash_dump(struct super_block *sb); | 620 | void logfs_crash_dump(struct super_block *sb); |
621 | void *memchr_inv(const void *s, int c, size_t n); | ||
622 | int logfs_statfs(struct dentry *dentry, struct kstatfs *stats); | 621 | int logfs_statfs(struct dentry *dentry, struct kstatfs *stats); |
623 | int logfs_check_ds(struct logfs_disk_super *ds); | 622 | int logfs_check_ds(struct logfs_disk_super *ds); |
624 | int logfs_write_sb(struct super_block *sb); | 623 | int 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 | */ | ||
105 | void *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 | */ |
118 | int logfs_statfs(struct dentry *dentry, struct kstatfs *stats) | 96 | int 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 |
115 | extern void * memchr(const void *,int,__kernel_size_t); | 115 | extern void * memchr(const void *,int,__kernel_size_t); |
116 | #endif | 116 | #endif |
117 | void *memchr_inv(const void *s, int c, size_t n); | ||
117 | 118 | ||
118 | extern char *kstrdup(const char *s, gfp_t gfp); | 119 | extern char *kstrdup(const char *s, gfp_t gfp); |
119 | extern char *kstrndup(const char *s, size_t len, gfp_t gfp); | 120 | extern 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 | } |
757 | EXPORT_SYMBOL(memchr); | 757 | EXPORT_SYMBOL(memchr); |
758 | #endif | 758 | #endif |
759 | |||
760 | static 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 | */ | ||
780 | void *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 | } | ||
812 | EXPORT_SYMBOL(memchr_inv); | ||
@@ -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) |