[커널 18차] 56주차

2022.06.18 22:19

kkr 조회 수:71

git : https://github.com/iamroot18/5.10/commit/a06c873e00acd7d5ef4941c72940430f0d671542

 

diff --git a/include/linux/atomic/atomic-instrumented.h b/include/linux/atomic/atomic-instrumented.h
index 4c28b6ee36ad..4588110c73d3 100644
--- a/include/linux/atomic/atomic-instrumented.h
+++ b/include/linux/atomic/atomic-instrumented.h
@@ -1928,6 +1928,10 @@ atomic_long_dec_if_positive(atomic_long_t *v)
     arch_sync_cmpxchg(__ai_ptr, __VA_ARGS__); \
 })
 
+/*
+ * IAMROOT, 2022.06.18:
+ * - 2개를 동시에 바꾼다.
+ */
 #define cmpxchg_double(ptr, ...) \
 ({ \
     typeof(ptr) __ai_ptr = (ptr); \
diff --git a/include/linux/cpuset.h b/include/linux/cpuset.h
index 56ab7113d261..e91677546c37 100644
--- a/include/linux/cpuset.h
+++ b/include/linux/cpuset.h
@@ -149,7 +149,13 @@ extern void cpuset_print_current_mems_allowed(void);
  * IAMROOT, 2022.03.19:
  * - /sys/fs/cgroup/cpuset/cpuset.mems 를 보면 할당가능한 numa node mask가
  *   기록되있다.
- * - 이값을 읽어 오기 위해 sequence lock을 한다.
+ * - 이값을 읽어 오기 위해 sequence lock을 한다.(mostly read)
+ *
+ * - 사용법
+ * do {
+ *    cpuset_mems_cookie = read_mems_allowed_begin();
+ *      ...
+ * } while (read_mems_allowed_retry(cpuset_mems_cookie));
  */
 static inline unsigned int read_mems_allowed_begin(void)
 {
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 480d688db1a9..da16b5fac66b 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -1818,6 +1818,12 @@ struct address_space *page_mapping(struct page *page);
  * ALLOC_NO_WATERMARKS and the low watermark was not
  * met implying that the system is under some pressure.
  */
+/*
+ * IAMROOT, 2022.06.18:
+ * - papago
+ *   페이지가 ALLOC_NO_WATERMARKS로 할당되었고 시스템이 약간의 압력을 받고 있음을
+ *   암시하는 로우 워터마크가 충족되지 않은 경우에만 true를 반환합니다.
+ */
 static inline bool page_is_pfmemalloc(const struct page *page)
 {
     /*
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index 1cfae2931135..2aa779b23db1 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -164,9 +164,20 @@ struct page {
             struct kmem_cache *slab_cache; /* not slob */
             /* Double-word boundary */
             void *freelist;        /* first free object */
+/*
+ * IAMROOT, 2022.06.18:
+ * - slub
+ */
             union {
                 void *s_mem;    /* slab: first object */
                 unsigned long counters;        /* SLUB */
+/*
+ * IAMROOT, 2022.06.18:
+ * - inuse   : 최초 빈 slab page에는 slab object 수가 들어가있다.(allocate_slab())
+ *   objects : 현재 남은 object수 처음엔 inuse와 같다.
+ *   frozen  : cpu cache에 들어갔을때 1. 그외는 0
+ *
+ */
                 struct {            /* SLUB */
                     unsigned inuse:16;
                     unsigned objects:15;
diff --git a/include/linux/reciprocal_div.h b/include/linux/reciprocal_div.h
index 585ce89c0f33..34c5e59e3395 100644
--- a/include/linux/reciprocal_div.h
+++ b/include/linux/reciprocal_div.h
@@ -20,6 +20,20 @@
  * to calculate the division A/B.
  */
 
+/*
+ * IAMROOT, 2022.06.18:
+ * - papago
+ *   이 알고리즘은 Torbjörn Granlund와 Peter L. Montgomery의 곱셈을 사용하는
+ *   불변 정수의 나눗셈 문서를 기반으로 합니다.
+ *
+ *   이 코드의 기반이 되는 Agner Fog의 어셈블러 구현은 다음에서 찾을 수 있습니다.
+ *   http://www.agner.org/optimize/asmlib.zip
+ *   
+ *   A/B에 대한 이 최적화는 제수 B가 대부분 런타임 불변인 경우에 유용합니다.
+ *   B의 역수는 reciprocal_value()를 사용하여 느린 경로에서 계산됩니다.
+ *   그러면 빠른 경로는 변수 배당 A와 함께 훨씬 빠른 곱셈 연산을 사용하여 나누기
+ *   A/B를 계산할 수 있습니다.
+ */
 struct reciprocal_value {
     u32 m;
     u8 sh1, sh2;
diff --git a/include/linux/slab.h b/include/linux/slab.h
index f9e7ad3192d8..25687269cc26 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -133,6 +133,11 @@
 
 /* The following flags affect the page allocator grouping pages by mobility */
 /* Objects are reclaimable */
+/*
+ * IAMROOT, 2022.06.18:
+ * - slab을 reclaim가능한 cache로 만든다.
+ *   ex) inode
+ */
 #define SLAB_RECLAIM_ACCOUNT    ((slab_flags_t __force)0x00020000U)
 #define SLAB_TEMPORARY        SLAB_RECLAIM_ACCOUNT    /* Objects are short-lived */
 
@@ -758,6 +763,10 @@ extern void *__kmalloc_node_track_caller(size_t, gfp_t, int, unsigned long);
 /*
  * Shortcuts
  */
+/*
+ * IAMROOT, 2022.06.18:
+ * - flags + __GFP_ZERO, all node
+ */
 static inline void *kmem_cache_zalloc(struct kmem_cache *k, gfp_t flags)
 {
     return kmem_cache_alloc(k, flags | __GFP_ZERO);
diff --git a/include/linux/slub_def.h b/include/linux/slub_def.h
index 10b71729aff5..7c3e8976eccd 100644
--- a/include/linux/slub_def.h
+++ b/include/linux/slub_def.h
@@ -49,6 +49,10 @@ struct kmem_cache_cpu {
     void **freelist;    /* Pointer to next available object */
     unsigned long tid;    /* Globally unique transaction id */
     struct page *page;    /* The slab from which we are allocating */
+/*
+ * IAMROOT, 2022.06.18:
+ * - parial page list.
+ */
 #ifdef CONFIG_SLUB_CPU_PARTIAL
     struct page *partial;    /* Partially allocated frozen slabs */
 #endif
@@ -80,6 +84,14 @@ struct kmem_cache_cpu {
  * contains both the order and the number of objects that a slab of the
  * given order would contain.
  */
+/*
+ * IAMROOT, 2022.06.18:
+ *   0          OO_SHIFT(16)      31
+ *   +-------------+---------------+
+ *   | object수    | order         |
+ *   +-------------+---------------+
+ *     oo_objects()  oo_order()
+ */
 struct kmem_cache_order_objects {
     unsigned int x;
 };
@@ -145,6 +157,10 @@ struct kmem_cache {
     unsigned int useroffset;    /* Usercopy region offset */
     unsigned int usersize;        /* Usercopy region size */
 
+/*
+ * IAMROOT, 2022.06.18:
+ * - online node에 대해서만 만들어진다.
+ */
     struct kmem_cache_node *node[MAX_NUMNODES];
 };
 
diff --git a/lib/fault-inject.c b/lib/fault-inject.c
index ce12621b4275..c00cbbc437ce 100644
--- a/lib/fault-inject.c
+++ b/lib/fault-inject.c
@@ -103,6 +103,10 @@ static inline bool fail_stacktrace(struct fault_attr *attr)
 bool should_fail(struct fault_attr *attr, ssize_t size)
 {
     if (in_task()) {
+/*
+ * IAMROOT, 2022.06.18:
+ * - fail_nth가 0이되면 실패시킨다.
+ */
         unsigned int fail_nth = READ_ONCE(current->fail_nth);
 
         if (fail_nth) {
diff --git a/mm/failslab.c b/mm/failslab.c
index f92fed91ac23..0ff58eea456a 100644
--- a/mm/failslab.c
+++ b/mm/failslab.c
@@ -14,6 +14,10 @@ static struct {
     .cache_filter = false,
 };
 
+/*
+ * IAMROOT, 2022.06.18:
+ * - slab에 사용하지 못하는 flag, fault injection 등을 검사한다.
+ */
 bool __should_failslab(struct kmem_cache *s, gfp_t gfpflags)
 {
     /* No fault-injection for bootstrap cache */
@@ -33,6 +37,10 @@ bool __should_failslab(struct kmem_cache *s, gfp_t gfpflags)
     return should_fail(&failslab.attr, s->object_size);
 }
 
+/*
+ * IAMROOT, 2022.06.18:
+ * - 특정 cache를 못만들도록 일부러 넣는다. (debug용 fault injection)
+ */
 static int __init setup_failslab(char *str)
 {
     return setup_fault_attr(&failslab.attr, str);
diff --git a/mm/kfence/core.c b/mm/kfence/core.c
index 756fab4aeec0..4f3eee5bfee7 100644
--- a/mm/kfence/core.c
+++ b/mm/kfence/core.c
@@ -748,6 +748,11 @@ void kfence_shutdown_cache(struct kmem_cache *s)
     }
 }
 
+/*
+ * IAMROOT, 2022.06.18:
+ * - PAGE_SIZE 이하의 경우에서, DMA요청이 아닌 경우에, kfence_enabled가 되있다면
+ *   kfence_guarded_alloc()을 호출한다.
+ */
 void *__kfence_alloc(struct kmem_cache *s, size_t size, gfp_t flags)
 {
     /*
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index 56819031e78d..d324d8366ec1 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -1881,6 +1881,11 @@ static unsigned interleave_nodes(struct mempolicy *policy)
  * Depending on the memory policy provide a node from which to allocate the
  * next slab entry.
  */
+/*
+ * IAMROOT, 2022.06.18:
+ * - interrupt의 경우 : 현재 cpu node
+ *   그외의 경우 task의 numa policy를 적용한다.
+ */
 unsigned int mempolicy_slab_node(void)
 {
     struct mempolicy *policy;
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 3be387b4ba2b..1e57b23fffbb 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -207,6 +207,11 @@ unsigned long totalcma_pages __read_mostly;
  * - 초기값 0. sysctl로 control한다.
  */
 int percpu_pagelist_high_fraction;
+
+/*
+ * IAMROOT, 2022.06.18:
+ * - boot중에는 reclaim이 제외된채지만. booting이 끝나면 정상적으로 변경된다.
+ */
 gfp_t gfp_allowed_mask __read_mostly = GFP_BOOT_MASK;
 DEFINE_STATIC_KEY_MAYBE(CONFIG_INIT_ON_ALLOC_DEFAULT_ON, init_on_alloc);
 EXPORT_SYMBOL(init_on_alloc);
diff --git a/mm/slab.h b/mm/slab.h
index 58c01a34e5b8..e3d600f09b1f 100644
--- a/mm/slab.h
+++ b/mm/slab.h
@@ -59,6 +59,11 @@ enum slab_state {
     DOWN,            /* No slab functionality yet */
     PARTIAL,        /* SLUB: kmem_cache_node available */
     PARTIAL_NODE,        /* SLAB: kmalloc size for node struct available */
+/*
+ * IAMROOT, 2022.06.18:
+ * - UP : sysfs에는 아직 안보임.
+ *   FULL : sysfs에 보이는 상황.
+ */
     UP,            /* Slab caches usable but not all extras yet */
     FULL            /* Everything is working */
 };
@@ -268,6 +273,10 @@ static inline size_t obj_full_size(struct kmem_cache *s)
 /*
  * Returns false if the allocation should fail.
  */
+/*
+ * IAMROOT, 2022.06.18:
+ * - memcg에서 제한을 확인한다.
+ */
 static inline bool memcg_slab_pre_alloc_hook(struct kmem_cache *s,
                          struct obj_cgroup **objcgp,
                          size_t objects, gfp_t flags)
@@ -277,6 +286,10 @@ static inline bool memcg_slab_pre_alloc_hook(struct kmem_cache *s,
     if (!memcg_kmem_enabled())
         return true;
 
+/*
+ * IAMROOT, 2022.06.18:
+ * - 둘다 acoount가 없으면 true.(제한이 없는 개념)
+ */
     if (!(flags & __GFP_ACCOUNT) && !(s->flags & SLAB_ACCOUNT))
         return true;
 
@@ -284,6 +297,10 @@ static inline bool memcg_slab_pre_alloc_hook(struct kmem_cache *s,
     if (!objcg)
         return true;
 
+/*
+ * IAMROOT, 2022.06.18:
+ * - 제한을 벗어나면 false.
+ */
     if (obj_cgroup_charge(objcg, flags, objects * obj_full_size(s))) {
         obj_cgroup_put(objcg);
         return false;
@@ -416,6 +433,10 @@ static inline struct kmem_cache *virt_to_cache(const void *obj)
     return page->slab_cache;
 }
 
+/*
+ * IAMROOT, 2022.06.18:
+ * - memcg와 통계에 기록한다.
+ */
 static __always_inline void account_slab_page(struct page *page, int order,
                           struct kmem_cache *s,
                           gfp_t gfp)
@@ -483,6 +504,10 @@ static inline size_t slab_ksize(const struct kmem_cache *s)
 #endif
 }
 
+/*
+ * IAMROOT, 2022.06.18:
+ * - flags 확인 및 memcg 확인.
+ */
 static inline struct kmem_cache *slab_pre_alloc_hook(struct kmem_cache *s,
                              struct obj_cgroup **objcgp,
                              size_t size, gfp_t flags)
@@ -560,6 +585,10 @@ struct kmem_cache_node {
 
 };
 
+/*
+ * IAMROOT, 2022.06.18:
+ * - @node에 대한 kmem_cache_node를 가져온다.
+ */
 static inline struct kmem_cache_node *get_node(struct kmem_cache *s, int node)
 {
     return s->node[node];
diff --git a/mm/slab_common.c b/mm/slab_common.c
index c375eef452e5..02feb3be9e8d 100644
--- a/mm/slab_common.c
+++ b/mm/slab_common.c
@@ -1376,6 +1376,10 @@ EXPORT_TRACEPOINT_SYMBOL(kmem_cache_alloc_node);
 EXPORT_TRACEPOINT_SYMBOL(kfree);
 EXPORT_TRACEPOINT_SYMBOL(kmem_cache_free);
 
+/*
+ * IAMROOT, 2022.06.18:
+ * - flag, fault injection등 검사 및 수행.
+ */
 int should_failslab(struct kmem_cache *s, gfp_t gfpflags)
 {
     if (__should_failslab(s, gfpflags))
diff --git a/mm/slub.c b/mm/slub.c
index a343b0da22bd..3ab524315b7e 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -189,6 +189,10 @@ static inline bool kmem_cache_debug(struct kmem_cache *s)
     return kmem_cache_debug_flags(s, SLAB_DEBUG_FLAGS);
 }
 
+/*
+ * IAMROOT, 2022.06.18:
+ * - redzone을 사용할경우 fp는 red_left_pad만큼 이동된 위치에 있다.
+ */
 void *fixup_red_left(struct kmem_cache *s, void *p)
 {
     if (kmem_cache_debug_flags(s, SLAB_RED_ZONE))
@@ -262,6 +266,12 @@ static inline bool kmem_cache_has_cpu_partial(struct kmem_cache *s)
  * Tracking user of a slab.
  */
 #define TRACK_ADDRS_COUNT 16
+
+/*
+ * IAMROOT, 2022.06.18:
+ * - object를 누가 호출해서 할당/해제 했는지를 추적한다.
+ *   할당용 1개, 해제용 1개를 쓴다.
+ */
 struct track {
     unsigned long addr;    /* Called from address */
 #ifdef CONFIG_STACKTRACE
@@ -306,6 +316,10 @@ static inline void stat(const struct kmem_cache *s, enum stat_item si)
  * differ during memory hotplug/hotremove operations.
  * Protected by slab_mutex.
  */
+/*
+ * IAMROOT, 2022.06.18:
+ * - memory에 있는 node.
+ */
 static nodemask_t slab_nodes;
 
 /********************************************************************
@@ -317,6 +331,11 @@ static nodemask_t slab_nodes;
  * with an XOR of the address where the pointer is held and a per-cache
  * random number.
  */
+/*
+ * IAMROOT, 2022.06.18:
+ * - CONFIG_SLAB_FREELIST_HARDENED가 on 일경우
+ *   a@s->random값을 이용해 FP(@ptr)을 숨긴다.
+ */
 static inline void *freelist_ptr(const struct kmem_cache *s, void *ptr,
                  unsigned long ptr_addr)
 {
@@ -339,6 +358,11 @@ static inline void *freelist_ptr(const struct kmem_cache *s, void *ptr,
 }
 
 /* Returns the freelist pointer recorded at location ptr_addr. */
+/*
+ * IAMROOT, 2022.06.18:
+ * @ptr_addr FP.
+ * hardened를 사용했을경우 관련 처리를 한다.
+ */
 static inline void *freelist_dereference(const struct kmem_cache *s,
                      void *ptr_addr)
 {
@@ -346,6 +370,10 @@ static inline void *freelist_dereference(const struct kmem_cache *s,
                 (unsigned long)ptr_addr);
 }
 
+/*
+ * IAMROOT, 2022.06.18:
+ * - @object의 FP를 가져온다. hardened를 사용했을경우 관련 처리를 한다.
+ */
 static inline void *get_freepointer(struct kmem_cache *s, void *object)
 {
     object = kasan_reset_tag(object);
@@ -371,6 +399,10 @@ static inline void *get_freepointer_safe(struct kmem_cache *s, void *object)
     return freelist_ptr(s, p, freepointer_addr);
 }
 
+/*
+ * IAMROOT, 2022.06.18:
+ * - @object의 FP에 next object (@fp)를 저장한다.
+ */
 static inline void set_freepointer(struct kmem_cache *s, void *object, void *fp)
 {
     unsigned long freeptr_addr = (unsigned long)object + s->offset;
@@ -389,11 +421,27 @@ static inline void set_freepointer(struct kmem_cache *s, void *object, void *fp)
         __p < (__addr) + (__objects) * (__s)->size; \
         __p += (__s)->size)
 
+/*
+ * IAMROOT, 2022.06.18:
+ * - PAGE_SIZE = 4K, order == PAGE_ALLOC_COSTLY_ORDER 일때
+ *   4k * 2^3 / size = return 32k / size
+ */
 static inline unsigned int order_objects(unsigned int order, unsigned int size)
 {
     return ((unsigned int)PAGE_SIZE << order) / size;
 }
 
+/*
+ * IAMROOT, 2022.06.18:
+ * - @order, @size로 oo초기값을 구해온다.
+ * - order제한이 MAX_OBJS_PER_PAGE(OO_SHIFT order)값이므로
+ *   
+ *   0          OO_SHIFT(16)      31
+ *   +-------------+---------------+
+ *   | object수    | order         |
+ *   +-------------+---------------+
+ *     oo_objects()  oo_order()
+ */
 static inline struct kmem_cache_order_objects oo_make(unsigned int order,
         unsigned int size)
 {
@@ -639,6 +687,11 @@ static inline void metadata_access_disable(void)
  */
 
 /* Verify that a pointer has an address that is valid within a slab page */
+/*
+ * IAMROOT, 2022.06.18:
+ * - 주소값들이 정상적으로 있는지 검사.
+ *   @object가 slab page안에 들어가는지 확인다.
+ */
 static inline int check_valid_pointer(struct kmem_cache *s,
                 struct page *page, void *object)
 {
@@ -670,6 +723,11 @@ static void print_section(char *level, char *text, u8 *addr,
 /*
  * See comment in calculate_sizes().
  */
+/*
+ * IAMROOT, 2022.06.18:
+ * - FP가 object 밖에 있는지 확인한다.(rcu, posion사용시 FP를 바깥에 빼놓는데
+ *   그 여부를 확인하는것).
+ */
 static inline bool freeptr_outside_object(struct kmem_cache *s)
 {
     return s->offset >= s->inuse;
@@ -697,6 +755,10 @@ static struct track *get_track(struct kmem_cache *s, void *object,
     return kasan_reset_tag(p + alloc);
 }
 
+/*
+ * IAMROOT, 2022.06.18:
+ * - 초기화때는 @addr = 0이여서 memset될것이다.
+ */
 static void set_track(struct kmem_cache *s, void *object,
             enum track_item alloc, unsigned long addr)
 {
@@ -723,6 +785,10 @@ static void set_track(struct kmem_cache *s, void *object,
     }
 }
 
+/*
+ * IAMROOT, 2022.06.18:
+ * - alloc, free track을 초기화한다.
+ */
 static void init_tracking(struct kmem_cache *s, void *object)
 {
     if (!(s->flags & SLAB_STORE_USER))
@@ -881,13 +947,35 @@ static __printf(3, 4) void slab_err(struct kmem_cache *s, struct page *page,
     add_taint(TAINT_BAD_PAGE, LOCKDEP_NOW_UNRELIABLE);
 }
 
+/*
+ * IAMROOT, 2022.06.18:
+ * - redzone, poison 값을 기록한다.
+ */
 static void init_object(struct kmem_cache *s, void *object, u8 val)
 {
     u8 *p = kasan_reset_tag(object);
 
+/*
+ * IAMROOT, 2022.06.18:
+ *
+ *            <----- inuse ----------->
+ * +----------+-----------------+-----+
+ * |    Z     | object          |  Z  |
+ * +----------+-----------------+-----+
+ * <--val---->p                  <-val->
+ * SLUB_RED_INACTIVE, SLUB_RED_ACTIVE
+ */
     if (s->flags & SLAB_RED_ZONE)
         memset(p - s->red_left_pad, val, s->red_left_pad);
 
+/*
+ * IAMROOT, 2022.06.18:
+ *
+ * +-----------------++
+ * | object          ||
+ * +-----------------++
+ * p<--POISON_FREE-->^POISON_END(마지막 byte만)
+ */
     if (s->flags & __OBJECT_POISON) {
         memset(p, POISON_FREE, s->object_size - 1);
         p[s->object_size - 1] = POISON_END;
@@ -974,7 +1062,10 @@ static int check_bytes_and_report(struct kmem_cache *s, struct page *page,
  * ignored. And therefore no slab options that rely on these boundaries
  * may be used with merged slabcaches.
  */
-
+/*
+ * IAMROOT, 2022.06.18:
+ * - 남아있는 영역에 POISON_INUSE값이 있는지 검사.
+ */
 static int check_pad_bytes(struct kmem_cache *s, struct page *page, u8 *p)
 {
     unsigned long off = get_info_end(s);    /* The end of info */
@@ -993,6 +1084,10 @@ static int check_pad_bytes(struct kmem_cache *s, struct page *page, u8 *p)
 }
 
 /* Check the pad bytes at the end of a slab page */
+/*
+ * IAMROOT, 2022.06.18:
+ * - pad공간의 침해여부 검사.(poison check.) error 출력 및 pad값 복구만 해준다.
+ */
 static int slab_pad_check(struct kmem_cache *s, struct page *page)
 {
     u8 *start;
@@ -1029,6 +1124,10 @@ static int slab_pad_check(struct kmem_cache *s, struct page *page)
     return 0;
 }
 
+/*
+ * IAMROOT, 2022.06.18:
+ * - object에 대해서 검사.
+ */
 static int check_object(struct kmem_cache *s, struct page *page,
                     void *object, u8 val)
 {
@@ -1036,6 +1135,10 @@ static int check_object(struct kmem_cache *s, struct page *page,
     u8 *endobject = object + s->object_size;
 
     if (s->flags & SLAB_RED_ZONE) {
+/*
+ * IAMROOT, 2022.06.18:
+ * - 각각 redzone영역에 val값이 있는지 검사.
+ */
         if (!check_bytes_and_report(s, page, object, "Left Redzone",
             object - s->red_left_pad, val, s->red_left_pad))
             return 0;
@@ -1044,6 +1147,10 @@ static int check_object(struct kmem_cache *s, struct page *page,
             endobject, val, s->inuse - s->object_size))
             return 0;
     } else {
+/*
+ * IAMROOT, 2022.06.18:
+ * POISON_INUSE이 padding 자리에 있는지 검사.
+ */
         if ((s->flags & SLAB_POISON) && s->object_size < s->inuse) {
             check_bytes_and_report(s, page, p, "Alignment padding",
                 endobject, POISON_INUSE,
@@ -1053,6 +1160,10 @@ static int check_object(struct kmem_cache *s, struct page *page,
 
     if (s->flags & SLAB_POISON) {
         if (val != SLUB_RED_ACTIVE && (s->flags & __OBJECT_POISON) &&
+/*
+ * IAMROOT, 2022.06.18:
+ * - object에 POISON_FREE, 마지막 byte에 POISON_END값이 있는지 검사.
+ */
             (!check_bytes_and_report(s, page, p, "Poison", p,
                     POISON_FREE, s->object_size - 1) ||
              !check_bytes_and_report(s, page, p, "End Poison",
@@ -1064,6 +1175,10 @@ static int check_object(struct kmem_cache *s, struct page *page,
         check_pad_bytes(s, page, p);
     }
 
+/*
+ * IAMROOT, 2022.06.18:
+ * - 사용중인 object는 FP가 없다. FP check를 안한다.
+ */
     if (!freeptr_outside_object(s) && val == SLUB_RED_ACTIVE)
         /*
          * Object and freepointer overlap. Cannot check
@@ -1072,6 +1187,10 @@ static int check_object(struct kmem_cache *s, struct page *page,
         return 1;
 
     /* Check free pointer validity */
+/*
+ * IAMROOT, 2022.06.18:
+ * - FP가 slab page 영역내에 있는지 검사한다.
+ */
     if (!check_valid_pointer(s, page, get_freepointer(s, p))) {
         object_err(s, page, p, "Freepointer corrupt");
         /*
@@ -1085,6 +1204,13 @@ static int check_object(struct kmem_cache *s, struct page *page,
     return 1;
 }
 
+/*
+ * IAMROOT, 2022.06.18:
+ * - 1. Slab flag가 있는지 검사.
+ *   2. page->object가 계산된 object보다 큰지 검사.
+ *   3. page->inuse가 계산된 object보다 큰지 검사.
+ *   4. slab pad공간(remainder)에 대한 posion 검사.
+ */
 static int check_slab(struct kmem_cache *s, struct page *page)
 {
     int maxobj;
@@ -1163,6 +1289,10 @@ static int on_freelist(struct kmem_cache *s, struct page *page, void *search)
     return search == NULL;
 }
 
+/*
+ * IAMROOT, 2022.06.18:
+ * - SLAB_TRACE가 있을경우 alloc시 pr_info 출력.
+ */
 static void trace(struct kmem_cache *s, struct page *page, void *object,
                                 int alloc)
 {
@@ -1240,6 +1370,10 @@ static inline void dec_slabs_node(struct kmem_cache *s, int node, int objects)
 }
 
 /* Object debug checks for alloc/free paths */
+/*
+ * IAMROOT, 2022.06.18:
+ * - redzone, poison, user track을 초기화한다.
+ */
 static void setup_object_debug(struct kmem_cache *s, struct page *page,
                                 void *object)
 {
@@ -1261,6 +1395,17 @@ void setup_page_debug(struct kmem_cache *s, struct page *page, void *addr)
     metadata_access_disable();
 }
 
+/*
+ * IAMROOT, 2022.06.18:
+ * - 1. Slab flag가 있는지 검사.
+ *   2. page->object가 계산된 object보다 큰지 검사.
+ *   3. page->inuse가 계산된 object보다 큰지 검사.
+ *   4. slab pad공간(remainder)에 대한 posion 검사.
+ *   5. object(FP)가 slab page 안에 있는지 검사.
+ *   6. object에 대해서 검사.
+ *
+ * - alloc일때 여러 검사를 수행한다.
+ */
 static inline int alloc_consistency_checks(struct kmem_cache *s,
                     struct page *page, void *object)
 {
@@ -1278,6 +1423,12 @@ static inline int alloc_consistency_checks(struct kmem_cache *s,
     return 1;
 }
 
+/*
+ * IAMROOT, 2022.06.18:
+ * - 1. alloc시 검사를 해야되는 사항 수행
+ *   2. alloc user track 기록
+ *   3. object의 redzone에 SLUB_RED_ACTIVE값으로 기록하고 posion정보도 기록한다.
+ */
 static noinline int alloc_debug_processing(struct kmem_cache *s,
                     struct page *page,
                     void *object, unsigned long addr)
@@ -1308,6 +1459,10 @@ static noinline int alloc_debug_processing(struct kmem_cache *s,
     return 0;
 }
 
+/*
+ * IAMROOT, 2022.06.18:
+ * - alloc_consistency_checks과 비슷한 방식으로 free할때 검사를 수행한다.
+ */
 static inline int free_consistency_checks(struct kmem_cache *s,
         struct page *page, void *object, unsigned long addr)
 {
@@ -1862,6 +2017,10 @@ static void *setup_object(struct kmem_cache *s, struct page *page,
 /*
  * Slab allocation and freeing
  */
+/*
+ * IAMROOT, 2022.06.18:
+ * - cache의 order로 page를 할당해온다.
+ */
 static inline struct page *alloc_slab_page(struct kmem_cache *s,
         gfp_t flags, int node, struct kmem_cache_order_objects oo)
 {
@@ -1911,6 +2070,10 @@ static void __init init_freelist_randomization(void)
 
     mutex_lock(&slab_mutex);
 
+/*
+ * IAMROOT, 2022.06.18:
+ * - 모든 slab cache를 interate하며 random seq를 초기화한다.
+ */
     list_for_each_entry(s, &slab_caches, list)
         init_cache_random_seq(s);
 
@@ -1918,6 +2081,11 @@ static void __init init_freelist_randomization(void)
 }
 
 /* Get the next entry on the pre-computed freelist randomized */
+/*
+ * IAMROOT, 2022.06.18:
+ * - @pos를 index로 하여 cache random_seq에서 next 주소를 가져온다.
+ *   만약 limit를 넘는 index가 있다면 재시도.
+ */
 static void *next_freelist_entry(struct kmem_cache *s, struct page *page,
                 unsigned long *pos, void *start,
                 unsigned long page_limit,
@@ -1940,6 +2108,10 @@ static void *next_freelist_entry(struct kmem_cache *s, struct page *page,
 }
 
 /* Shuffle the single linked freelist based on a random pre-computed sequence */
+/*
+ * IAMROOT, 2022.06.18:
+ * - freelist를 random으로 시작점을 정하고, 순서를 섞는다. debug 정보를 초기화한다.
+ */
 static bool shuffle_freelist(struct kmem_cache *s, struct page *page)
 {
     void *start;
@@ -1951,17 +2123,43 @@ static bool shuffle_freelist(struct kmem_cache *s, struct page *page)
         return false;
 
     freelist_count = oo_objects(s->oo);
+/*
+ * IAMROOT, 2022.06.18:
+ * - freelist_count이내의 숫자에서 random number를 가져온다.
+ */
     pos = get_random_int() % freelist_count;
 
     page_limit = page->objects * s->size;
     start = fixup_red_left(s, page_address(page));
 
     /* First entry is used as the base of the freelist */
+/*
+ * IAMROOT, 2022.06.18:
+ * - pos를 기준으로 random next를 가져온다. pos는 + 1 된다.
+ */
     cur = next_freelist_entry(s, page, &pos, start, page_limit,
                 freelist_count);
     cur = setup_object(s, page, cur);
+
+/*
+ * IAMROOT, 2022.06.18:
+ * - 시작지점을 위에서 random으로 구한 cur로 설정한다.
+ */
     page->freelist = cur;
 
+/*
+ * IAMROOT, 2022.06.18:
+ * - cur의 FP에 next를 단방향 list 식으로 연결한다. 맨마지막 object FP엔 null을
+ *   넣는다.
+ *
+ * |     object1             |    object2              |
+ * +---+-----------+---+-----+---+-----------+---+-----+
+ * | Z |   |FP|    | Z | PAD | Z |   |FP|    | Z | PAD |
+ * +---+----v------+---+-----+---^----v------+---+-----+
+ *          \____________________/    NULL
+ *        object의 시작점을 가리킨다.
+ *
+ */
     for (idx = 1; idx < page->objects; idx++) {
         next = next_freelist_entry(s, page, &pos, start, page_limit,
             freelist_count);
@@ -1985,6 +2183,11 @@ static inline bool shuffle_freelist(struct kmem_cache *s, struct page *page)
 }
 #endif /* CONFIG_SLAB_FREELIST_RANDOM */
 
+/*
+ * IAMROOT, 2022.06.18:
+ * - slab page를 할당받고 debug정보 초기화, fp를 전부 이어 놓는다. 그리고 frozen
+ *   상태를 해놓는다.
+ */
 static struct page *allocate_slab(struct kmem_cache *s, gfp_t flags, int node)
 {
     struct page *page;
@@ -2003,11 +2206,19 @@ static struct page *allocate_slab(struct kmem_cache *s, gfp_t flags, int node)
      * so we fall-back to the minimum order allocation.
      */
     alloc_gfp = (flags | __GFP_NOWARN | __GFP_NORETRY) & ~__GFP_NOFAIL;
+/*
+ * IAMROOT, 2022.06.18:
+ * - direct recalim 요청, order가 min보다 크면 nofail을 지우고 nomemalloc을 추가한다.
+ */
     if ((alloc_gfp & __GFP_DIRECT_RECLAIM) && oo_order(oo) > oo_order(s->min))
         alloc_gfp = (alloc_gfp | __GFP_NOMEMALLOC) & ~(__GFP_RECLAIM|__GFP_NOFAIL);
 
     page = alloc_slab_page(s, alloc_gfp, node, oo);
     if (unlikely(!page)) {
+/*
+ * IAMROOT, 2022.06.18:
+ * - 실패하면 order를 줄이고, flags를 완화하여 한번더 시도한다.
+ */
         oo = s->min;
         alloc_gfp = flags;
         /*
@@ -2025,6 +2236,12 @@ static struct page *allocate_slab(struct kmem_cache *s, gfp_t flags, int node)
     account_slab_page(page, oo_order(oo), s, flags);
 
     page->slab_cache = s;
+
+/*
+ * IAMROOT, 2022.06.18:
+ * - slab flag를 set한다. 만약 비상메모리로 할당받아왔다면 SlabPfmemalloc flag도
+ *   붙인다.
+ */
     __SetPageSlab(page);
     if (page_is_pfmemalloc(page))
         SetPageSlabPfmemalloc(page);
@@ -2038,6 +2255,10 @@ static struct page *allocate_slab(struct kmem_cache *s, gfp_t flags, int node)
     shuffle = shuffle_freelist(s, page);
 
     if (!shuffle) {
+/*
+ * IAMROOT, 2022.06.18:
+ * - shuffle이 아니거나 기능을 안쓰는 경우등일때 순서대로 연결한다.
+ */
         start = fixup_red_left(s, start);
         start = setup_object(s, page, start);
         page->freelist = start;
@@ -2051,6 +2272,12 @@ static struct page *allocate_slab(struct kmem_cache *s, gfp_t flags, int node)
     }
 
     page->inuse = page->objects;
+
+/*
+ * IAMROOT, 2022.06.18:
+ * - frozen은 cpu에 해당 page가 있을 경우 set된다.
+ *   미리 cpu에 바로 연결될 준비를 해놓는 개념.
+ */
     page->frozen = 1;
 
 out:
@@ -2062,6 +2289,11 @@ static struct page *allocate_slab(struct kmem_cache *s, gfp_t flags, int node)
     return page;
 }
 
+/*
+ * IAMROOT, 2022.06.18:
+ * - slab page를 할당받고 debug정보 초기화, fp를 전부 이어 놓는다. 그리고 frozen
+ *   상태를 해놓는다.
+ */
 static struct page *new_slab(struct kmem_cache *s, gfp_t flags, int node)
 {
     if (unlikely(flags & GFP_SLAB_BUG_MASK))
@@ -2218,6 +2450,10 @@ static void *get_partial_node(struct kmem_cache *s, struct kmem_cache_node *n,
      * partial slab and there is none available then get_partial()
      * will return NULL.
      */
+/*
+ * IAMROOT, 2022.06.18:
+ * - kmem_cache_node가 없거나 parital도 없으면 return null.
+ */
     if (!n || !n->nr_partial)
         return NULL;
 
@@ -2282,10 +2518,37 @@ static void *get_any_partial(struct kmem_cache *s, gfp_t flags,
      * may be expensive if we do it every time we are trying to find a slab
      * with available objects.
      */
+/*
+ * IAMROOT, 2022.06.18:
+ * - papago
+ *   조각 모음 비율을 사용하면 노드 간 조각 모음과 노드 로컬 할당 간의 균형을
+ *   구성할 수 있습니다. defrag_ratio가 낮을수록 다른 노드에서 부분 슬래브를
+ *   얻으려고 시도하는 대신 로컬 할당을 수행하는 경향이 높아집니다.
+ *
+ *   defrag_ratio가 0으로 설정되면 kmalloc()은 항상 노드 로컬 객체를 반환합니다.
+ *   비율이 더 높으면 kmalloc()은 다른 노드에서 부분 슬래브를 가져와 채워지기
+ *   때문에 노드 개체를 반환할 수 있습니다.
+ *
+ *   /sys/kernel/slab/xx/remote_node_defrag_ratio가 100으로 설정되면
+ *   (defrag_ratio = 1000이 됨) 모든(거의 거의) 할당이 먼저 다른 노드에서 슬랩
+ *   캐시 조각 모음을 시도합니다.
+ *   이것은 사용 가능한 개체가 있는 슬래브를 찾으려고 할 때마다 비용이 많이 들 수
+ *   있는 부분 슬래브를 찾기 위해 모든 노드를 스캔하는 것을 의미합니다.
+ *
+ * - /sys/kernel/slab/xx/remote_node_defrag_ratio
+ *   유저에서 보면 100(default 100.). kernel에서는 1000로 환산해서 사용한다.
+ *   remote node에서도 가져오는 비율.
+ */
     if (!s->remote_node_defrag_ratio ||
             get_cycles() % 1024 > s->remote_node_defrag_ratio)
         return NULL;
 
+/*
+ * IAMROOT, 2022.06.18:
+ * - task mempolicy에 따라 node를 구해오고 해당 node로 시작하는 zonelist를 구해와
+ *   zone을 iterate한다.
+ *   cache node가 어느 zone에서도 없다면 iterate가 종료되고 return null.
+ */
     do {
         cpuset_mems_cookie = read_mems_allowed_begin();
         zonelist = node_zonelist(mempolicy_slab_node(), flags);
@@ -2412,6 +2675,10 @@ static void init_kmem_cache_cpus(struct kmem_cache *s)
  * Assumes the slab has been already safely taken away from kmem_cache_cpu
  * by the caller.
  */
+/*
+ * IAMROOT, 2022.06.18:
+ * - 
+ */
 static void deactivate_slab(struct kmem_cache *s, struct page *page,
                 void *freelist)
 {
@@ -2903,6 +3170,11 @@ slab_out_of_memory(struct kmem_cache *s, gfp_t gfpflags, int nid)
 #endif
 }
 
+/*
+ * IAMROOT, 2022.06.18:
+ * - 긴급메모리에서 가져온 page인지 확인하고 맞다면 @gfpflags가 긴급메모리에서
+ *   실제로 요청한 flag인지 확인한다.
+ */
 static inline bool pfmemalloc_match(struct page *page, gfp_t gfpflags)
 {
     if (unlikely(PageSlabPfmemalloc(page)))
@@ -2988,6 +3260,10 @@ static void *___slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node,
 
 reread_page:
 
+/*
+ * IAMROOT, 2022.06.18:
+ * - @c에 page가 없는경우 바로 new_slab
+ */
     page = READ_ONCE(c->page);
     if (!page) {
         /*
@@ -3054,6 +3330,11 @@ static void *___slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node,
      * That page must be frozen for per cpu allocations to work.
      */
     VM_BUG_ON(!c->page->frozen);
+/*
+ * IAMROOT, 2022.06.18:
+ * - c->freelist가 다음 object를 가리키게 한다.
+ * - tid += TID_STEP
+ */
     c->freelist = get_freepointer(s, freelist);
     c->tid = next_tid(c->tid);
     local_unlock_irqrestore(&s->cpu_slab->lock, flags);
@@ -3074,6 +3355,10 @@ static void *___slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node,
 
 new_slab:
 
+/*
+ * IAMROOT, 2022.06.18:
+ * - c->paritial page가 있는지 검사. 없다면 new_objects로 진행.
+ */
     if (slub_percpu_partial(c)) {
         local_lock_irqsave(&s->cpu_slab->lock, flags);
         if (unlikely(c->page)) {
@@ -3095,11 +3380,20 @@ static void *___slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node,
 
 new_objects:
 
+/*
+ * IAMROOT, 2022.06.18:
+ * - 요청 @node의 parital에서 slab page를 가져와본다.
+ *   n->paritial의 slab page가 없으면 freelist는 null.
+ */
     freelist = get_partial(s, gfpflags, node, &page);
     if (freelist)
         goto check_new_page;
 
     slub_put_cpu_ptr(s->cpu_slab);
+/*
+ * IAMROOT, 2022.06.18:
+ * - n->partial도 없었으므로 새로운 frozen상태의 slab page를 구해온다.
+ */
     page = new_slab(s, gfpflags, node);
     c = slub_get_cpu_ptr(s->cpu_slab);
 
@@ -3112,6 +3406,11 @@ static void *___slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node,
      * No other reference to the page yet so we can
      * muck around with it freely without cmpxchg
      */
+
+/*
+ * IAMROOT, 2022.06.18:
+ * - page->freelist를 null로 끊고 c freelist에 넣을 준비를 한다.
+ */
     freelist = page->freelist;
     page->freelist = NULL;
 
@@ -3119,6 +3418,11 @@ static void *___slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node,
 
 check_new_page:
 
+/*
+ * IAMROOT, 2022.06.18:
+ * - debug라면, alloc_debug_processing을 통해 잘못된 slab page라면 새로운 slab을
+ *   할당받도록 new_slab으로 이동한다.
+ */
     if (kmem_cache_debug(s)) {
         if (!alloc_debug_processing(s, page, freelist, addr)) {
             /* Slab failed checks. Next slab needed */
@@ -3132,6 +3436,11 @@ static void *___slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node,
         }
     }
 
+/*
+ * IAMROOT, 2022.06.18:
+ * - page가 긴급메모리에서 가져왔는데 @gfpflags에 긴급요청이 없었으면. 즉
+ *   flag와 맞지 않게 메모리를 가져왔으면 return_single.
+ */
     if (unlikely(!pfmemalloc_match(page, gfpflags)))
         /*
          * For !pfmemalloc_match() case we don't load freelist so that
@@ -3216,6 +3525,18 @@ static __always_inline void maybe_wipe_obj_freeptr(struct kmem_cache *s,
  *
  * Otherwise we can simply pick the next object from the lockless free list.
  */
+/*
+ * IAMROOT, 2022.06.18:
+ * - papago
+ *   할당 기능(kmalloc, kmem_cache_alloc)이 해당 기능으로 접힌 fastpath를 갖도록
+ *   인라인된 fastpath. 따라서 빠른 경로에서 충족될 수 있는 요청에 대한 함수
+ *   호출 오버헤드가 없습니다.
+ *
+ *   fastpath는 먼저 lockless freelist를 사용할 수 있는지 확인하여 작동합니다.
+ *   그렇지 않은 경우 느린 처리를 위해 __slab_alloc이 호출됩니다.
+ *
+ *   그렇지 않으면 잠금 없는 자유 목록에서 다음 개체를 간단히 선택할 수 있습니다.*
+ */
 static __always_inline void *slab_alloc_node(struct kmem_cache *s,
         gfp_t gfpflags, int node, unsigned long addr, size_t orig_size)
 {
@@ -3247,6 +3568,19 @@ static __always_inline void *slab_alloc_node(struct kmem_cache *s,
      * two reads, it's OK as the two are still associated with the same cpu
      * and cmpxchg later will validate the cpu.
      */
+/*
+ * IAMROOT, 2022.06.18:
+ * - papago
+ *   이 cpu ptr을 통해 kmem_cache cpu 데이터를 읽어야 합니다. 선점이
+ *   활성화되었습니다. 한 CPU 영역에서 읽는 동안 CPU 간에 앞뒤로 전환할 수 있습니다.
+ *   cmpxchg를 수행할 때 원래 CPU에서 다시 종료되는 한 문제가 되지 않습니다.
+ *
+ *   tid 및 kmem_cache_cpu가 동일한 CPU에서 검색되도록 보장해야 합니다.
+ *   먼저 kmem_cache_cpu 포인터를 읽고 tid를 읽는 데 사용합니다.
+ *   우리가 선점되어 두 읽기 사이에 다른 CPU로 전환되는 경우 두 읽기가
+ *   여전히 동일한 CPU와 연결되어 있고 나중에 cmpxchg에서 CPU의 유효성을
+ *   검사하므로 괜찮습니다.
+ */
     c = raw_cpu_ptr(s->cpu_slab);
     tid = READ_ONCE(c->tid);
 
@@ -3258,6 +3592,15 @@ static __always_inline void *slab_alloc_node(struct kmem_cache *s,
      * page could be one associated with next tid and our alloc/free
      * request will be failed. In this case, we will retry. So, no problem.
      */
+/*
+ * IAMROOT, 2022.06.18:
+ * papago
+ * 여기서 사용되는 Irqless 객체 할당/해제 알고리즘은 cpu_slab의 데이터를 가져오는
+ * 순서에 따라 다릅니다. tid는 이전 tid와 연결된 개체 및 페이지가 현재 tid와 함께
+ * 사용되지 않도록 보장하기 위해 c에서 무엇보다 먼저 가져와야 합니다. tid를 먼저
+ * 가져오면 객체와 페이지가 다음 tid와 연결될 수 있으며 할당/해제 요청이
+ * 실패합니다. 이 경우 다시 시도합니다. 문제 없습니다. 
+ */
     barrier();
 
     /*
@@ -3266,6 +3609,12 @@ static __always_inline void *slab_alloc_node(struct kmem_cache *s,
      * occurs on the right processor and that there was no operation on the
      * linked list in between.
      */
+/*
+ * IAMROOT, 2022.06.18:
+ * - 트랜잭션 ID는 CPU별 및 CPU별 대기열의 작업별로 global적으로 고유합니다.
+ *   따라서 cmpxchg_double이 올바른 프로세서에서 발생하고 그 사이에 연결된 목록에
+ *   대한 작업이 없음을 보장할 수 있습니다.
+ */
 
     object = c->freelist;
     page = c->page;
@@ -3276,6 +3625,17 @@ static __always_inline void *slab_alloc_node(struct kmem_cache *s,
      * the slow path which uses local_lock. It is still relatively fast if
      * there is a suitable cpu freelist.
      */
+/*
+ * IAMROOT, 2022.06.18:
+ * - slowpath가 local_lock_irqsave()를 사용하는 경우 irq 처리기의 fastpath 작업에
+ *   대해 보호되지 않기 때문에 PREEMPT_RT에서 잠금 없는 빠른 경로를 사용할 수
+ *   없습니다. 따라서 local_lock을 사용하는 느린 경로를 선택해야 합니다. 적절한
+ *   CPU 여유 목록이 있으면 여전히 상대적으로 빠릅니다.
+ *
+ * - object == NULL : freelist가 하나도 없다.
+ *   page == 0      : page가 없다.
+ *   !node_match    : 요청 node와 cache의 node가 다른 경우. 요청한 node에서 가져온다.
+ */
     if (IS_ENABLED(CONFIG_PREEMPT_RT) ||
         unlikely(!object || !page || !node_match(page, node))) {
         object = __slab_alloc(s, gfpflags, node, addr, c);
@@ -3296,6 +3656,18 @@ static __always_inline void *slab_alloc_node(struct kmem_cache *s,
          * against code executing on this cpu *not* from access by
          * other cpus.
          */
+/*
+ * IAMROOT, 2022.06.18:
+ * - papgo
+ *   cmpxchg는 추가 작업이 없고 올바른 프로세서에 있는 경우에만 일치합니다.
+ *
+ *   cmpxchg는 원자적으로 다음을 수행합니다(잠금 의미 없이!).
+ *   1. 첫 번째 포인터를 현재 CPU당 영역으로 재배치합니다.
+ *   2. tid 및 freelist가 변경되지 않았는지 확인합니다.
+ *   3. 변경되지 않은 경우 tid 및 freelist를 교체합니다.
+ *   이것은 잠금 의미가 없기 때문에 보호는 이 CPU에서 실행되는 코드에 대해서만
+ *   다른 CPU에 의해 액세스되지 않습니다.
+ */
         if (unlikely(!this_cpu_cmpxchg_double(
                 s->cpu_slab->freelist, s->cpu_slab->tid,
                 object, tid,
@@ -3317,6 +3689,10 @@ static __always_inline void *slab_alloc_node(struct kmem_cache *s,
     return object;
 }
 
+/*
+ * IAMROOT, 2022.06.18:
+ * - 모든 node 대상.
+ */
 static __always_inline void *slab_alloc(struct kmem_cache *s,
         gfp_t gfpflags, unsigned long addr, size_t orig_size)
 {
@@ -3866,6 +4242,34 @@ static unsigned int slub_min_objects;
  * requested a higher minimum order then we start with that one instead of
  * the smallest order which will fit the object.
  */
+
+/*
+ * IAMROOT, 2022.06.18:
+ * - papgo
+ *  slab object 크기가 주어지면 할당 순서를 계산합니다.
+ *  
+ *  할당 순서는 성능 및 기타 시스템 구성 요소에 상당한 영향을 미칩니다.
+ *  일반적으로 0차 할당은 페이지 할당자에서 조각화를 일으키지 않으므로 0차 할당이
+ *  선호되어야 합니다. 더 큰 개체는 사용하지 않은 공간이 너무 많이 남아 있을 수
+ *  있으므로 순서 0 슬래브에 넣는 데 문제가 있습니다. 슬래브의 1/16 이상이
+ *  낭비되면 더 높은 순서로 이동합니다.
+ *  
+ *  만족스러운 성능에 도달하려면 하나의 슬래브에 최소한의 개체 수를 보장해야 합니다.
+ *  그렇지 않으면 list_lock을 취해야 하는 부분 목록에서 너무 많은 활동을 생성할 수
+ *  있습니다. 이것은 거의 사용되지 않는 대형 슬래브의 경우 덜 우려됩니다.
+ *  
+ *  slub_max_order는 슬래브에 있는 객체의 수를 중요한 것으로 간주하는 것을 중단하기
+ *  시작하는 순서를 지정합니다. slub_max_order에 도달하면 페이지 순서를 가능한 한
+ *  낮게 유지하려고 합니다. 그래서 우리는 작은 페이지 주문에 찬성하여 더 많은 공간
+ *  낭비를 받아들입니다.
+ *
+ *  고차 할당은 또한 슬래브에 더 많은 개체를 배치할 수 있게 하여 개체 처리
+ *  오버헤드를 줄입니다. 사용자가 더 높은 최소 주문을 요청한 경우 개체에 맞는
+ *  최소 주문 대신 해당 주문부터 시작합니다.
+ *
+ * - slab_size / fract의 크기가 unused 보다 큰지를 확인한다. 낭비공간이 적은
+ *   order값을 얻기 위한 작업이다.
+ */
 static inline unsigned int slab_order(unsigned int size,
         unsigned int min_objects, unsigned int max_order,
         unsigned int fract_leftover)
@@ -3873,9 +4277,24 @@ static inline unsigned int slab_order(unsigned int size,
     unsigned int min_order = slub_min_order;
     unsigned int order;
 
+/*
+ * IAMROOT, 2022.06.18:
+ * - min_order에 대해서 object개수가 너무 많으면(min order가 너무 큰 상황)
+ *   MAX_OBJS_PER_PAGE의 기준으로 맞춰서 order를 구한다.
+ *
+ * - ex) size = 16, min_order = 7
+ *   4k * 2^x / 16 >= 32k => 2^x >= 2^7 => x >= 7
+ *   order_objects값이 32k가 나와 MAX_OBJS_PER_PAGE값이 초과.
+ *   즉 min_order값이 너무 크다.
+ *   get_order(16 * 32767) - 1 => 6
+ */
     if (order_objects(min_order, size) > MAX_OBJS_PER_PAGE)
         return get_order(size * MAX_OBJS_PER_PAGE) - 1;
 
+/*
+ * IAMROOT, 2022.06.18:
+ * - min_order ~ max_order
+ */
     for (order = max(min_order, (unsigned int)get_order(min_objects * size));
             order <= max_order; order++) {
 
@@ -3884,6 +4303,10 @@ static inline unsigned int slab_order(unsigned int size,
 
         rem = slab_size % size;
 
+/*
+ * IAMROOT, 2022.06.18:
+ * - slab_size / fract_leftover보다 적으면. 즉 낭비가 적으면 break.
+ */
         if (rem <= slab_size / fract_leftover)
             break;
     }
@@ -3891,6 +4314,11 @@ static inline unsigned int slab_order(unsigned int size,
     return order;
 }
 
+/*
+ * IAMROOT, 2022.06.18:
+ * - @size를 사용해 min_objects를 기준으로 min_order ~ max_order사이의 값으로
+ *   가장 낭비가 적은 order를 구한다. 단 범위를 벗어날수도 있다.
+ */
 static inline int calculate_order(unsigned int size)
 {
     unsigned int order;
@@ -3920,15 +4348,32 @@ static inline int calculate_order(unsigned int size)
         nr_cpus = num_present_cpus();
         if (nr_cpus <= 1)
             nr_cpus = nr_cpu_ids;
+/*
+ * IAMROOT, 2022.06.18:
+ * - min_objects = 4 * 2log(nr_cpus)
+ * - ex)
+ *   nr_cpus == 4 일때 4 * (3 + 1) = 16
+ */
         min_objects = 4 * (fls(nr_cpus) + 1);
     }
     max_objects = order_objects(slub_max_order, size);
     min_objects = min(min_objects, max_objects);
 
+/*
+ * IAMROOT, 2022.06.18:
+ * - 1. slab order 범위 내 적절한 order 산출
+ *   2. 1개 object가 들어갈 수 있는 slab order 범위 내 산출
+ *   3. 1개 object가 들어갈수 있는 order 산출 (order 무제한)
+ */
     while (min_objects > 1) {
         unsigned int fraction;
 
         fraction = 16;
+/*
+ * IAMROOT, 2022.06.18:
+ * - 1/16(6.25%) -> 1/8(12.5%) -> 1/4(25%) 로 fraction을 확인한다.
+ *   최대 25%낭비까지만 고려한다.
+ */
         while (fraction >= 4) {
             order = slab_order(size, min_objects,
                     slub_max_order, fraction);
@@ -3943,6 +4388,18 @@ static inline int calculate_order(unsigned int size)
      * We were unable to place multiple objects in a slab. Now
      * lets see if we can place a single object there.
      */
+
+/*
+ * IAMROOT, 2022.06.18:
+ * - 2.
+ *   min_objects를 무시하고 1개 이상. slub_max_orde는 제한사항 그대로 사용.
+ *   fraction 무시(낭비 무시).
+ *
+ * - 낭비가 1 /4 보다 큰경우 진입하게 된다. 낭비가 얼마되든 상관이 없이 order만을
+ *   고려한다.
+ *
+ * - ex) slub_max_order = 3, size = 20k인경우 50%가까이 낭비되는 상태로 들어올것.
+ */
     order = slab_order(size, 1, slub_max_order, 1);
     if (order <= slub_max_order)
         return order;
@@ -3950,9 +4407,23 @@ static inline int calculate_order(unsigned int size)
     /*
      * Doh this slab cannot be placed using slub_max_order.
      */
+/*
+ * IAMROOT, 2022.06.18:
+ * - 3.
+ *   MAX_ORDER로 계산. fraction 무시.
+ *
+ * - ex) slub_max_order = 3, size = 40k일때.
+ *   max order만으로는 32k까지만 되므로, max order를 4로 키워야된다.
+ */
     order = slab_order(size, 1, MAX_ORDER, 1);
     if (order < MAX_ORDER)
         return order;
+/*
+ * IAMROOT, 2022.06.18:
+ * - MAX_ORDER로도 order를 못구함. system config가 안맞는다.
+ *
+ * - ex) size가 4k * 2^11 보다 큰 경우. MAX_ORDER로도 할당이 안되는 경우.
+ */
     return -ENOSYS;
 }
 
@@ -4125,6 +4596,11 @@ static void set_cpu_partial(struct kmem_cache *s)
  * calculate_sizes() determines the order and the distribution of data within
  * a slab object.
  */
+/*
+ * IAMROOT, 2022.06.18:
+ * - size (debug flag, align등을 고려), flags, allocflags, red_left_pad,
+ *   offset, oo(min_order, max_order, @forced_order 고려)등을 결정한다.
+ */
 static int calculate_sizes(struct kmem_cache *s, int forced_order)
 {
     slab_flags_t flags = s->flags;
@@ -4222,6 +4698,15 @@ static int calculate_sizes(struct kmem_cache *s, int forced_order)
  *   s->offset >= s->inuse라는 가정은 freeptr_outside_object() 함수에서 사용되는
  *   free pointer가 객체 외부에 있다는 것을 의미합니다. 그것이 더 이상 사실이
  *   아니라면 함수를 수정해야 합니다.
+ *
+ * - if문의 조건에 해당하면 시작주소(offset)을 조정하고 뒤에 long byte를 추가한다.
+ *
+ * - object_size = 20이라고 가정. size는 align되어 24라고 했을대.
+ *     +----------------+-+--+       
+ *     |  obj_size=20   | |fp|       
+ *     +________________+_+--+       
+ *                        ^offset = 24
+ *     <---new_size=32------->
  */
         s->offset = size;
         size += sizeof(void *);
@@ -4236,7 +4721,17 @@ static int calculate_sizes(struct kmem_cache *s, int forced_order)
  * - papgo
  *   인접한 할당에서 작은 크기의 오버/언더플로를 방지하기 위해 개체의
  *   가장자리에서 멀리 유지하기 위해 개체의 중간 근처에 freelist 포인터를
- *   저장합니다.*
+ *   저장합니다.
+ *
+ * - over/under flow 방지를 위해 fp를 중앙으로 이동한다.(offset 추가.)
+ *
+ * - object_size = 20이라고 가정. size는 align되어 24라고 했을대.
+ *               obj_size=20   
+ *           +-------+--+-----+-+          
+ *           |       |fp|     | |          
+ *           +_______+__+_____+_+          
+ *                   ^offset = 8
+ *           <--- size=24------->
  */
         s->offset = ALIGN_DOWN(s->object_size / 2, sizeof(void *));
     }
@@ -4247,6 +4742,10 @@ static int calculate_sizes(struct kmem_cache *s, int forced_order)
          * Need to store information about allocs and frees after
          * the object.
          */
+/*
+ * IAMROOT, 2022.06.18:
+ * - 할당, 해제용으로 총 2개.
+ */
         size += 2 * sizeof(struct track);
 #endif
 
@@ -4260,6 +4759,20 @@ static int calculate_sizes(struct kmem_cache *s, int forced_order)
          * corrupted if a user writes before the start
          * of the object.
          */
+/*
+ * IAMROOT, 2022.06.18:
+ * - long + red_left_pad
+ *  
+ * - s->align을 64라고 가정했을때.
+ *   <- red zone(s->align) -> <-----old size ---------->
+ *   +------------------------+------------------------+---+
+ *   | (8) | (54)             | object                 |(8)|
+ *   +________________________+________________________+___+   
+ *     Z      PAD             ^red_left_pads            Z
+ *   <--------- new size = red_left_pad + old_size + 8  --->
+ *
+ *
+ */
         size += sizeof(void *);
 
         s->red_left_pad = sizeof(void *);
@@ -4273,8 +4786,17 @@ static int calculate_sizes(struct kmem_cache *s, int forced_order)
      * offset 0. In order to align the objects we have to simply size
      * each object to conform to the alignment.
      */
+/*
+ * IAMROOT, 2022.06.18:
+ * - 최종적으로 s->align으로 size를 다시 align해준다.
+ */
     size = ALIGN(size, s->align);
     s->size = size;
+/*
+ * IAMROOT, 2022.06.18:
+ * - Git blame 참고
+ *   mm: slub: implement SLUB version of obj_to_index()
+ */
     s->reciprocal_size = reciprocal_value(size);
     if (forced_order >= 0)
         order = forced_order;
@@ -4285,15 +4807,31 @@ static int calculate_sizes(struct kmem_cache *s, int forced_order)
         return 0;
 
     s->allocflags = 0;
+/*
+ * IAMROOT, 2022.06.18:
+ * - order가 1이상이면 compound_order 처리.
+ */
     if (order)
         s->allocflags |= __GFP_COMP;
 
+/*
+ * IAMROOT, 2022.06.18:
+ * - dma 영역내 할당.
+ */
     if (s->flags & SLAB_CACHE_DMA)
         s->allocflags |= GFP_DMA;
 
+/*
+ * IAMROOT, 2022.06.18:
+ * - dma32 영역내 할당.
+ */
     if (s->flags & SLAB_CACHE_DMA32)
         s->allocflags |= GFP_DMA32;
 
+/*
+ * IAMROOT, 2022.06.18:
+ * - reclaim 가능한 slab을 만들도록 한다.
+ */
     if (s->flags & SLAB_RECLAIM_ACCOUNT)
         s->allocflags |= __GFP_RECLAIMABLE;
 
@@ -4301,6 +4839,13 @@ static int calculate_sizes(struct kmem_cache *s, int forced_order)
      * Determine the number of objects per slab
      */
     s->oo = oo_make(order, size);
+/*
+ * IAMROOT, 2022.06.18:
+ * - size로 재계산을하여 min oo를 구해놓는다.
+ * - max oo도 s->oo와 비교하여 갱신한다.
+ *   alias cache(size와 flag가 비슷해서 원래 있던 cache를 다른 곳에서 사용하는경우)
+ *   를 open할때 상황에따라 order가 다를 수 잇으므로 max를 갱신해주는것이다.
+ */
     s->min = oo_make(get_order(size), size);
     if (oo_objects(s->oo) > oo_objects(s->max))
         s->max = s->oo;
@@ -4878,6 +5423,10 @@ static int slab_mem_going_online_callback(void *arg)
     return ret;
 }
 
+/*
+ * IAMROOT, 2022.06.18:
+ * - memory node가 추가되거나 삭제 되거나 할때 callback으로 호출된다.
+ */
 static int slab_memory_callback(struct notifier_block *self,
                 unsigned long action, void *arg)
 {
@@ -4920,6 +5469,10 @@ static struct notifier_block slab_memory_callback_nb = {
  * that may be pointing to the wrong kmem_cache structure.
  */
 
+/*
+ * IAMROOT, 2022.06.18:
+ * - static영역에 만들어진 cache를 동적영역으로 옮긴다.
+ */
 static struct kmem_cache * __init bootstrap(struct kmem_cache *static_cache)
 {
     int node;
@@ -5001,9 +5554,18 @@ void __init kmem_cache_init(void)
     create_boot_cache(kmem_cache_node, "kmem_cache_node",
         sizeof(struct kmem_cache_node), SLAB_HWCACHE_ALIGN, 0, 0);
 
+/*
+ * IAMROOT, 2022.06.18:
+ * - notifier에 slab_memory_callback_nb을 등록한다.
+ */
     register_hotmemory_notifier(&slab_memory_callback_nb);
 
     /* Able to allocate the per node structures */
+
+/*
+ * IAMROOT, 2022.06.18:
+ * - kmem_cache_node를 할당할수 있는 상태가 되서 state를 변경한다.
+ */
     slab_state = PARTIAL;
 
 /*
@@ -5068,6 +5630,7 @@ __kmem_cache_alias(const char *name, unsigned int size, unsigned int align,
 /*
  * IAMROOT, 2022.06.11: 
  * 슬럽(slub) 캐시를 생성한다.
+ * - config가 존재할 경우 sys/kernel/slab, debugfs에 경로가 생긴다.
  */
 int __kmem_cache_create(struct kmem_cache *s, slab_flags_t flags)
 {
@@ -5078,6 +5641,10 @@ int __kmem_cache_create(struct kmem_cache *s, slab_flags_t flags)
         return err;
 
     /* Mutex is not taken during early boot */
+/*
+ * IAMROOT, 2022.06.18:
+ * - 부팅중엔(아직 slab이 안만들어지는 상황) 빠져나간다.
+ */
     if (slab_state <= UP)
         return 0;
 
@@ -6184,6 +6751,10 @@ static int sysfs_slab_alias(struct kmem_cache *s, const char *name)
     return 0;
 }
 
+/*
+ * IAMROOT, 2022.06.18:
+ * - sysfs의 slab
+ */
 static int __init slab_sysfs_init(void)
 {
     struct kmem_cache *s;
 

번호 제목 글쓴이 날짜 조회 수
공지 [공지] 스터디 정리 노트 공간입니다. woos 2016.05.14 623
145 [커널 18차] 65주차 kkr 2022.08.20 27
144 [커널 18차] 64주차 kkr 2022.08.13 75
143 [커널 17차] 100주차 [1] ㅇㅇㅇ 2022.08.06 98
142 [커널 18차] 63주차 kkr 2022.08.06 102
141 [커널 17차] 99주차 ㅇㅇㅇ 2022.07.31 35
140 [커널 18차] 62주차 kkr 2022.07.30 26
139 [커널 17차] 97~98주차 ㅇㅇㅇ 2022.07.24 52
138 [커널 18차] 61주차 kkr 2022.07.23 112
137 [커널 18차] 60주차 kkr 2022.07.16 128
136 [커널 17차] 95~96주차 ㅇㅇㅇ 2022.07.10 105
135 [커널 18차] 59주차 kkr 2022.07.09 125
134 [커널 19차] 8주차 kanlee 2022.07.02 160
133 [커널 19차] 7주차 kanlee 2022.07.02 95
132 [커널 19차] 6주차 kanlee 2022.07.02 42
131 [커널 19차] 5주차 kanlee 2022.07.02 38
130 [커널 19차] 4주차 kanlee 2022.07.02 106
129 [커널 18차] 57주차 kkr 2022.06.25 129
128 [커널 17차] 94주차 ㅇㅇㅇ 2022.06.19 80
» [커널 18차] 56주차 kkr 2022.06.18 71
126 [커널 17차] 92~93주차 ㅇㅇㅇ 2022.06.11 92
XE Login