-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathlinux-mm-for-4.14.113.patch
4580 lines (4307 loc) · 174 KB
/
linux-mm-for-4.14.113.patch
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
From 5c319b949f0a175e798e9ac26a078db1e1bb43e3 Mon Sep 17 00:00:00 2001
From: Dongli Zhang <[email protected]>
Date: Tue, 11 Feb 2020 14:06:26 -0800
Subject: [PATCH 1/1] linux-mm-for-4.14.113
Signed-off-by: Dongli Zhang <[email protected]>
---
include/linux/memcontrol.h | 14 +
include/linux/mm.h | 3 +
include/linux/mm_types.h | 34 +
include/linux/slab.h | 86 ++
include/linux/slub_def.h | 97 ++
mm/kasan/kasan.c | 5 +
mm/slab.h | 63 ++
mm/slab_common.c | 202 ++++
mm/slub.c | 2078 ++++++++++++++++++++++++++++++++++++
tools/vm/slabinfo.c | 10 +
10 files changed, 2592 insertions(+)
diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
index 69966c46..4df90172 100644
--- a/include/linux/memcontrol.h
+++ b/include/linux/memcontrol.h
@@ -1118,6 +1118,20 @@ void memcg_put_cache_ids(void);
#define for_each_memcg_cache_index(_idx) \
for ((_idx) = 0; (_idx) < memcg_nr_cache_ids; (_idx)++)
+/*
+ * called by:
+ * - fs/pipe.c|148| <<anon_pipe_buf_steal>> if (memcg_kmem_enabled())
+ * - mm/list_lru.c|70| <<mem_cgroup_from_kmem>> if (!memcg_kmem_enabled())
+ * - mm/page_alloc.c|1049| <<free_pages_prepare>> if (memcg_kmem_enabled() && PageKmemcg(page))
+ * - mm/page_alloc.c|4201| <<__alloc_pages_nodemask>> if (memcg_kmem_enabled() && (gfp_mask & __GFP_ACCOUNT) && page &&
+ * - mm/slab.h|277| <<memcg_charge_slab>> if (!memcg_kmem_enabled())
+ * - mm/slab.h|287| <<memcg_uncharge_slab>> if (!memcg_kmem_enabled())
+ * - mm/slab.h|366| <<cache_from_obj>> if (!memcg_kmem_enabled() &&
+ * - mm/slab.h|432| <<slab_pre_alloc_hook>> if (memcg_kmem_enabled() &&
+ * - mm/slab.h|453| <<slab_post_alloc_hook>> if (memcg_kmem_enabled())
+ * - mm/vmscan.c|468| <<shrink_slab>> if (memcg && (!memcg_kmem_enabled() || !mem_cgroup_online(memcg)))
+ * - mm/vmscan.c|497| <<shrink_slab>> if (memcg_kmem_enabled() &&
+ */
static inline bool memcg_kmem_enabled(void)
{
return static_branch_unlikely(&memcg_kmem_enabled_key);
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 58f2263d..31fc7006 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -2425,6 +2425,9 @@ extern void __kernel_map_pages(struct page *page, int numpages, int enable);
static inline bool debug_pagealloc_enabled(void)
{
+ /*
+ * _debug_pagealloc_enabled定义在page_alloc.c
+ */
return _debug_pagealloc_enabled;
}
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index e41ef532..26adb790 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -92,6 +92,40 @@ struct page {
unsigned int active; /* SLAB */
struct { /* SLUB */
+ /*
+ * 修改page->inuse的地方:
+ * - mm/slub.c|692| <<set_page_slub_counters>> page->inuse = tmp.inuse;
+ * - mm/slub.c|1509| <<on_freelist>> page->inuse = page->objects;
+ * - mm/slub.c|1807| <<alloc_debug_processing>> page->inuse = page->objects;
+ * - mm/slub.c|1534| <<on_freelist>> page->inuse = page->objects - nr;
+ * - mm/slub.c|2428| <<allocate_slab>> page->inuse = page->objects;
+ * - mm/slub.c|4455| <<early_kmem_cache_node_alloc>> page->inuse = 1;
+ * - mm/slub.c|2699| <<acquire_slab>> new.inuse = page->objects;
+ * - mm/slub.c|3001| <<deactivate_slab>> new.inuse--;
+ * - mm/slub.c|3035| <<deactivate_slab>> new.inuse--;
+ * - mm/slub.c|3463| <<get_freelist>> new.inuse = page->objects;
+ * - mm/slub.c|3877| <<__slab_free>> new.inuse -= cnt;
+ *
+ * 使用page->inuse的地方:
+ * - mm/slub.c|1072| <<print_page_info>> page, page->objects, page->inuse, page->freelist, page->flags);
+ * - mm/slub.c|1468| <<check_slab>> if (page->inuse > page->objects) {
+ * - mm/slub.c|1470| <<check_slab>> page->inuse, page->objects);
+ * - mm/slub.c|1531| <<on_freelist>> if (page->inuse != page->objects - nr) {
+ * - mm/slub.c|1533| <<on_freelist>> page->inuse, page->objects - nr);
+ * - mm/slub.c|1589| <<trace>> object, page->inuse,
+ * - mm/slub.c|3233| <<put_cpu_partial>> pobjects += page->objects - page->inuse;
+ * - mm/slub.c|3332| <<count_free>> return page->objects - page->inuse;
+ * - mm/slub.c|4798| <<free_partial>> if (!page->inuse) {
+ * - mm/slub.c|5059| <<__kmem_cache_shrink>> int free = page->objects - page->inuse;
+ * - mm/slub.c|5468| <<count_inuse>> return page->inuse;
+ * - mm/slub.c|5932| <<show_slab_objects>> x = page->inuse;
+ * - mm/slub.c|3043| <<deactivate_slab>> if (!new.inuse && n->nr_partial >= s->min_partial)
+ * - mm/slub.c|3163| <<unfreeze_partials>> if (unlikely(!new.inuse && n->nr_partial >= s->min_partial)) {
+ * - mm/slub.c|3878| <<__slab_free>> if ((!new.inuse || !prior) && !was_frozen) {
+ * - mm/slub.c|3930| <<__slab_free>> if (unlikely(!new.inuse && n->nr_partial >= s->min_partial))
+ *
+ * struct page结构体中inuse代表已经使用的obj数量
+ */
unsigned inuse:16;
unsigned objects:15;
unsigned frozen:1;
diff --git a/include/linux/slab.h b/include/linux/slab.h
index ae5ed649..bb5a55ec 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -21,8 +21,38 @@
* Flags to pass to kmem_cache_create().
* The ones marked DEBUG are only valid if CONFIG_DEBUG_SLAB is set.
*/
+/*
+ * slub中使用SLAB_CONSISTENCY_CHECKS的例子 (当slub_debug设置了f的时候):
+ * - mm/slub.c|313| <<DEBUG_DEFAULT_FLAGS>> #define DEBUG_DEFAULT_FLAGS (SLAB_CONSISTENCY_CHECKS | SLAB_RED_ZONE | \
+ * - mm/slub.c|320| <<SLAB_NO_CMPXCHG>> #define SLAB_NO_CMPXCHG (SLAB_CONSISTENCY_CHECKS | SLAB_STORE_USER | \
+ * - mm/slub.c|1786| <<alloc_debug_processing>> if (s->flags & SLAB_CONSISTENCY_CHECKS) {
+ * - mm/slub.c|1882| <<free_debug_processing>> if (s->flags & SLAB_CONSISTENCY_CHECKS) {
+ * - mm/slub.c|1890| <<free_debug_processing>> if (s->flags & SLAB_CONSISTENCY_CHECKS) {
+ * - mm/slub.c|1949| <<setup_slub_debug>> slub_debug |= SLAB_CONSISTENCY_CHECKS;
+ * - mm/slub.c|2381| <<__free_slab>> if (s->flags & SLAB_CONSISTENCY_CHECKS) {
+ * - mm/slub.c|5988| <<sanity_checks_show>> return sprintf(buf, "%d\n", !!(s->flags & SLAB_CONSISTENCY_CHECKS));
+ * - mm/slub.c|5994| <<sanity_checks_store>> s->flags &= ~SLAB_CONSISTENCY_CHECKS;
+ * - mm/slub.c|5997| <<sanity_checks_store>> s->flags |= SLAB_CONSISTENCY_CHECKS;
+ * - mm/slub.c|6532| <<create_unique_id>> if (s->flags & SLAB_CONSISTENCY_CHECKS)
+ */
#define SLAB_CONSISTENCY_CHECKS 0x00000100UL /* DEBUG: Perform (expensive) checks on alloc/free */
#define SLAB_RED_ZONE 0x00000400UL /* DEBUG: Red zone objs in a cache */
+/*
+ * slub中使用SLAB_POISON的地方:
+ * - mm/slab_common.c|86| <<SLAB_NEVER_MERGE>> #define SLAB_NEVER_MERGE (SLAB_RED_ZONE | SLAB_POISON | SLAB_STORE_USER | \
+ * - mm/slub.c|326| <<DEBUG_DEFAULT_FLAGS>> SLAB_POISON | SLAB_STORE_USER)
+ * - mm/slub.c|350| <<DEBUG_METADATA_FLAGS>> #define DEBUG_METADATA_FLAGS (SLAB_RED_ZONE | SLAB_POISON | SLAB_STORE_USER)
+ * - mm/slub.c|1535| <<slab_pad_check>> if (!(s->flags & SLAB_POISON))
+ * - mm/slub.c|1616| <<check_object>> if ((s->flags & SLAB_POISON) && s->object_size < s->inuse) {
+ * - mm/slub.c|1623| <<check_object>> if (s->flags & SLAB_POISON) {
+ * - mm/slub.c|2277| <<setup_slub_debug>> slub_debug |= SLAB_POISON;
+ * - mm/slub.c|2733| <<allocate_slab>> if (unlikely(s->flags & SLAB_POISON))
+ * - mm/slub.c|5263| <<calculate_sizes>> if ((flags & SLAB_POISON) && !(flags & SLAB_TYPESAFE_BY_RCU) &&
+ * - mm/slub.c|5291| <<calculate_sizes>> if (((flags & (SLAB_TYPESAFE_BY_RCU | SLAB_POISON)) ||
+ * - mm/slub.c|7093| <<poison_show>> return sprintf(buf, "%d\n", !!(s->flags & SLAB_POISON));
+ * - mm/slub.c|7102| <<poison_store>> s->flags &= ~SLAB_POISON;
+ * - mm/slub.c|7104| <<poison_store>> s->flags |= SLAB_POISON;
+ */
#define SLAB_POISON 0x00000800UL /* DEBUG: Poison objects */
#define SLAB_HWCACHE_ALIGN 0x00002000UL /* Align objs on cache lines */
#define SLAB_CACHE_DMA 0x00004000UL /* Use GFP_DMA memory */
@@ -65,8 +95,55 @@
*
* Note that SLAB_TYPESAFE_BY_RCU was originally named SLAB_DESTROY_BY_RCU.
*/
+/*
+ * 在以下使用SLAB_TYPESAFE_BY_RCU:
+ * - net/dccp/ipv4.c|961| <<global>> .slab_flags = SLAB_TYPESAFE_BY_RCU,
+ * - net/dccp/ipv6.c|1048| <<global>> .slab_flags = SLAB_TYPESAFE_BY_RCU,
+ * - net/ipv4/tcp_ipv4.c|2429| <<global>> .slab_flags = SLAB_TYPESAFE_BY_RCU,
+ * - net/ipv6/tcp_ipv6.c|1947| <<global>> .slab_flags = SLAB_TYPESAFE_BY_RCU,
+ * - net/llc/af_llc.c|145| <<global>> .slab_flags = SLAB_TYPESAFE_BY_RCU,
+ * - net/smc/af_smc.c|104| <<global>> .slab_flags = SLAB_TYPESAFE_BY_RCU,
+ * - drivers/gpu/drm/i915/i915_gem.c|4913| <<i915_gem_load_init>> SLAB_TYPESAFE_BY_RCU);
+ * - drivers/gpu/drm/i915/selftests/mock_gem_device.c|203| <<mock_gem_device>> SLAB_TYPESAFE_BY_RCU);
+ * - drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c|1118| <<ldlm_init>> SLAB_TYPESAFE_BY_RCU, NULL);
+ * - fs/jbd2/journal.c|2384| <<jbd2_journal_init_journal_head_cache>> SLAB_TEMPORARY | SLAB_TYPESAFE_BY_RCU,
+ * - fs/kernfs/mount.c|418| <<kernfs_init>> SLAB_PANIC | SLAB_TYPESAFE_BY_RCU,
+ * - kernel/fork.c|2220| <<proc_caches_init>> SLAB_HWCACHE_ALIGN|SLAB_PANIC|SLAB_TYPESAFE_BY_RCU|
+ * - mm/kasan/kasan.c|350| <<kasan_cache_create>> if (cache->flags & SLAB_TYPESAFE_BY_RCU || cache->ctor ||
+ * - mm/kasan/kasan.c|503| <<kasan_poison_slab_free>> if (unlikely(cache->flags & SLAB_TYPESAFE_BY_RCU))
+ * - mm/kasan/kasan.c|514| <<kasan_slab_free>> if (unlikely(cache->flags & SLAB_TYPESAFE_BY_RCU))
+ * - mm/rmap.c|435| <<anon_vma_init>> 0, SLAB_TYPESAFE_BY_RCU|SLAB_PANIC|SLAB_ACCOUNT,
+ * - mm/slab.c|1720| <<slab_destroy>> if (unlikely(cachep->flags & SLAB_TYPESAFE_BY_RCU))
+ * - mm/slab.c|1916| <<set_objfreelist_slab_cache>> if (cachep->ctor || flags & SLAB_TYPESAFE_BY_RCU)
+ * - mm/slab.c|2022| <<__kmem_cache_create>> if (!(flags & SLAB_TYPESAFE_BY_RCU))
+ * - mm/slab.h|130| <<SLAB_CORE_FLAGS>> SLAB_TYPESAFE_BY_RCU | SLAB_DEBUG_OBJECTS )
+ * - mm/slab.h|409| <<slab_ksize>> if (s->flags & (SLAB_TYPESAFE_BY_RCU | SLAB_STORE_USER))
+ * - mm/slab_common.c|87| <<SLAB_NEVER_MERGE>> SLAB_TRACE | SLAB_TYPESAFE_BY_RCU | SLAB_NOLEAKTRACE | \
+ * - mm/slab_common.c|703| <<shutdown_cache>> if (s->flags & SLAB_TYPESAFE_BY_RCU) {
+ * - mm/slob.c|529| <<__kmem_cache_create>> if (flags & SLAB_TYPESAFE_BY_RCU) {
+ * - mm/slob.c|604| <<kmem_cache_free>> if (unlikely(c->flags & SLAB_TYPESAFE_BY_RCU)) {
+ * - mm/slub.c|2889| <<free_slab>> if (unlikely(s->flags & SLAB_TYPESAFE_BY_RCU)) {
+ * - mm/slub.c|4670| <<slab_free>> if (s->flags & SLAB_KASAN && !(s->flags & SLAB_TYPESAFE_BY_RCU))
+ * - mm/slub.c|5263| <<calculate_sizes>> if ((flags & SLAB_POISON) && !(flags & SLAB_TYPESAFE_BY_RCU) &&
+ * - mm/slub.c|5291| <<calculate_sizes>> if (((flags & (SLAB_TYPESAFE_BY_RCU | SLAB_POISON)) ||
+ * - mm/slub.c|5426| <<kmem_cache_open>> if (need_reserve_slab_rcu && (s->flags & SLAB_TYPESAFE_BY_RCU))
+ * - mm/slub.c|7006| <<destroy_by_rcu_show>> return sprintf(buf, "%d\n", !!(s->flags & SLAB_TYPESAFE_BY_RCU));
+ * - net/netfilter/nf_conntrack_core.c|2069| <<nf_conntrack_init_start>> SLAB_TYPESAFE_BY_RCU | SLAB_HWCACHE_ALIGN, NULL);
+ */
#define SLAB_TYPESAFE_BY_RCU 0x00080000UL /* Defer freeing slabs to RCU */
#define SLAB_MEM_SPREAD 0x00100000UL /* Spread some memory over cpuset */
+/*
+ * 在以下使用SLAB_TRACE:
+ * - mm/slab.h|136| <<SLAB_DEBUG_FLAGS>> SLAB_TRACE | SLAB_CONSISTENCY_CHECKS)
+ * - mm/slab.h|160| <<SLAB_FLAGS_PERMITTED>> SLAB_TRACE | \
+ * - mm/slab_common.c|43| <<SLAB_NEVER_MERGE>> SLAB_TRACE | SLAB_TYPESAFE_BY_RCU | SLAB_NOLEAKTRACE | \
+ * - mm/slub.c|321| <<SLAB_NO_CMPXCHG>> SLAB_TRACE)
+ * - mm/slub.c|1481| <<trace>> if (s->flags & SLAB_TRACE) {
+ * - mm/slub.c|1751| <<setup_slub_debug>> slub_debug |= SLAB_TRACE;
+ * - mm/slub.c|5795| <<trace_show>> return sprintf(buf, "%d\n", !!(s->flags & SLAB_TRACE));
+ * - mm/slub.c|5809| <<trace_store>> s->flags &= ~SLAB_TRACE;
+ * - mm/slub.c|5812| <<trace_store>> s->flags |= SLAB_TRACE;
+ */
#define SLAB_TRACE 0x00200000UL /* Trace allocations and frees */
/* Flag to prevent checks on free */
@@ -79,6 +156,15 @@
#define SLAB_NOLEAKTRACE 0x00800000UL /* Avoid kmemleak tracing */
#ifdef CONFIG_FAILSLAB
+/*
+ * 在以下使用SLAB_FAILSLAB:
+ * - mm/failslab.c|29| <<should_failslab>> if (failslab.cache_filter && !(s->flags & SLAB_FAILSLAB))
+ * - mm/slab_common.c|88| <<SLAB_NEVER_MERGE>> SLAB_FAILSLAB | SLAB_KASAN)
+ * - mm/slub.c|2286| <<setup_slub_debug>> slub_debug |= SLAB_FAILSLAB;
+ * - mm/slub.c|7175| <<failslab_show>> return sprintf(buf, "%d\n", !!(s->flags & SLAB_FAILSLAB));
+ * - mm/slub.c|7184| <<failslab_store>> s->flags &= ~SLAB_FAILSLAB;
+ * - mm/slub.c|7186| <<failslab_store>> s->flags |= SLAB_FAILSLAB;
+ */
# define SLAB_FAILSLAB 0x02000000UL /* Fault injection mark */
#else
# define SLAB_FAILSLAB 0x00000000UL
diff --git a/include/linux/slub_def.h b/include/linux/slub_def.h
index f8ced87a..1ac4d159 100644
--- a/include/linux/slub_def.h
+++ b/include/linux/slub_def.h
@@ -43,6 +43,14 @@ struct kmem_cache_cpu {
unsigned long tid; /* Globally unique transaction id */
struct page *page; /* The slab from which we are allocating */
#ifdef CONFIG_SLUB_CPU_PARTIAL
+ /*
+ * kmem_cache_cpu->partial使用的例子:
+ * - include/linux/slub_def.h|54| <<slub_percpu_partial>> #define slub_percpu_partial(c) ((c)->partial)
+ * - mm/slub.c|3133| <<unfreeze_partials>> while ((page = c->partial)) {
+ * - mm/slub.c|3137| <<unfreeze_partials>> c->partial = page->next;
+ * - mm/slub.c|3212| <<put_cpu_partial>> oldpage = this_cpu_read(s->cpu_slab->partial);
+ * - mm/slub.c|3240| <<put_cpu_partial>> } while (this_cpu_cmpxchg(s->cpu_slab->partial, oldpage, page)
+ */
struct page *partial; /* Partially allocated frozen slabs */
#endif
#ifdef CONFIG_SLUB_STATS
@@ -51,13 +59,33 @@ struct kmem_cache_cpu {
};
#ifdef CONFIG_SLUB_CPU_PARTIAL
+/*
+ * 在以下调用slub_percpu_partial():
+ * - include/linux/slub_def.h|62| <<slub_set_percpu_partial>> slub_percpu_partial(c) = (p)->next; \
+ * - include/linux/slub_def.h|66| <<slub_percpu_partial_read_once>> #define slub_percpu_partial_read_once(c) READ_ONCE(slub_percpu_partial(c))
+ * - mm/slub.c|3290| <<has_cpu_slab>> return c->page || slub_percpu_partial(c);
+ * - mm/slub.c|3565| <<___slab_alloc>> if (slub_percpu_partial(c)) {
+ * - mm/slub.c|3566| <<___slab_alloc>> page = c->page = slub_percpu_partial(c);
+ * - mm/slub.c|6207| <<slabs_cpu_partial_show>> page = slub_percpu_partial(per_cpu_ptr(s->cpu_slab, cpu));
+ * - mm/slub.c|6221| <<slabs_cpu_partial_show>> page = slub_percpu_partial(per_cpu_ptr(s->cpu_slab, cpu));
+ */
#define slub_percpu_partial(c) ((c)->partial)
+/*
+ * called by:
+ * - mm/slub.c|2608| <<___slab_alloc>> slub_set_percpu_partial(c, page);
+ */
#define slub_set_percpu_partial(c, p) \
({ \
slub_percpu_partial(c) = (p)->next; \
})
+/*
+ * called by:
+ * - mm/slub.c|5977| <<show_slab_objects>> page = slub_percpu_partial_read_once(c);
+ *
+ * 如果c->partial存在
+ */
#define slub_percpu_partial_read_once(c) READ_ONCE(slub_percpu_partial(c))
#else
#define slub_percpu_partial(c) NULL
@@ -83,9 +111,51 @@ struct kmem_cache {
struct kmem_cache_cpu __percpu *cpu_slab;
/* Used for retriving partial slabs etc */
unsigned long flags;
+ /*
+ * 在以下使用kmem_cache->min_partial:
+ * - mm/slub.c|6558| <<global>> SLAB_ATTR(min_partial);
+ * - mm/slub.c|2960| <<get_any_partial>> n->nr_partial > s->min_partial) {
+ * - mm/slub.c|3202| <<deactivate_slab>> if (!new.inuse && n->nr_partial >= s->min_partial)
+ * - mm/slub.c|3356| <<unfreeze_partials>> if (unlikely(!new.inuse && n->nr_partial >= s->min_partial)) {
+ * - mm/slub.c|4267| <<__slab_free>> if (unlikely(!new.inuse && n->nr_partial >= s->min_partial))
+ * - mm/slub.c|4896| <<set_min_partial>> s->min_partial = min;
+ * - mm/slub.c|5536| <<__kmemcg_cache_deactivate>> s->min_partial = 0;
+ * - mm/slub.c|6542| <<min_partial_show>> return sprintf(buf, "%lu\n", s->min_partial);
+ *
+ * 根据MIM_PARTIAL猜测Mininum number of partial slabs. These will be left on the partial
+ * lists even if they are empty. kmem_cache_shrink may reclaim them.
+ * 根据MAX_PARTIAL猜测Maximum number of desirable partial slabs.
+ * The existence of more partial slabs makes kmem_cache_shrink
+ * sort the partial list by the number of objects in use.
+ */
unsigned long min_partial;
int size; /* The size of an object including meta data */
int object_size; /* The size of an object without meta data */
+ /*
+ * 设置kmem_cache->offset的地方:
+ * - mm/slub.c|4905| <<calculate_sizes>> s->offset = size;
+ * - mm/slub.c|5000| <<kmem_cache_open>> s->offset = 0
+ * 其他使用kmem_cache->offset的地方:
+ * - mm/slub.c|534| <<get_freepointer>> return freelist_dereference(s, object + s->offset);
+ * - mm/slub.c|548| <<prefetch_freepointer>> prefetch(freelist_dereference(s, object + s->offset));
+ * - mm/slub.c|574| <<get_freepointer_safe>> freepointer_addr = (unsigned long )object + s->offset;
+ * - mm/slub.c|599| <<set_freepointer>> unsigned long freeptr_addr = (unsigned long )object + s->offset;
+ * - mm/slub.c|1040| <<get_track>> if (s->offset)
+ * - mm/slub.c|1041| <<get_track>> p = object + s->offset + sizeof(void *);
+ * - mm/slub.c|1245| <<print_trailer>> if (s->offset)
+ * - mm/slub.c|1246| <<print_trailer>> off = s->offset + sizeof(void *);
+ * - mm/slub.c|1503| <<check_pad_bytes>> if (s->offset)
+ * - mm/slub.c|1641| <<check_object>> if (!s->offset && val == SLUB_RED_ACTIVE)
+ * - mm/slub.c|2894| <<free_slab>> int offset = (PAGE_SIZE << order) - s->reserved;
+ * - mm/slub.c|5490| <<kmem_cache_open>> oo_order(s->oo), s->offset, flags);
+ * - mm/slub.c|5690| <<__check_heap_object>> offset = (ptr - page_address(page)) % s->size;
+ *
+ * 就是在calculate_sizes()设置, 在以下条件设置:
+ * 4898 if (((flags & (SLAB_TYPESAFE_BY_RCU | SLAB_POISON)) ||
+ * 4899 s->ctor)) {
+ * 当slub_debug=ZUF(没有P)的时候, kmalloc-128的s->offset=0
+ * 当slub_debug=PZUF(有P)的时候, kmalloc-128的s->offset=136
+ */
int offset; /* Free pointer offset. */
#ifdef CONFIG_SLUB_CPU_PARTIAL
/* Number of per cpu partial objects to keep around */
@@ -99,9 +169,36 @@ struct kmem_cache {
gfp_t allocflags; /* gfp flags to use on each alloc */
int refcount; /* Refcount for slab cache destroy */
void (*ctor)(void *);
+ /*
+ * 修改kmem_cache->inuse的地方:
+ * - mm/slub.c|5371| <<__kmem_cache_alias>> s->inuse = max_t(int , s->inuse, ALIGN(size, sizeof(void *)));
+ * - mm/slub.c|4607| <<calculate_sizes>> s->inuse = size;
+ * - mm/slub.c|1405| <<check_object>> s->inuse - s->object_size);
+ * - mm/slub.c|5375| <<__kmem_cache_alias>> c->inuse = max_t(int , c->inuse,
+ * 使用kmem_cache->inuse的地方:
+ * - mm/slub.c|950| <<get_track>> p = object + s->inuse;
+ * - mm/slub.c|1143| <<print_trailer>> s->inuse - s->object_size);
+ * - mm/slub.c|1148| <<print_trailer>> off = s->inuse;
+ * - mm/slub.c|1206| <<init_object>> memset(p + s->object_size, val, s->inuse - s->object_size);
+ * - mm/slub.c|1298| <<check_pad_bytes>> unsigned long off = s->inuse;
+ * - mm/slub.c|1399| <<check_object>> endobject, val, s->inuse - s->object_size))
+ * - mm/slub.c|1402| <<check_object>> if ((s->flags & SLAB_POISON) && s->object_size < s->inuse) {
+ * - mm/slub.c|2697| <<acquire_slab>> *objects = new.objects - new.inuse;
+ *
+ * Offset to metadata
+ * With that we have determined the number of bytes in actual use
+ * by the object. This is the potential offset to the free pointer.
+ */
int inuse; /* Offset to metadata */
int align; /* Alignment */
int reserved; /* Reserved bytes at the end of slabs */
+ /*
+ * 修改red_left_pad的地方:
+ * - mm/slub.c|5045| <<calculate_sizes>> s->red_left_pad = sizeof(void *);
+ * - mm/slub.c|5046| <<calculate_sizes>> s->red_left_pad = ALIGN(s->red_left_pad, s->align);
+ *
+ * Left redzone padding size
+ */
int red_left_pad; /* Left redzone padding size */
const char *name; /* Name (only for display!) */
struct list_head list; /* List of slab caches */
diff --git a/mm/kasan/kasan.c b/mm/kasan/kasan.c
index 71a43192..23e52193 100644
--- a/mm/kasan/kasan.c
+++ b/mm/kasan/kasan.c
@@ -453,6 +453,11 @@ static inline depot_stack_handle_t save_stack(gfp_t flags)
return depot_save_stack(&trace, flags);
}
+/*
+ * called by:
+ * - mm/kasan/kasan.c|524| <<kasan_slab_free>> set_track(&get_alloc_info(cache, object)->free_track, GFP_NOWAIT);
+ * - mm/kasan/kasan.c|551| <<kasan_kmalloc>> set_track(&get_alloc_info(cache, object)->alloc_track, flags);
+ */
static inline void set_track(struct kasan_track *track, gfp_t flags)
{
track->pid = current->pid;
diff --git a/mm/slab.h b/mm/slab.h
index 485d9fbb..23650fee 100644
--- a/mm/slab.h
+++ b/mm/slab.h
@@ -351,6 +351,13 @@ static inline void memcg_link_cache(struct kmem_cache *s)
#endif /* CONFIG_MEMCG && !CONFIG_SLOB */
+/*
+ * called by:
+ * - mm/slub.c|3033| <<kmem_cache_free>> s = cache_from_obj(s, x);
+ * - mm/slub.c|3094| <<build_detached_freelist>> df->s = cache_from_obj(s, object);
+ * - mm/slab.c|3750| <<kmem_cache_free>> cachep = cache_from_obj(cachep, objp);
+ * - mm/slab.c|3777| <<kmem_cache_free_bulk>> s = cache_from_obj(orig_s, objp);
+ */
static inline struct kmem_cache *cache_from_obj(struct kmem_cache *s, void *x)
{
struct kmem_cache *cachep;
@@ -408,6 +415,14 @@ static inline size_t slab_ksize(const struct kmem_cache *s)
#endif
}
+/*
+ * called by:
+ * - mm/slub.c|2649| <<slab_alloc_node>> s = slab_pre_alloc_hook(s, gfpflags);
+ * - mm/slub.c|3117| <<kmem_cache_alloc_bulk>> s = slab_pre_alloc_hook(s, flags);
+ * - mm/slab.c|3297| <<slab_alloc_node>> cachep = slab_pre_alloc_hook(cachep, flags);
+ * - mm/slab.c|3376| <<slab_alloc>> cachep = slab_pre_alloc_hook(cachep, flags);
+ * - mm/slab.c|3575| <<kmem_cache_alloc_bulk>> s = slab_pre_alloc_hook(s, flags);
+ */
static inline struct kmem_cache *slab_pre_alloc_hook(struct kmem_cache *s,
gfp_t flags)
{
@@ -428,6 +443,16 @@ static inline struct kmem_cache *slab_pre_alloc_hook(struct kmem_cache *s,
return s;
}
+/*
+ * called by:
+ * - mm/slub.c|2764| <<slab_alloc_node>> slab_post_alloc_hook(s, gfpflags, 1, &object);
+ * - mm/slub.c|3200| <<kmem_cache_alloc_bulk>> slab_post_alloc_hook(s, flags, size, p);
+ * - mm/slub.c|3204| <<kmem_cache_alloc_bulk>> slab_post_alloc_hook(s, flags, i, p);
+ * - mm/slab.c|3333| <<slab_alloc_node>> slab_post_alloc_hook(cachep, flags, 1, &ptr);
+ * - mm/slab.c|3390| <<slab_alloc>> slab_post_alloc_hook(cachep, flags, 1, &objp);
+ * - mm/slab.c|3598| <<kmem_cache_alloc_bulk>> slab_post_alloc_hook(s, flags, size, p);
+ * - mm/slab.c|3604| <<kmem_cache_alloc_bulk>> slab_post_alloc_hook(s, flags, i, p);
+ */
static inline void slab_post_alloc_hook(struct kmem_cache *s, gfp_t flags,
size_t size, void **p)
{
@@ -469,10 +494,48 @@ struct kmem_cache_node {
#endif
#ifdef CONFIG_SLUB
+ /*
+ * 增加nr_partial的地方:
+ * - mm/slub.c|2588| <<__add_partial>> n->nr_partial++;
+ * 减少nr_partial的地方:
+ * - mm/slub.c|2613| <<remove_partial>> n->nr_partial--;
+ * - mm/slub.c|4943| <<__kmem_cache_shrink>> n->nr_partial--;
+ * 其他使用nr_partial的地方:
+ * - mm/slub.c|2687| <<get_partial_node>> if (!n || !n->nr_partial)
+ * - mm/slub.c|2764| <<get_any_partial>> n->nr_partial > s->min_partial) {
+ * - mm/slub.c|2961| <<deactivate_slab>> if (!new.inuse && n->nr_partial >= s->min_partial)
+ * - mm/slub.c|3075| <<unfreeze_partials>> if (unlikely(!new.inuse && n->nr_partial >= s->min_partial)) {
+ * - mm/slub.c|3807| <<__slab_free>> if (unlikely(!new.inuse && n->nr_partial >= s->min_partial))
+ * - mm/slub.c|4273| <<init_kmem_cache_node>> n->nr_partial = 0;
+ * - mm/slub.c|4698| <<__kmem_cache_shutdown>> if (n->nr_partial || slabs_node(s, node))
+ * - mm/slub.c|5413| <<validate_slab_node>> if (count != n->nr_partial)
+ * - mm/slub.c|5415| <<validate_slab_node>> s->name, count, n->nr_partial);
+ * - mm/slub.c|5857| <<show_slab_objects>> x = n->nr_partial;
+ */
unsigned long nr_partial;
+ /*
+ * 比如page->lru是在__add_partial()加入partial的
+ * 在remove_partial()删除的
+ */
struct list_head partial;
#ifdef CONFIG_SLUB_DEBUG
+ /*
+ * 增加和减少nr_slabs的地方:
+ * - mm/slub.c|1883| <<inc_slabs_node>> atomic_long_inc(&n->nr_slabs);
+ * - mm/slub.c|1895| <<dec_slabs_node>> atomic_long_dec(&n->nr_slabs);
+ * - mm/slub.c|4935| <<init_kmem_cache_node>> atomic_long_set(&n->nr_slabs, 0);
+ */
atomic_long_t nr_slabs;
+ /*
+ * 增加减少和获取total_objects的地方:
+ * - mm/slub.c|1713| <<inc_slabs_node>> atomic_long_add(objects, &n->total_objects);
+ * - mm/slub.c|1725| <<dec_slabs_node>> atomic_long_sub(objects, &n->total_objects);
+ * - mm/slub.c|4756| <<init_kmem_cache_node>> atomic_long_set(&n->total_objects, 0);
+ * - mm/slub.c|3558| <<node_nr_objs>> return atomic_long_read(&n->total_objects);
+ * - mm/slub.c|6399| <<show_slab_objects>> x = atomic_long_read(&n->total_objects);
+ * - mm/slub.c|6401| <<show_slab_objects>> x = atomic_long_read(&n->total_objects) -
+ * - mm/slub.c|6444| <<any_slab_objects>> if (atomic_long_read(&n->total_objects))
+ */
atomic_long_t total_objects;
struct list_head full;
#endif
diff --git a/mm/slab_common.c b/mm/slab_common.c
index f6764cf1..1effe69b 100644
--- a/mm/slab_common.c
+++ b/mm/slab_common.c
@@ -26,29 +26,83 @@
#include "slab.h"
+/*
+ * slub中使用slab_state的例子:
+ * - mm/slab_common.c|1140| <<create_kmalloc_caches>> slab_state = UP;
+ * - mm/slub.c|6034| <<kmem_cache_init>> slab_state = PARTIAL;
+ * - mm/slub.c|7761| <<slab_sysfs_init>> slab_state = FULL;
+ * - mm/slab_common.c|919| <<slab_is_available>> return slab_state >= UP;
+ * - mm/slub.c|5100| <<init_kmem_cache_nodes>> if (slab_state == DOWN) {
+ * - mm/slub.c|5450| <<kmem_cache_open>> if (slab_state >= UP) {
+ * - mm/slub.c|6134| <<__kmem_cache_create>> if (slab_state <= UP)
+ * - mm/slub.c|7415| <<slab_attr_store>> if (slab_state >= FULL && err >= 0 && is_root_cache(s)) {
+ * - mm/slub.c|7681| <<sysfs_slab_remove>> if (slab_state < FULL)
+ * - mm/slub.c|7694| <<sysfs_slab_unlink>> if (slab_state >= FULL)
+ * - mm/slub.c|7700| <<sysfs_slab_release>> if (slab_state >= FULL)
+ * - mm/slub.c|7728| <<sysfs_slab_alias>> if (slab_state == FULL) {
+ *
+ * 猜测可以用来保证kmalloc-xxx比其他先初始化???
+ */
enum slab_state slab_state;
+/*
+ * slub中使用slab_caches的例子:
+ * - mm/slab_common.c|92| <<kmem_cache_sanity_check>> list_for_each_entry(s, &slab_caches, list) {
+ * - mm/slab_common.c|416| <<create_cache>> list_add(&s->list, &slab_caches);
+ * - mm/slab_common.c|953| <<create_kmalloc_cache>> list_add(&s->list, &slab_caches);
+ * - mm/slub.c|2571| <<init_freelist_randomization>> list_for_each_entry(s, &slab_caches, list)
+ * - mm/slub.c|3761| <<slub_cpu_dead>> list_for_each_entry(s, &slab_caches, list) {
+ * - mm/slub.c|5849| <<slab_mem_going_offline_callback>> list_for_each_entry(s, &slab_caches, list)
+ * - mm/slub.c|5873| <<slab_mem_offline_callback>> list_for_each_entry(s, &slab_caches, list) {
+ * - mm/slub.c|5912| <<slab_mem_going_online_callback>> list_for_each_entry(s, &slab_caches, list) {
+ * - mm/slub.c|5999| <<bootstrap>> list_add(&s->list, &slab_caches);
+ * - mm/slub.c|7763| <<slab_sysfs_init>> list_for_each_entry(s, &slab_caches, list) {
+ */
LIST_HEAD(slab_caches);
DEFINE_MUTEX(slab_mutex);
struct kmem_cache *kmem_cache;
+/*
+ * 在以下使用slab_caches_to_rcu_destroy:
+ * - mm/slab_common.c|589| <<slab_caches_to_rcu_destroy_workfn>> list_splice_init(&slab_caches_to_rcu_destroy, &to_destroy);
+ * - mm/slab_common.c|621| <<shutdown_cache>> list_add_tail(&s->list, &slab_caches_to_rcu_destroy);
+ */
static LIST_HEAD(slab_caches_to_rcu_destroy);
static void slab_caches_to_rcu_destroy_workfn(struct work_struct *work);
+/*
+ * 调用slab_caches_to_rcu_destroy_work的地方:
+ * - mm/slab_common.c|622| <<shutdown_cache>> schedule_work(&slab_caches_to_rcu_destroy_work);
+ */
static DECLARE_WORK(slab_caches_to_rcu_destroy_work,
slab_caches_to_rcu_destroy_workfn);
/*
* Set of flags that will prevent slab merging
*/
+/*
+ * 在以下使用SLAB_NEVER_MERGE:
+ * - mm/slab_common.c|311| <<slab_unmergeable>> if (slab_nomerge || (s->flags & SLAB_NEVER_MERGE))
+ * - mm/slab_common.c|355| <<find_mergeable>> if (flags & SLAB_NEVER_MERGE)
+ */
#define SLAB_NEVER_MERGE (SLAB_RED_ZONE | SLAB_POISON | SLAB_STORE_USER | \
SLAB_TRACE | SLAB_TYPESAFE_BY_RCU | SLAB_NOLEAKTRACE | \
SLAB_FAILSLAB | SLAB_KASAN)
+/*
+ * 在以下使用SLAB_MERGE_SAME:
+ * - mm/slab_common.c|365| <<find_mergeable>> if ((flags & SLAB_MERGE_SAME) != (s->flags & SLAB_MERGE_SAME))
+ */
#define SLAB_MERGE_SAME (SLAB_RECLAIM_ACCOUNT | SLAB_CACHE_DMA | \
SLAB_ACCOUNT)
/*
* Merge control. If this is set then no merging of slab caches will occur.
*/
+/*
+ * 在以下使用slab_nomerge:
+ * - mm/slab_common.c|86| <<setup_slab_nomerge>> slab_nomerge = true;
+ * - mm/slab_common.c|311| <<slab_unmergeable>> if (slab_nomerge || (s->flags & SLAB_NEVER_MERGE))
+ * - mm/slab_common.c|339| <<find_mergeable>> if (slab_nomerge)
+ */
static bool slab_nomerge = !IS_ENABLED(CONFIG_SLAB_MERGE_DEFAULT);
static int __init setup_slab_nomerge(char *str)
@@ -66,6 +120,16 @@ __setup("slab_nomerge", setup_slab_nomerge);
/*
* Determine the size of a slab object
*/
+/*
+ * called by:
+ * - drivers/block/skd_main.c|2914| <<skd_construct>> WARN_ONCE(kmem_cache_size(skdev->msgbuf_cache) < size,
+ * - drivers/block/skd_main.c|2916| <<skd_construct>> kmem_cache_size(skdev->msgbuf_cache), size);
+ * - drivers/block/skd_main.c|2922| <<skd_construct>> WARN_ONCE(kmem_cache_size(skdev->sglist_cache) < size,
+ * - drivers/block/skd_main.c|2924| <<skd_construct>> kmem_cache_size(skdev->sglist_cache), size);
+ * - drivers/block/skd_main.c|2930| <<skd_construct>> WARN_ONCE(kmem_cache_size(skdev->databuf_cache) < size,
+ * - drivers/block/skd_main.c|2932| <<skd_construct>> kmem_cache_size(skdev->databuf_cache), size);
+ * - lib/lru_cache.c|107| <<lc_create>> unsigned cache_obj_size = kmem_cache_size(cache);
+ */
unsigned int kmem_cache_size(struct kmem_cache *s)
{
return s->object_size;
@@ -73,6 +137,12 @@ unsigned int kmem_cache_size(struct kmem_cache *s)
EXPORT_SYMBOL(kmem_cache_size);
#ifdef CONFIG_DEBUG_VM
+/*
+ * called by:
+ * - mm/slab_common.c|456| <<kmem_cache_create>> err = kmem_cache_sanity_check(name, size);
+ *
+ * ol6中uek4没有设置CONFIG_DEBUG_VM
+ */
static int kmem_cache_sanity_check(const char *name, size_t size)
{
struct kmem_cache *s = NULL;
@@ -110,6 +180,13 @@ static inline int kmem_cache_sanity_check(const char *name, size_t size)
}
#endif
+/*
+ * called by:
+ * - mm/slab.c|3605| <<kmem_cache_alloc_bulk>> __kmem_cache_free_bulk(s, i, p);
+ * - mm/slab_common.c|203| <<__kmem_cache_alloc_bulk>> __kmem_cache_free_bulk(s, i, p);
+ * - mm/slob.c|619| <<kmem_cache_free_bulk>> __kmem_cache_free_bulk(s, size, p);
+ * - mm/slub.c|4858| <<kmem_cache_alloc_bulk>> __kmem_cache_free_bulk(s, i, p);
+ */
void __kmem_cache_free_bulk(struct kmem_cache *s, size_t nr, void **p)
{
size_t i;
@@ -122,6 +199,10 @@ void __kmem_cache_free_bulk(struct kmem_cache *s, size_t nr, void **p)
}
}
+/*
+ * 不被slub调用:
+ * - mm/slob.c|626| <<kmem_cache_alloc_bulk>> return __kmem_cache_alloc_bulk(s, flags, size, p);
+ */
int __kmem_cache_alloc_bulk(struct kmem_cache *s, gfp_t flags, size_t nr,
void **p)
{
@@ -139,6 +220,16 @@ int __kmem_cache_alloc_bulk(struct kmem_cache *s, gfp_t flags, size_t nr,
#if defined(CONFIG_MEMCG) && !defined(CONFIG_SLOB)
+/*
+ * 在以下使用slab_root_caches:
+ * - mm/slab_common.c|290| <<memcg_update_all_caches>> list_for_each_entry(s, &slab_root_caches, root_caches_node) {
+ * - mm/slab_common.c|306| <<memcg_link_cache>> list_add(&s->root_caches_node, &slab_root_caches);
+ * - mm/slab_common.c|392| <<find_mergeable>> list_for_each_entry_reverse(s, &slab_root_caches, root_caches_node) {
+ * - mm/slab_common.c|820| <<memcg_deactivate_kmem_caches>> list_for_each_entry(s, &slab_root_caches, root_caches_node) {
+ * - mm/slab_common.c|1332| <<slab_start>> return seq_list_start(&slab_root_caches, *pos);
+ * - mm/slab_common.c|1337| <<slab_next>> return seq_list_next(p, &slab_root_caches, pos);
+ * - mm/slab_common.c|1391| <<slab_show>> if (p == slab_root_caches.next)
+ */
LIST_HEAD(slab_root_caches);
void slab_init_memcg_params(struct kmem_cache *s)
@@ -270,8 +361,18 @@ static inline void memcg_unlink_cache(struct kmem_cache *s)
/*
* Find a mergeable slab cache
*/
+/*
+ * called by:
+ * - mm/slab_common.c|393| <<find_mergeable>> if (slab_unmergeable(s))
+ * - mm/slub.c|7617| <<sysfs_slab_add>> int unmergeable = slab_unmergeable(s);
+ */
int slab_unmergeable(struct kmem_cache *s)
{
+ /*
+ * 对于slub_debug=FU,kmalloc-128,会把kmalloc-128的debug设置上
+ * 于是没有slab可以merge到kmalloc-128了
+ * 测试的时候新创建的128大小的slab被merge到"pid"了!
+ */
if (slab_nomerge || (s->flags & SLAB_NEVER_MERGE))
return 1;
@@ -290,32 +391,73 @@ int slab_unmergeable(struct kmem_cache *s)
return 0;
}
+/*
+ * 在以下使用kmalloc_info[]来创建kmalloc-128等:
+ * - mm/slab.c|1297| <<kmem_cache_init>> kmalloc_info[INDEX_NODE].name,
+ * - mm/slab_common.c|1201| <<new_kmalloc_cache>> kmalloc_caches[idx] = create_kmalloc_cache(kmalloc_info[idx].name,
+ * - mm/slab_common.c|1202| <<new_kmalloc_cache>> kmalloc_info[idx].size, flags);
+ *
+ * called by:
+ * - mm/slab.c|1896| <<__kmem_cache_alias>> cachep = find_mergeable(size, align, flags, name, ctor);
+ * - mm/slub.c|5106| <<__kmem_cache_alias>> s = find_mergeable(size, align, flags, name, ctor);
+ */
struct kmem_cache *find_mergeable(size_t size, size_t align,
unsigned long flags, const char *name, void (*ctor)(void *))
{
struct kmem_cache *s;
+ /* 如果内核参数设置了nomerge, 就不用merge这一个了 */
if (slab_nomerge)
return NULL;
if (ctor)
return NULL;
+ /*
+ * 为什么不用calculate_sizes()计算呢????
+ */
size = ALIGN(size, sizeof(void *));
align = calculate_alignment(flags, align, size);
size = ALIGN(size, align);
+ /*
+ * 可能会把一些debug flag一起返回
+ */
flags = kmem_cache_flags(size, flags, name, NULL);
+ /*
+ * #define SLAB_NEVER_MERGE (SLAB_RED_ZONE | SLAB_POISON | SLAB_STORE_USER | \
+ * SLAB_TRACE | SLAB_TYPESAFE_BY_RCU | SLAB_NOLEAKTRACE | \
+ * SLAB_FAILSLAB | SLAB_KASAN)
+ */
if (flags & SLAB_NEVER_MERGE)
return NULL;
+ /*
+ * 在以下使用slab_root_caches:
+ * - mm/slab_common.c|290| <<memcg_update_all_caches>> list_for_each_entry(s, &slab_root_caches, root_caches_node) {
+ * - mm/slab_common.c|306| <<memcg_link_cache>> list_add(&s->root_caches_node, &slab_root_caches);
+ * - mm/slab_common.c|392| <<find_mergeable>> list_for_each_entry_reverse(s, &slab_root_caches, root_caches_node) {
+ * - mm/slab_common.c|820| <<memcg_deactivate_kmem_caches>> list_for_each_entry(s, &slab_root_caches, root_caches_node) {
+ * - mm/slab_common.c|1332| <<slab_start>> return seq_list_start(&slab_root_caches, *pos);
+ * - mm/slab_common.c|1337| <<slab_next>> return seq_list_next(p, &slab_root_caches, pos);
+ * - mm/slab_common.c|1391| <<slab_show>> if (p == slab_root_caches.next)
+ */
list_for_each_entry_reverse(s, &slab_root_caches, root_caches_node) {
+ /*
+ * 对于slub_debug=FU,kmalloc-128,会把kmalloc-128的debug设置上
+ * 于是没有slab可以merge到kmalloc-128了
+ * 测试的时候新创建的128大小的slab被merge到"pid"了!
+ */
if (slab_unmergeable(s))
continue;
if (size > s->size)
continue;
+ /*
+ * #define SLAB_MERGE_SAME (SLAB_RECLAIM_ACCOUNT | SLAB_CACHE_DMA | \
+ * SLAB_ACCOUNT)
+ */
if ((flags & SLAB_MERGE_SAME) != (s->flags & SLAB_MERGE_SAME))
continue;
/*
@@ -341,6 +483,12 @@ struct kmem_cache *find_mergeable(size_t size, size_t align,
* Figure out what the alignment of the objects will be given a set of
* flags, a user specified alignment and the size of the objects.
*/
+/*
+ * called by:
+ * - mm/slab_common.c|420| <<find_mergeable>> align = calculate_alignment(flags, align, size);
+ * - mm/slab_common.c|638| <<kmem_cache_create>> calculate_alignment(flags, align, size),
+ * - mm/slab_common.c|1057| <<create_boot_cache>> s->align = calculate_alignment(flags, ARCH_KMALLOC_MINALIGN, size);
+ */
unsigned long calculate_alignment(unsigned long flags,
unsigned long align, unsigned long size)
{
@@ -364,6 +512,11 @@ unsigned long calculate_alignment(unsigned long flags,
return ALIGN(align, sizeof(void *));
}
+/*
+ * called by:
+ * - mm/slab_common.c|480| <<kmem_cache_create>> s = create_cache(cache_name, size, size,
+ * - mm/slab_common.c|621| <<memcg_create_kmem_cache>> s = create_cache(cache_name, root_cache->object_size,
+ */
static struct kmem_cache *create_cache(const char *name,
size_t object_size, size_t size, size_t align,
unsigned long flags, void (*ctor)(void *),
@@ -443,6 +596,12 @@ kmem_cache_create(const char *name, size_t size, size_t align,
mutex_lock(&slab_mutex);
+ /*
+ * called by:
+ * - mm/slab_common.c|456| <<kmem_cache_create>> err = kmem_cache_sanity_check(name, size);
+ *
+ * ol6中uek4没有设置CONFIG_DEBUG_VM
+ */
err = kmem_cache_sanity_check(name, size);
if (err) {
goto out_unlock;
@@ -462,6 +621,13 @@ kmem_cache_create(const char *name, size_t size, size_t align,
*/
flags &= CACHE_CREATE_MASK;
+ /*
+ * called by:
+ * - mm/slab_common.c|475| <<kmem_cache_create>> s = __kmem_cache_alias(name, size, align, flags, ctor);
+ *
+ * 该函数检查已创建的slab是否存在与当前想要创建的slab的对象大小相
+ * 匹配的,如果有则通过别名合并到一个缓存中进行访问.
+ */
s = __kmem_cache_alias(name, size, align, flags, ctor);
if (s)
goto out_unlock;
@@ -472,6 +638,11 @@ kmem_cache_create(const char *name, size_t size, size_t align,
goto out_unlock;
}
+ /*
+ * create_cache()在以下调用:
+ * - mm/slab_common.c|480| <<kmem_cache_create>> s = create_cache(cache_name, size, size,
+ * - mm/slab_common.c|621| <<memcg_create_kmem_cache>> s = create_cache(cache_name, root_cache->object_size,
+ */
s = create_cache(cache_name, size, size,
calculate_alignment(flags, align, size),
flags, ctor, NULL, NULL);
@@ -880,6 +1051,9 @@ bool slab_is_available(void)
return slab_state >= UP;
}
+/*
+ * 注意!!! 下面是ndef, NOT define!!!
+ */
#ifndef CONFIG_SLOB
/* Create a cache during boot when no slab services are available yet */
void __init create_boot_cache(struct kmem_cache *s, const char *name, size_t size,
@@ -902,6 +1076,12 @@ void __init create_boot_cache(struct kmem_cache *s, const char *name, size_t siz
s->refcount = -1; /* Exempt from merging for now */
}
+/*
+ * called by:
+ * - mm/slab.c|1296| <<kmem_cache_init>> kmalloc_caches[INDEX_NODE] = create_kmalloc_cache(
+ * - mm/slab_common.c|1201| <<new_kmalloc_cache>> kmalloc_caches[idx] = create_kmalloc_cache(kmalloc_info[idx].name,
+ * - mm/slab_common.c|1242| <<create_kmalloc_caches>> kmalloc_dma_caches[i] = create_kmalloc_cache(n,
+ */
struct kmem_cache *__init create_kmalloc_cache(const char *name, size_t size,
unsigned long flags)
{
@@ -997,6 +1177,12 @@ struct kmem_cache *kmalloc_slab(size_t size, gfp_t flags)
* kmalloc_index() supports up to 2^26=64MB, so the final entry of the table is
* kmalloc-67108864.
*/
+/*
+ * 在以下使用kmalloc_info[]:
+ * - mm/slab.c|1297| <<kmem_cache_init>> kmalloc_info[INDEX_NODE].name,
+ * - mm/slab_common.c|1201| <<new_kmalloc_cache>> kmalloc_caches[idx] = create_kmalloc_cache(kmalloc_info[idx].name,
+ * - mm/slab_common.c|1202| <<new_kmalloc_cache>> kmalloc_info[idx].size, flags);
+ */
const struct kmalloc_info_struct kmalloc_info[] __initconst = {
{NULL, 0}, {"kmalloc-96", 96},
{"kmalloc-192", 192}, {"kmalloc-8", 8},
@@ -1061,6 +1247,12 @@ void __init setup_kmalloc_cache_index_table(void)
}
}
+/*
+ * called by:
+ * - mm/slab_common.c|1081| <<create_kmalloc_caches>> new_kmalloc_cache(i, flags);
+ * - mm/slab_common.c|1089| <<create_kmalloc_caches>> new_kmalloc_cache(1, flags);
+ * - mm/slab_common.c|1091| <<create_kmalloc_caches>> new_kmalloc_cache(2, flags);
+ */
static void __init new_kmalloc_cache(int idx, unsigned long flags)
{
kmalloc_caches[idx] = create_kmalloc_cache(kmalloc_info[idx].name,
@@ -1072,6 +1264,11 @@ static void __init new_kmalloc_cache(int idx, unsigned long flags)
* may already have been created because they were needed to
* enable allocations for slab creation.
*/
+/*
+ * called by:
+ * - mm/slab.c|1316| <<kmem_cache_init>> create_kmalloc_caches(ARCH_KMALLOC_FLAGS);
+ * - mm/slub.c|6052| <<kmem_cache_init>> create_kmalloc_caches(0);
+ */
void __init create_kmalloc_caches(unsigned long flags)
{
int i;
@@ -1254,6 +1451,11 @@ memcg_accumulate_slabinfo(struct kmem_cache *s, struct slabinfo *info)
}
}
+/*
+ * called by:
+ * - mm/slab_common.c|1481| <<slab_show>> cache_show(s, m);
+ * - mm/slab_common.c|1514| <<memcg_slab_show>> cache_show(s, m);
+ */
static void cache_show(struct kmem_cache *s, struct seq_file *m)
{
struct slabinfo sinfo;
diff --git a/mm/slub.c b/mm/slub.c
index 220d42e5..d7c13f28 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -40,6 +40,101 @@
#include "internal.h"
+/*
+ * NOTES:
+ *
+ * 1. s->offset: Free pointer offset
+ * 就是在calculate_sizes()设置, 在以下条件设置:
+ * 4898 if (((flags & (SLAB_TYPESAFE_BY_RCU | SLAB_POISON)) ||
+ * 4899 s->ctor)) {
+ * 当slub_debug=ZUF(没有P)的时候, kmalloc-128的s->offset=0
+ * 当slub_debug=PZUF(有P)的时候, kmalloc-128的s->offset=136
+ */
+
+/*
+ * 从high level考虑,SLUB就是利用特殊区域填充特殊的magic num,在每一次
+ * alloc/free的时候检查magic num是否被意外修改.只申请内存而不释放的
+ * 话,是没法检测的.我们只能借助slabinfo工具主动触发检测功能。所以,这
+ * 也是SLUB DEBUG的一个劣势,它不能做到动态监测.它的检测机制是被动的.
+ *
+ * 一共四个debug的选项:
+ * - SLAB_CONSISTENCY_CHECKS
+ * - SLAB_RED_ZONE
+ * - SLAB_POISON
+ * - SLAB_STORE_USER
+ *
+ * SLUB DEBUG检测oob问题原理也很简单,既然为了发现是否越界,那么
+ * 就在分配出去的内存尾部添加一段额外的内存,填充特殊数字(magic num).
+ * 我们只需要检测这块额外的内存的数据是否被修改就可以知道是否发生了
+ * oob情况.而这段额外的内存就叫做Redzone.
+ *
+ * SLUB DEBUG关闭的情况下,free pointer是内嵌在object之中的,但是SLUB DEBUG
+ * 打开之后,free pointer是在object之外,并且多了很多其他的内存,
+ * 例如red zone,trace和red_left_pad等.这里之所以将FP后移就是因为为了检测
+ * use-after-free问题,当free object时会在将object填充magic num(0x6b).
+ * 如果不后移的话,岂不是破坏了object之间的单链表关系.
+ *
+ * 在没有slub_debug的时候:
+ * [Object size(with FP at the beginning 8-byte)][Obj align]
+ *
+ * 在slub_debug=PZU的时候:
+ * [Object size][Red zone][FP][alloc/free track][padding][red_left_pad]
+ *
+ * 其实slub_debug=PZU的时候应该是:
+ * [red_left_pad][Object size][Red zone][FP][alloc/free track][padding]
+ *
+ * - Redzone (主要检测右边oob)
+ * 从图中我们可以看到在object后面紧接着就是Red zone区域,那么Red zone有什
+ * 么作用呢?既然紧随其后,自然是检测右边界越界访问
+ * (right out-of-bounds access).原理很简单,在Red zone区域填充magic num,
+ * 检查Red zone区域数据是否被修改即可知道是否发生right oob. 可能你会想到
+ * 如果越过Redzone,直接改写了FP,岂不是检测不到oob了,并且链表结构也被破坏
+ * 了.其实在check_object()函数中会调用check_valid_pointer()来检查FP是否
+ * valid,如果invalid,同样会print error syslog.
+ *
+ * - padding
+ * padding是sizeof(void *) bytes的填充区域,在分配slab缓存池时,会将所有的内
+ * 存填充0x5a.同样在free/alloc object的时候作为检测的一种途径.如果padding
+ * 区域的数据不是0x5a,就代表发生了"Object padding overwritten"问题.这也是
+ * 有可能,越界跨度很大.
+ *
+ * - red_left_pad (检测左边的oob)
+ * 在struct page结构中有一个freelist指针,freelist会指向第一个available object.
+ * 在构建object之间的单链表的时候,object首地址实际上都会加上一个red_left_pad的
+ * 偏移,这样实际的layout就如同下面转换之后的layout:
+ *
+ * 其实slub_debug=PZU的时候应该是:
+ * [red_left_pad][Object size][Red zone][FP][alloc/free track][padding]
+ *
+ * 填充的magic num和Redzone一样,差别只是检测的区域不一样而已.
+ */
+
+/*
+ * 关于填充
+ *
+ * 从high level考虑,SLUB就是利用特殊区域填充特殊的magic num,在
+ * 每一次alloc/free的时候检查magic num是否被意外修改.
+ *
+ * - SLUB_RED_INACTIVE
+ *
+ * - SLUB_RED_ACTIVE
+ *
+ * - POISON_INUSE
+ *
+ * - POISON_FREE
+ */
+
+/*
+ * To detect out-of-bound:
+ *
+ * To detect use-after-free:
+ */
+
+/*
+ * - https://blog.csdn.net/juS3Ve/article/details/79285745
+ * - http://www.wowotech.net/memory_management/426.html
+ */
+
/*
* Lock order:
* 1. slab_mutex (Global Mutex)
@@ -116,6 +211,20 @@
* the fast path and disables lockless freelists.
*/
+ /*
+ * called by:
+ * - mm/slub.c|130| <<fixup_red_left>> if (kmem_cache_debug(s) && s->flags & SLAB_RED_ZONE)
+ * - mm/slub.c|139| <<kmem_cache_has_cpu_partial>> return !kmem_cache_debug(s);
+ * - mm/slub.c|2097| <<deactivate_slab>> if (kmem_cache_debug(s) && !lock) {
+ * - mm/slub.c|2594| <<___slab_alloc>> if (likely(!kmem_cache_debug(s) && pfmemalloc_match(page, gfpflags)))
+ * - mm/slub.c|2598| <<___slab_alloc>> if (kmem_cache_debug(s) &&
+ * - mm/slub.c|2814| <<__slab_free>> if (kmem_cache_debug(s) &&
+ * - mm/slub.c|2889| <<__slab_free>> if (kmem_cache_debug(s))
+ * - mm/slub.c|3845| <<__check_heap_object>> if (kmem_cache_debug(s) && s->flags & SLAB_RED_ZONE) {
+ */
+ /*
+ * 当kmem_cache->flags设置了debug的任何flag的时候返回 true
+ */
static inline int kmem_cache_debug(struct kmem_cache *s)
{
#ifdef CONFIG_SLUB_DEBUG
@@ -125,17 +234,51 @@ static inline int kmem_cache_debug(struct kmem_cache *s)
#endif
}
+/*
+ * called by:
+ * - include/linux/slub_def.h|183| <<nearest_obj>> result = fixup_red_left(cache, result);
+ * - mm/slub.c|432| <<for_each_object>> for (__p = fixup_red_left(__s, __addr); \