Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

slub: convert SLAB_DEBUG_FREE to SLAB_CONSISTENCY_CHECKS

SLAB_DEBUG_FREE allows expensive consistency checks at free to be turned
on or off. Expand its use to be able to turn off all consistency
checks. This gives a nice speed up if you only want features such as
poisoning or tracing.

Credit to Mathias Krause for the original work which inspired this
series

Signed-off-by: Laura Abbott <labbott@fedoraproject.org>
Acked-by: Christoph Lameter <cl@linux.com>
Cc: Pekka Enberg <penberg@kernel.org>
Cc: David Rientjes <rientjes@google.com>
Cc: Joonsoo Kim <js1304@gmail.com>
Cc: Kees Cook <keescook@chromium.org>
Cc: Mathias Krause <minipli@googlemail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Laura Abbott and committed by
Linus Torvalds
becfda68 804aa132

+69 -44
+2 -2
Documentation/vm/slub.txt
··· 35 35 Enable options only for select slabs 36 36 37 37 Possible debug options are 38 - F Sanity checks on (enables SLAB_DEBUG_FREE. Sorry 39 - SLAB legacy issues) 38 + F Sanity checks on (enables SLAB_DEBUG_CONSISTENCY_CHECKS 39 + Sorry SLAB legacy issues) 40 40 Z Red zoning 41 41 P Poisoning (object and padding) 42 42 U User tracking (free and alloc)
+1 -1
include/linux/slab.h
··· 20 20 * Flags to pass to kmem_cache_create(). 21 21 * The ones marked DEBUG are only valid if CONFIG_DEBUG_SLAB is set. 22 22 */ 23 - #define SLAB_DEBUG_FREE 0x00000100UL /* DEBUG: Perform (expensive) checks on free */ 23 + #define SLAB_CONSISTENCY_CHECKS 0x00000100UL /* DEBUG: Perform (expensive) checks on alloc/free */ 24 24 #define SLAB_RED_ZONE 0x00000400UL /* DEBUG: Red zone objs in a cache */ 25 25 #define SLAB_POISON 0x00000800UL /* DEBUG: Poison objects */ 26 26 #define SLAB_HWCACHE_ALIGN 0x00002000UL /* Align objs on cache lines */
+3 -2
mm/slab.h
··· 125 125 #define SLAB_DEBUG_FLAGS (SLAB_RED_ZONE | SLAB_POISON | SLAB_STORE_USER) 126 126 #elif defined(CONFIG_SLUB_DEBUG) 127 127 #define SLAB_DEBUG_FLAGS (SLAB_RED_ZONE | SLAB_POISON | SLAB_STORE_USER | \ 128 - SLAB_TRACE | SLAB_DEBUG_FREE) 128 + SLAB_TRACE | SLAB_CONSISTENCY_CHECKS) 129 129 #else 130 130 #define SLAB_DEBUG_FLAGS (0) 131 131 #endif ··· 311 311 * to not do even the assignment. In that case, slab_equal_or_root 312 312 * will also be a constant. 313 313 */ 314 - if (!memcg_kmem_enabled() && !unlikely(s->flags & SLAB_DEBUG_FREE)) 314 + if (!memcg_kmem_enabled() && 315 + !unlikely(s->flags & SLAB_CONSISTENCY_CHECKS)) 315 316 return s; 316 317 317 318 page = virt_to_head_page(x);
+62 -38
mm/slub.c
··· 160 160 */ 161 161 #define MAX_PARTIAL 10 162 162 163 - #define DEBUG_DEFAULT_FLAGS (SLAB_DEBUG_FREE | SLAB_RED_ZONE | \ 163 + #define DEBUG_DEFAULT_FLAGS (SLAB_CONSISTENCY_CHECKS | SLAB_RED_ZONE | \ 164 164 SLAB_POISON | SLAB_STORE_USER) 165 165 166 166 /* ··· 1007 1007 init_tracking(s, object); 1008 1008 } 1009 1009 1010 - static noinline int alloc_debug_processing(struct kmem_cache *s, 1010 + static inline int alloc_consistency_checks(struct kmem_cache *s, 1011 1011 struct page *page, 1012 1012 void *object, unsigned long addr) 1013 1013 { 1014 1014 if (!check_slab(s, page)) 1015 - goto bad; 1015 + return 0; 1016 1016 1017 1017 if (!check_valid_pointer(s, page, object)) { 1018 1018 object_err(s, page, object, "Freelist Pointer check fails"); 1019 - goto bad; 1019 + return 0; 1020 1020 } 1021 1021 1022 1022 if (!check_object(s, page, object, SLUB_RED_INACTIVE)) 1023 - goto bad; 1023 + return 0; 1024 + 1025 + return 1; 1026 + } 1027 + 1028 + static noinline int alloc_debug_processing(struct kmem_cache *s, 1029 + struct page *page, 1030 + void *object, unsigned long addr) 1031 + { 1032 + if (s->flags & SLAB_CONSISTENCY_CHECKS) { 1033 + if (!alloc_consistency_checks(s, page, object, addr)) 1034 + goto bad; 1035 + } 1024 1036 1025 1037 /* Success perform special debug activities for allocs */ 1026 1038 if (s->flags & SLAB_STORE_USER) ··· 1055 1043 return 0; 1056 1044 } 1057 1045 1046 + static inline int free_consistency_checks(struct kmem_cache *s, 1047 + struct page *page, void *object, unsigned long addr) 1048 + { 1049 + if (!check_valid_pointer(s, page, object)) { 1050 + slab_err(s, page, "Invalid object pointer 0x%p", object); 1051 + return 0; 1052 + } 1053 + 1054 + if (on_freelist(s, page, object)) { 1055 + object_err(s, page, object, "Object already free"); 1056 + return 0; 1057 + } 1058 + 1059 + if (!check_object(s, page, object, SLUB_RED_ACTIVE)) 1060 + return 0; 1061 + 1062 + if (unlikely(s != page->slab_cache)) { 1063 + if (!PageSlab(page)) { 1064 + slab_err(s, page, "Attempt to free object(0x%p) " 1065 + "outside of slab", object); 1066 + } else if (!page->slab_cache) { 1067 + pr_err("SLUB <none>: no slab for object 0x%p.\n", 1068 + object); 1069 + dump_stack(); 1070 + } else 1071 + object_err(s, page, object, 1072 + "page slab pointer corrupt."); 1073 + return 0; 1074 + } 1075 + return 1; 1076 + } 1077 + 1058 1078 /* Supports checking bulk free of a constructed freelist */ 1059 1079 static noinline int free_debug_processing( 1060 1080 struct kmem_cache *s, struct page *page, ··· 1102 1058 spin_lock_irqsave(&n->list_lock, flags); 1103 1059 slab_lock(page); 1104 1060 1105 - if (!check_slab(s, page)) 1106 - goto out; 1061 + if (s->flags & SLAB_CONSISTENCY_CHECKS) { 1062 + if (!check_slab(s, page)) 1063 + goto out; 1064 + } 1107 1065 1108 1066 next_object: 1109 1067 cnt++; 1110 1068 1111 - if (!check_valid_pointer(s, page, object)) { 1112 - slab_err(s, page, "Invalid object pointer 0x%p", object); 1113 - goto out; 1114 - } 1115 - 1116 - if (on_freelist(s, page, object)) { 1117 - object_err(s, page, object, "Object already free"); 1118 - goto out; 1119 - } 1120 - 1121 - if (!check_object(s, page, object, SLUB_RED_ACTIVE)) 1122 - goto out; 1123 - 1124 - if (unlikely(s != page->slab_cache)) { 1125 - if (!PageSlab(page)) { 1126 - slab_err(s, page, "Attempt to free object(0x%p) " 1127 - "outside of slab", object); 1128 - } else if (!page->slab_cache) { 1129 - pr_err("SLUB <none>: no slab for object 0x%p.\n", 1130 - object); 1131 - dump_stack(); 1132 - } else 1133 - object_err(s, page, object, 1134 - "page slab pointer corrupt."); 1135 - goto out; 1069 + if (s->flags & SLAB_CONSISTENCY_CHECKS) { 1070 + if (!free_consistency_checks(s, page, object, addr)) 1071 + goto out; 1136 1072 } 1137 1073 1138 1074 if (s->flags & SLAB_STORE_USER) ··· 1169 1145 for (; *str && *str != ','; str++) { 1170 1146 switch (tolower(*str)) { 1171 1147 case 'f': 1172 - slub_debug |= SLAB_DEBUG_FREE; 1148 + slub_debug |= SLAB_CONSISTENCY_CHECKS; 1173 1149 break; 1174 1150 case 'z': 1175 1151 slub_debug |= SLAB_RED_ZONE; ··· 1473 1449 int order = compound_order(page); 1474 1450 int pages = 1 << order; 1475 1451 1476 - if (kmem_cache_debug(s)) { 1452 + if (s->flags & SLAB_CONSISTENCY_CHECKS) { 1477 1453 void *p; 1478 1454 1479 1455 slab_pad_check(s, page); ··· 4793 4769 4794 4770 static ssize_t sanity_checks_show(struct kmem_cache *s, char *buf) 4795 4771 { 4796 - return sprintf(buf, "%d\n", !!(s->flags & SLAB_DEBUG_FREE)); 4772 + return sprintf(buf, "%d\n", !!(s->flags & SLAB_CONSISTENCY_CHECKS)); 4797 4773 } 4798 4774 4799 4775 static ssize_t sanity_checks_store(struct kmem_cache *s, 4800 4776 const char *buf, size_t length) 4801 4777 { 4802 - s->flags &= ~SLAB_DEBUG_FREE; 4778 + s->flags &= ~SLAB_CONSISTENCY_CHECKS; 4803 4779 if (buf[0] == '1') { 4804 4780 s->flags &= ~__CMPXCHG_DOUBLE; 4805 - s->flags |= SLAB_DEBUG_FREE; 4781 + s->flags |= SLAB_CONSISTENCY_CHECKS; 4806 4782 } 4807 4783 return length; 4808 4784 } ··· 5337 5313 *p++ = 'd'; 5338 5314 if (s->flags & SLAB_RECLAIM_ACCOUNT) 5339 5315 *p++ = 'a'; 5340 - if (s->flags & SLAB_DEBUG_FREE) 5316 + if (s->flags & SLAB_CONSISTENCY_CHECKS) 5341 5317 *p++ = 'F'; 5342 5318 if (!(s->flags & SLAB_NOTRACK)) 5343 5319 *p++ = 't';
+1 -1
tools/vm/slabinfo.c
··· 135 135 "\nValid debug options (FZPUT may be combined)\n" 136 136 "a / A Switch on all debug options (=FZUP)\n" 137 137 "- Switch off all debug options\n" 138 - "f / F Sanity Checks (SLAB_DEBUG_FREE)\n" 138 + "f / F Sanity Checks (SLAB_CONSISTENCY_CHECKS)\n" 139 139 "z / Z Redzoning\n" 140 140 "p / P Poisoning\n" 141 141 "u / U Tracking\n"