aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/slab_def.h2
-rw-r--r--mm/slab.c80
-rw-r--r--mm/slab.h14
-rw-r--r--mm/slab_common.c47
4 files changed, 82 insertions, 61 deletions
diff --git a/include/linux/slab_def.h b/include/linux/slab_def.h
index 8694f7a5d92b..339ba027ade9 100644
--- a/include/linux/slab_def.h
+++ b/include/linux/slab_def.h
@@ -81,7 +81,7 @@ struct kmem_cache {
81#endif 81#endif
82 82
83#ifdef CONFIG_SLAB_FREELIST_RANDOM 83#ifdef CONFIG_SLAB_FREELIST_RANDOM
84 void *random_seq; 84 unsigned int *random_seq;
85#endif 85#endif
86 86
87 struct kmem_cache_node *node[MAX_NUMNODES]; 87 struct kmem_cache_node *node[MAX_NUMNODES];
diff --git a/mm/slab.c b/mm/slab.c
index cc8bbc1e6bc9..763096a247f6 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -1236,61 +1236,6 @@ static void __init set_up_node(struct kmem_cache *cachep, int index)
1236 } 1236 }
1237} 1237}
1238 1238
1239#ifdef CONFIG_SLAB_FREELIST_RANDOM
1240static void freelist_randomize(struct rnd_state *state, freelist_idx_t *list,
1241 size_t count)
1242{
1243 size_t i;
1244 unsigned int rand;
1245
1246 for (i = 0; i < count; i++)
1247 list[i] = i;
1248
1249 /* Fisher-Yates shuffle */
1250 for (i = count - 1; i > 0; i--) {
1251 rand = prandom_u32_state(state);
1252 rand %= (i + 1);
1253 swap(list[i], list[rand]);
1254 }
1255}
1256
1257/* Create a random sequence per cache */
1258static int cache_random_seq_create(struct kmem_cache *cachep, gfp_t gfp)
1259{
1260 unsigned int seed, count = cachep->num;
1261 struct rnd_state state;
1262
1263 if (count < 2)
1264 return 0;
1265
1266 /* If it fails, we will just use the global lists */
1267 cachep->random_seq = kcalloc(count, sizeof(freelist_idx_t), gfp);
1268 if (!cachep->random_seq)
1269 return -ENOMEM;
1270
1271 /* Get best entropy at this stage */
1272 get_random_bytes_arch(&seed, sizeof(seed));
1273 prandom_seed_state(&state, seed);
1274
1275 freelist_randomize(&state, cachep->random_seq, count);
1276 return 0;
1277}
1278
1279/* Destroy the per-cache random freelist sequence */
1280static void cache_random_seq_destroy(struct kmem_cache *cachep)
1281{
1282 kfree(cachep->random_seq);
1283 cachep->random_seq = NULL;
1284}
1285#else
1286static inline int cache_random_seq_create(struct kmem_cache *cachep, gfp_t gfp)
1287{
1288 return 0;
1289}
1290static inline void cache_random_seq_destroy(struct kmem_cache *cachep) { }
1291#endif /* CONFIG_SLAB_FREELIST_RANDOM */
1292
1293
1294/* 1239/*
1295 * Initialisation. Called after the page allocator have been initialised and 1240 * Initialisation. Called after the page allocator have been initialised and
1296 * before smp_init(). 1241 * before smp_init().
@@ -2535,7 +2480,7 @@ static void cache_init_objs_debug(struct kmem_cache *cachep, struct page *page)
2535union freelist_init_state { 2480union freelist_init_state {
2536 struct { 2481 struct {
2537 unsigned int pos; 2482 unsigned int pos;
2538 freelist_idx_t *list; 2483 unsigned int *list;
2539 unsigned int count; 2484 unsigned int count;
2540 unsigned int rand; 2485 unsigned int rand;
2541 }; 2486 };
@@ -2554,7 +2499,7 @@ static bool freelist_state_initialize(union freelist_init_state *state,
2554 unsigned int rand; 2499 unsigned int rand;
2555 2500
2556 /* Use best entropy available to define a random shift */ 2501 /* Use best entropy available to define a random shift */
2557 get_random_bytes_arch(&rand, sizeof(rand)); 2502 rand = get_random_int();
2558 2503
2559 /* Use a random state if the pre-computed list is not available */ 2504 /* Use a random state if the pre-computed list is not available */
2560 if (!cachep->random_seq) { 2505 if (!cachep->random_seq) {
@@ -2576,13 +2521,20 @@ static freelist_idx_t next_random_slot(union freelist_init_state *state)
2576 return (state->list[state->pos++] + state->rand) % state->count; 2521 return (state->list[state->pos++] + state->rand) % state->count;
2577} 2522}
2578 2523
2524/* Swap two freelist entries */
2525static void swap_free_obj(struct page *page, unsigned int a, unsigned int b)
2526{
2527 swap(((freelist_idx_t *)page->freelist)[a],
2528 ((freelist_idx_t *)page->freelist)[b]);
2529}
2530
2579/* 2531/*
2580 * Shuffle the freelist initialization state based on pre-computed lists. 2532 * Shuffle the freelist initialization state based on pre-computed lists.
2581 * return true if the list was successfully shuffled, false otherwise. 2533 * return true if the list was successfully shuffled, false otherwise.
2582 */ 2534 */
2583static bool shuffle_freelist(struct kmem_cache *cachep, struct page *page) 2535static bool shuffle_freelist(struct kmem_cache *cachep, struct page *page)
2584{ 2536{
2585 unsigned int objfreelist = 0, i, count = cachep->num; 2537 unsigned int objfreelist = 0, i, rand, count = cachep->num;
2586 union freelist_init_state state; 2538 union freelist_init_state state;
2587 bool precomputed; 2539 bool precomputed;
2588 2540
@@ -2607,7 +2559,15 @@ static bool shuffle_freelist(struct kmem_cache *cachep, struct page *page)
2607 * Later use a pre-computed list for speed. 2559 * Later use a pre-computed list for speed.
2608 */ 2560 */
2609 if (!precomputed) { 2561 if (!precomputed) {
2610 freelist_randomize(&state.rnd_state, page->freelist, count); 2562 for (i = 0; i < count; i++)
2563 set_free_obj(page, i, i);
2564
2565 /* Fisher-Yates shuffle */
2566 for (i = count - 1; i > 0; i--) {
2567 rand = prandom_u32_state(&state.rnd_state);
2568 rand %= (i + 1);
2569 swap_free_obj(page, i, rand);
2570 }
2611 } else { 2571 } else {
2612 for (i = 0; i < count; i++) 2572 for (i = 0; i < count; i++)
2613 set_free_obj(page, i, next_random_slot(&state)); 2573 set_free_obj(page, i, next_random_slot(&state));
@@ -3979,7 +3939,7 @@ static int enable_cpucache(struct kmem_cache *cachep, gfp_t gfp)
3979 int shared = 0; 3939 int shared = 0;
3980 int batchcount = 0; 3940 int batchcount = 0;
3981 3941
3982 err = cache_random_seq_create(cachep, gfp); 3942 err = cache_random_seq_create(cachep, cachep->num, gfp);
3983 if (err) 3943 if (err)
3984 goto end; 3944 goto end;
3985 3945
diff --git a/mm/slab.h b/mm/slab.h
index dedb1a920fb8..5fa8b8f20eb1 100644
--- a/mm/slab.h
+++ b/mm/slab.h
@@ -42,6 +42,7 @@ struct kmem_cache {
42#include <linux/kmemcheck.h> 42#include <linux/kmemcheck.h>
43#include <linux/kasan.h> 43#include <linux/kasan.h>
44#include <linux/kmemleak.h> 44#include <linux/kmemleak.h>
45#include <linux/random.h>
45 46
46/* 47/*
47 * State of the slab allocator. 48 * State of the slab allocator.
@@ -464,4 +465,17 @@ int memcg_slab_show(struct seq_file *m, void *p);
464 465
465void ___cache_free(struct kmem_cache *cache, void *x, unsigned long addr); 466void ___cache_free(struct kmem_cache *cache, void *x, unsigned long addr);
466 467
468#ifdef CONFIG_SLAB_FREELIST_RANDOM
469int cache_random_seq_create(struct kmem_cache *cachep, unsigned int count,
470 gfp_t gfp);
471void cache_random_seq_destroy(struct kmem_cache *cachep);
472#else
473static inline int cache_random_seq_create(struct kmem_cache *cachep,
474 unsigned int count, gfp_t gfp)
475{
476 return 0;
477}
478static inline void cache_random_seq_destroy(struct kmem_cache *cachep) { }
479#endif /* CONFIG_SLAB_FREELIST_RANDOM */
480
467#endif /* MM_SLAB_H */ 481#endif /* MM_SLAB_H */
diff --git a/mm/slab_common.c b/mm/slab_common.c
index 82317abb03ed..da88c1588752 100644
--- a/mm/slab_common.c
+++ b/mm/slab_common.c
@@ -1030,6 +1030,53 @@ void *kmalloc_order_trace(size_t size, gfp_t flags, unsigned int order)
1030EXPORT_SYMBOL(kmalloc_order_trace); 1030EXPORT_SYMBOL(kmalloc_order_trace);
1031#endif 1031#endif
1032 1032
1033#ifdef CONFIG_SLAB_FREELIST_RANDOM
1034/* Randomize a generic freelist */
1035static void freelist_randomize(struct rnd_state *state, unsigned int *list,
1036 size_t count)
1037{
1038 size_t i;
1039 unsigned int rand;
1040
1041 for (i = 0; i < count; i++)
1042 list[i] = i;
1043
1044 /* Fisher-Yates shuffle */
1045 for (i = count - 1; i > 0; i--) {
1046 rand = prandom_u32_state(state);
1047 rand %= (i + 1);
1048 swap(list[i], list[rand]);
1049 }
1050}
1051
1052/* Create a random sequence per cache */
1053int cache_random_seq_create(struct kmem_cache *cachep, unsigned int count,
1054 gfp_t gfp)
1055{
1056 struct rnd_state state;
1057
1058 if (count < 2 || cachep->random_seq)
1059 return 0;
1060
1061 cachep->random_seq = kcalloc(count, sizeof(unsigned int), gfp);
1062 if (!cachep->random_seq)
1063 return -ENOMEM;
1064
1065 /* Get best entropy at this stage of boot */
1066 prandom_seed_state(&state, get_random_long());
1067
1068 freelist_randomize(&state, cachep->random_seq, count);
1069 return 0;
1070}
1071
1072/* Destroy the per-cache random freelist sequence */
1073void cache_random_seq_destroy(struct kmem_cache *cachep)
1074{
1075 kfree(cachep->random_seq);
1076 cachep->random_seq = NULL;
1077}
1078#endif /* CONFIG_SLAB_FREELIST_RANDOM */
1079
1033#ifdef CONFIG_SLABINFO 1080#ifdef CONFIG_SLABINFO
1034 1081
1035#ifdef CONFIG_SLAB 1082#ifdef CONFIG_SLAB