[커널 18차] 50주차

2022.05.10 18:18

kkr 조회 수:207

git : https://github.com/iamroot18/5.10/commit/80afe12f1c731c4d2cfd490339b3487f7dd01e76

 
diff --git a/include/linux/bitmap.h b/include/linux/bitmap.h
index b9e8696ea1c1..aad28e05df69 100644
--- a/include/linux/bitmap.h
+++ b/include/linux/bitmap.h
@@ -391,6 +391,10 @@ static inline int bitmap_intersects(const unsigned long *src1,
         return __bitmap_intersects(src1, src2, nbits);
 }
 
+/*
+ * IAMROOT, 2022.05.07:
+ * - @src1이 @src2에 모두 포함되어있는지 판별한다.
+ */
 static inline int bitmap_subset(const unsigned long *src1,
             const unsigned long *src2, unsigned int nbits)
 {
diff --git a/include/linux/mm.h b/include/linux/mm.h
index a099b72852eb..7f6d32cc6893 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -2056,6 +2056,10 @@ static inline bool get_user_page_fast_only(unsigned long addr,
 /*
  * per-process(per-mm_struct) statistics.
  */
+/*
+ * IAMROOT, 2022.05.07:
+ * - @member에 대한 실제 사용 phy memory를 구한다.
+ */
 static inline unsigned long get_mm_counter(struct mm_struct *mm, int member)
 {
     long val = atomic_long_read(&mm->rss_stat.count[member]);
@@ -2109,6 +2113,10 @@ static inline int mm_counter(struct page *page)
     return mm_counter_file(page);
 }
 
+/*
+ * IAMROOT, 2022.05.07:
+ * - 실제 할당되어 사용되는 page 수를 구한다.
+ */
 static inline unsigned long get_mm_rss(struct mm_struct *mm)
 {
     return get_mm_counter(mm, MM_FILEPAGES) +
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index f6012515cde9..c79e9cbbd00b 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -539,6 +539,10 @@ struct mm_struct {
          * @mm_count (which may then free the &struct mm_struct if
          * @mm_count also drops to 0).
          */
+/*
+ * IAMROOT, 2022.05.07:
+ * - mm을 사용하고있는 process나 thread 수.
+ */
         atomic_t mm_users;
 
         /**
diff --git a/include/linux/sched/mm.h b/include/linux/sched/mm.h
index 96e70c5e7632..0823f393bdab 100644
--- a/include/linux/sched/mm.h
+++ b/include/linux/sched/mm.h
@@ -31,6 +31,10 @@ extern struct mm_struct *mm_alloc(void);
  * See also <Documentation/vm/active_mm.rst> for an in-depth explanation
  * of &mm_struct.mm_count vs &mm_struct.mm_users.
  */
+/*
+ * IAMROOT, 2022.05.07:
+ * - @mm에 대한 refcnt(pin)를 증가시킨다.
+ */
 static inline void mmgrab(struct mm_struct *mm)
 {
     atomic_inc(&mm->mm_count);
diff --git a/include/linux/sched/signal.h b/include/linux/sched/signal.h
index e5f4ce622ee6..b21041b8a292 100644
--- a/include/linux/sched/signal.h
+++ b/include/linux/sched/signal.h
@@ -218,6 +218,13 @@ struct signal_struct {
      * oom
      */
     bool oom_flag_origin;
+/*
+ * IAMROOT, 2022.05.07:
+ * - lagacy 방식으로 -17 ~ 15의 제어로 /proc/${pid}/oom_adj 으로 사용했으며
+ *   현재는 -1000 ~ 1000까지의 숫자로 /proc/${pid}/oom_score_adj으로 사용한다.
+ *   (oom_adj_write(), oom_socre_adj_write() 참고)
+ *   lagacy방식으로 사용할경우 현재 score로 변환하여 고쳐주긴한다.
+ */
     short oom_score_adj;        /* OOM kill score adjustment */
     short oom_score_adj_min;    /* OOM kill score adjustment min value.
                      * Only settable by CAP_SYS_RESOURCE. */
@@ -600,6 +607,10 @@ extern void flush_itimer_signals(void);
 #define next_task(p) \
     list_entry_rcu((p)->tasks.next, struct task_struct, tasks)
 
+/*
+ * IAMROOT, 2022.05.07:
+ * - init_task부터 모든 process를 iterate한다.
+ */
 #define for_each_process(p) \
     for (p = &init_task ; (p = next_task(p)) != &init_task ; )
 
@@ -615,13 +626,25 @@ extern bool current_is_single_threaded(void);
 #define while_each_thread(g, t) \
     while ((t = next_thread(t)) != g)
 
+/*
+ * IAMROOT, 2022.05.07:
+ * - signal을 공유하고 있는 list iteration.
+ */
 #define __for_each_thread(signal, t)    \
     list_for_each_entry_rcu(t, &(signal)->thread_head, thread_node)
 
+/*
+ * IAMROOT, 2022.05.07:
+ * - p(process)에 대한 thread들을 iterate한다.
+ */
 #define for_each_thread(p, t)        \
     __for_each_thread((p)->signal, t)
 
 /* Careful: this is a double loop, 'break' won't work as expected. */
+/*
+ * IAMROOT, 2022.05.07:
+ * - 모든 process의 모든 thread를 순회한다.
+ */
 #define for_each_process_thread(p, t)    \
     for_each_process(p) for_each_thread(p, t)
 
diff --git a/include/uapi/linux/mempolicy.h b/include/uapi/linux/mempolicy.h
index 046d0ccba4cd..4000010a9833 100644
--- a/include/uapi/linux/mempolicy.h
+++ b/include/uapi/linux/mempolicy.h
@@ -18,9 +18,25 @@
 /* Policies */
 enum {
     MPOL_DEFAULT,
+/*
+ * IAMROOT, 2022.05.07:
+ * - 선호 node(반드시는 아님)
+ */
     MPOL_PREFERRED,
+/*
+ * IAMROOT, 2022.05.07:
+ * - 특정 node에 memory를 할당할수있는.
+ */
     MPOL_BIND,
+/*
+ * IAMROOT, 2022.05.07:
+ * - 2개 이상의 node에서 교대로 할당.
+ */
     MPOL_INTERLEAVE,
+/*
+ * IAMROOT, 2022.05.07:
+ * - cpu가 있는 node에서만 할당.
+ */
     MPOL_LOCAL,
     MPOL_PREFERRED_MANY,
     MPOL_MAX,    /* always last member of enum */
diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
index 0255be5011e3..8a1eb08fee3c 100644
--- a/kernel/cgroup/cpuset.c
+++ b/kernel/cgroup/cpuset.c
@@ -3643,6 +3643,10 @@ EXPORT_SYMBOL_GPL(cpuset_mem_spread_node);
  * to the other.
  **/
 
+/*
+ * IAMROOT, 2022.05.07:
+ * - @tas1의 node가 @task2의 node에 속해있는지 확인한다.
+ */
 int cpuset_mems_allowed_intersects(const struct task_struct *tsk1,
                    const struct task_struct *tsk2)
 {
diff --git a/kernel/freezer.c b/kernel/freezer.c
index 45ab36ffd0e7..fd7227c0ff31 100644
--- a/kernel/freezer.c
+++ b/kernel/freezer.c
@@ -143,6 +143,10 @@ bool freeze_task(struct task_struct *p)
     return true;
 }
 
+/*
+ * IAMROOT, 2022.05.07:
+ * - @p가 frozen 상태이면 wakeup.
+ */
 void __thaw_task(struct task_struct *p)
 {
     unsigned long flags;
diff --git a/mm/internal.h b/mm/internal.h
index b61df0de0888..41a80aa78fdb 100644
--- a/mm/internal.h
+++ b/mm/internal.h
@@ -205,6 +205,24 @@ struct alloc_context {
  *
  * Assumption: *_mem_map is contiguous at least up to MAX_ORDER
  */
+/*
+ * IAMROOT, 2022.05.07:
+ * - buddy page를 찾는다.
+ * ex) order 0에 대한 pair page
+ *   3 -> 2
+ *   2 -> 3
+ *   1 -> 0
+ *   0 -> 1
+ * ex) order 1에 대한 pair page
+ *   7 -> X
+ *   6 -> 4
+ *   5 -> X
+ *   4 -> 6
+ *   3 -> X
+ *   2 -> 0
+ *   1 -> X
+ *   0 -> 2
+ */
 static inline unsigned long
 __find_buddy_pfn(unsigned long page_pfn, unsigned int order)
 {
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 256e71297f39..72951f568571 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -1284,6 +1284,10 @@ static void invalidate_reclaim_iterators(struct mem_cgroup *dead_memcg)
  *
  * This function must not be called for the root memory cgroup.
  */
+/*
+ * IAMROOT, 2022.05.07:
+ * - @memcg를 root로 tree구조로 iterate하며 @fn을 실행한다.
+ */
 int mem_cgroup_scan_tasks(struct mem_cgroup *memcg,
               int (*fn)(struct task_struct *, void *), void *arg)
 {
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index 9f648e5b91fc..d177e6063070 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -2012,6 +2012,10 @@ bool init_nodemask_of_mempolicy(nodemask_t *mask)
  *
  * Takes task_lock(tsk) to prevent freeing of its mempolicy.
  */
+/*
+ * IAMROOT, 2022.05.07:
+ * - @task가 MPOL_BIND 일때 @mask node에 속해있는지의 여부를 확인한다.
+ */
 bool mempolicy_in_oom_domain(struct task_struct *tsk,
                     const nodemask_t *mask)
 {
@@ -2022,6 +2026,12 @@ bool mempolicy_in_oom_domain(struct task_struct *tsk,
         return ret;
 
     task_lock(tsk);
+
+/*
+ * IAMROOT, 2022.05.07:
+ * - task의 mempolicy를 가져온다. 해당 task가 bind policy라면 mempolicy에 속한 node가
+ *   mask에 포함이 되있는지를 확인한다.
+ */
     mempolicy = tsk->mempolicy;
     if (mempolicy && mempolicy->mode == MPOL_BIND)
         ret = nodes_intersects(mempolicy->nodes, *mask);
diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index 989f35a2bbb1..7ec453aee4b2 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -52,6 +52,30 @@
 #define CREATE_TRACE_POINTS
 #include <trace/events/oom.h>
 
+/*
+ * IAMROOT, 2022.05.07:
+ * --- sysctl_panic_on_oom
+ *
+ * - /proc/sys/vm/panic_on_oom
+ * - Documentation 참고
+ *  0으로 설정하면 커널은 oom_killer라는 일부 악성 프로세스를 종료합니다.
+ *  일반적으로 oom_killer는 악성 프로세스를 제거할 수 있으며 시스템은
+ *  존속합니다.
+ *
+ * 1로 설정하면 메모리 부족이 발생할 때 커널이 패닉에 빠집니다. 그러나
+ * 프로세스가 mempolicy/cpusets에 의해 노드 사용을 제한하고 이러한 노드가
+ * 메모리 소진 상태가 되면 하나의 프로세스가 oom-killer에 의해 중단될 수 있다.
+ * 이 경우 패닉은 발생하지 않습니다. 다른 노드의 메모리가 비어 있을 수 있기
+ * 때문입니다. 이는 시스템 전체 상태가 아직 치명적이지 않을 수 있음을
+ * 의미합니다.
+ *
+ * 만약 이것이 2로 설정된다면, 위에서 언급한 것에도 커널은 강제적으로 패닉을
+ * 일으킨다. memcg 아래서 oom도 발생하며, 전체 시스템이 공황상태에 빠진다. 
+ *
+ * --- sysctl_oom_kill_allocating_task
+ *  oom이 일어날때 사용자가 oom kill을 할 task를 정할때 사용한다. 설정이 되면
+ *  oom score를 할 필요없이 설정된 task로 oom kill을 한다.
+ */
 int sysctl_panic_on_oom;
 int sysctl_oom_kill_allocating_task;
 int sysctl_oom_dump_tasks = 1;
@@ -68,6 +92,10 @@ DEFINE_MUTEX(oom_lock);
 /* Serializes oom_score_adj and oom_score_adj_min updates */
 DEFINE_MUTEX(oom_adj_mutex);
 
+/*
+ * IAMROOT, 2022.05.07:
+ * - oom controller에 memcg가 지정되있는지 확인한다.
+ */
 static inline bool is_memcg_oom(struct oom_control *oc)
 {
     return oc->memcg != NULL;
@@ -86,6 +114,13 @@ static inline bool is_memcg_oom(struct oom_control *oc)
  * This function is assuming oom-killer context and 'current' has triggered
  * the oom-killer.
  */
+/*
+ * IAMROOT, 2022.05.07:
+ * - @start process의 thread들을 iterate하며 oc->nodemask에 따라 같은 node영역을 가진
+ *   thread를 찾는다.
+ * - 같은 node영역을 찾는다는 것은 현재 memory가 모자르는 node를 사용하는 다른 thread
+ *   를 찾아 해당 thread를 죽이면 node에 free memory가 생기므로 node를 찾는것이다.
+ */
 static bool oom_cpuset_eligible(struct task_struct *start,
                 struct oom_control *oc)
 {
@@ -98,6 +133,10 @@ static bool oom_cpuset_eligible(struct task_struct *start,
 
     rcu_read_lock();
     for_each_thread(start, tsk) {
+/*
+ * IAMROOT, 2022.05.07:
+ * - mask != null이면 mempolicy로 처리한다.
+ */
         if (mask) {
             /*
              * If this is a mempolicy constrained oom, tsk's
@@ -111,8 +150,16 @@ static bool oom_cpuset_eligible(struct task_struct *start,
              * This is not a mempolicy constrained oom, so only
              * check the mems of tsk's cpuset.
              */
+/*
+ * IAMROOT, 2022.05.07:
+ * - current의 allow node가 task allow node에 포함되있는지에 대한 여부를 확인한다.
+ */
             ret = cpuset_mems_allowed_intersects(current, tsk);
         }
+/*
+ * IAMROOT, 2022.05.07:
+ * - node 영역이 겹치는 thread를 찾는순간 return true.
+ */
         if (ret)
             break;
     }
@@ -156,6 +203,17 @@ struct task_struct *find_lock_task_mm(struct task_struct *p)
  * order == -1 means the oom kill is required by sysrq, otherwise only
  * for display purposes.
  */
+/*
+ * IAMROOT, 2022.05.07:
+ * - sysrq요청인지(강제로 oom상태 확인. 사용자 요청) 확인한다.
+ * --- /proc/sys/kernel/sysrq
+ *  - help(sudo echo "g" > /proc/sysrq-trigger)
+ *  sysrq: HELP : loglevel(0-9) reboot(b) crash(c) terminate-all-tasks(e)
+ *  memory-full-oom-kill(f) kill-all-tasks(i) thaw-filesystems(j) sak(k)
+ *  show-backtrace-all-active-cpus(l) show-memory-usage(m) nice-all-RT-tasks(n)
+ *  poweroff(o) show-registers(p) show-all-timers(q) unraw(r) sync(s)
+ *  show-task-states(t) unmount(u) show-blocked-tasks(w) dump-ftrace-buffer(z)
+ */
 static inline bool is_sysrq_oom(struct oom_control *oc)
 {
     return oc->order == -1;
@@ -201,6 +259,17 @@ static bool should_dump_unreclaim_slab(void)
  * predictable as possible.  The goal is to return the highest value for the
  * task consuming the most memory to avoid subsequent oom failures.
  */
+/*
+ * IAMROOT, 2022.05.07:
+ * - @p에 대해서 oom_score_adj 및 memory 사용등을 적용해 point를 계산한다.
+ *
+ * ---
+ *  /proc/${pid}/oom_score 를 통해서 점수를 볼수있지만 proc_oom_score()함수를
+ *  참고하면 실제 user에서 볼때는 0 ~ 2000 값으로 변환을 하여 보여줄려고한다.
+ *
+ * ---
+ *  proc_oom_score, proc_oom_adj_operations, proc_oom_score_adj_operations 참고
+ */
 long oom_badness(struct task_struct *p, unsigned long totalpages)
 {
     long points;
@@ -218,6 +287,11 @@ long oom_badness(struct task_struct *p, unsigned long totalpages)
      * unkillable or have been already oom reaped or the are in
      * the middle of vfork
      */
+/*
+ * IAMROOT, 2022.05.07:
+ * - signal->oom_score_adj
+ *   각 thread들이 공유하고 있는 oom_score_adj.
+ */
     adj = (long)p->signal->oom_score_adj;
     if (adj == OOM_SCORE_ADJ_MIN ||
             test_bit(MMF_OOM_SKIP, &p->mm->flags) ||
@@ -230,11 +304,26 @@ long oom_badness(struct task_struct *p, unsigned long totalpages)
      * The baseline for the badness score is the proportion of RAM that each
      * task's rss, pagetable and swap space use.
      */
+/*
+ * IAMROOT, 2022.05.07:
+ * - 실제 사용 memory + swap한 memory + pgtable 사용 memory 
+ */
     points = get_mm_rss(p->mm) + get_mm_counter(p->mm, MM_SWAPENTS) +
         mm_pgtables_bytes(p->mm) / PAGE_SIZE;
     task_unlock(p);
 
     /* Normalize to oom_score_adj units */
+/*
+ * IAMROOT, 2022.05.07:
+ * - adj * (totalpages / 1000) + point 값을 return한다.
+ * ex) points = 100, adj = 10, totalpages = 200000
+ * return = 10 * (200000 / 1000) + 100
+ *        = 2100
+ *
+ * ex) points = 100, adj = 500, totalpages = 200000
+ * return = 500 * (200000 / 1000) + 100
+ *        = 100100
+ */
     adj *= totalpages / 1000;
     points += adj;
 
@@ -251,6 +340,10 @@ static const char * const oom_constraint_text[] = {
 /*
  * Determine the type of allocation constraint.
  */
+/*
+ * IAMROOT, 2022.05.07:
+ * - @oc에 따라 oom에 어떻게 동작할지를 정한다.
+ */
 static enum oom_constraint constrained_alloc(struct oom_control *oc)
 {
     struct zone *zone;
@@ -285,6 +378,15 @@ static enum oom_constraint constrained_alloc(struct oom_control *oc)
      * the page allocator means a mempolicy is in effect.  Cpuset policy
      * is enforced in get_page_from_freelist().
      */
+/*
+ * IAMROOT, 2022.05.07:
+ * - papgo
+ *   이것은 __GFP_THISNODE 할당이 아니므로 페이지 할당기에서 잘린 노드 마스크는
+ *   mem 정책이 적용됨을 의미합니다. CPUet 정책은 get_page_from_freeelist()에
+ *   적용됩니다.
+ * - @oc->nodemask에 memory node가 전부 포함이 안되있으면 memory policy를 따른다.
+ *   (numactl 설정에 따른다.)
+ */
     if (oc->nodemask &&
         !nodes_subset(node_states[N_MEMORY], *oc->nodemask)) {
         oc->totalpages = total_swap_pages;
@@ -294,11 +396,24 @@ static enum oom_constraint constrained_alloc(struct oom_control *oc)
     }
 
     /* Check this allocation failure is caused by cpuset's wall function */
+/*
+ * IAMROOT, 2022.05.07:
+ * - zonelist를 iterate 하면서 해당 zone의 node가 memcg에서 허용한 node인지 확인한다.
+ *   허락을 안했다면 cpuset_limited가 true가된다.
+ * - memory node에 oc->nodemask가 전부 포함이 되었지만 일부 memcg에는 허락이
+ *   안됭상태가 발견되면 cpuset으로 적용하도록 한다.
+ */
     for_each_zone_zonelist_nodemask(zone, z, oc->zonelist,
             highest_zoneidx, oc->nodemask)
         if (!cpuset_zone_allowed(zone, oc->gfp_mask))
             cpuset_limited = true;
 
+/*
+ * IAMROOT, 2022.05.07:
+ * - 현재 task에 허락된 node에 대해서 totalpage를 구하고 CONSTRAINT_CPUSET으로
+ *   return.
+ * - memcg에 허용되지 않은 node가 발견되엇으니 cpuset으로 적용하라는 의미이다.
+ */
     if (cpuset_limited) {
         oc->totalpages = total_swap_pages;
         for_each_node_mask(nid, cpuset_current_mems_allowed)
@@ -308,11 +423,20 @@ static enum oom_constraint constrained_alloc(struct oom_control *oc)
     return CONSTRAINT_NONE;
 }
 
+/*
+ * IAMROOT, 2022.05.07:
+ * - @task를 oom을 위해 평가한다.
+ * - select된 task는 oc->chosen에 갱신되고 해당 점수가 oc->chosen_points에 갱신된다.
+ */
 static int oom_evaluate_task(struct task_struct *task, void *arg)
 {
     struct oom_control *oc = arg;
     long points;
 
+/*
+ * IAMROOT, 2022.05.07:
+ * - 못죽이거나 memory 영향이 없는 경우엔 next로 처리한다.
+ */
     if (oom_unkillable_task(task))
         goto next;
 
@@ -326,6 +450,13 @@ static int oom_evaluate_task(struct task_struct *task, void *arg)
      * the task has MMF_OOM_SKIP because chances that it would release
      * any memory is quite low.
      */
+/*
+ * IAMROOT, 2022.05.07:
+ * - papago
+ *   이 작업은 이미 메모리 예약에 액세스할 수 있으므로 중지되고 있습니다.
+ *   작업에 MMF_OOM_SKIP가 없는 한 다른 작업이 예약에 액세스할 수 있도록
+ *   허용하지 마십시오. 메모리를 방출할 가능성이 매우 낮기 때문입니다.
+ */
     if (!is_sysrq_oom(oc) && tsk_is_oom_victim(task)) {
         if (test_bit(MMF_OOM_SKIP, &task->signal->oom_mm->flags))
             goto next;
@@ -336,12 +467,20 @@ static int oom_evaluate_task(struct task_struct *task, void *arg)
      * If task is allocating a lot of memory and has been marked to be
      * killed first if it triggers an oom, then select it.
      */
+/*
+ * IAMROOT, 2022.05.07:
+ * - origin flag가 set되있으면 많은 memory를 사용중으로 예상하며, 첫번째 타겟으로한다.
+ */
     if (oom_task_origin(task)) {
         points = LONG_MAX;
         goto select;
     }
 
     points = oom_badness(task, oc->totalpages);
+/*
+ * IAMROOT, 2022.05.07:
+ * - 이전에 저장된 최대 값과 비교한다. LONG_MIN이면 아에 선택안한다.
+ */
     if (points == LONG_MIN || points < oc->chosen_points)
         goto next;
 
@@ -364,10 +503,19 @@ static int oom_evaluate_task(struct task_struct *task, void *arg)
  * Simple selection loop. We choose the process with the highest number of
  * 'points'. In case scan was aborted, oc->chosen is set to -1.
  */
+/*
+ * IAMROOT, 2022.05.07:
+ * - oom point가 가장 높은 process를 찾아서 @oc에 기록한다.
+ */
 static void select_bad_process(struct oom_control *oc)
 {
     oc->chosen_points = LONG_MIN;
 
+/*
+ * IAMROOT, 2022.05.07:
+ * - memcg에서의 oom이면 memcg에서, 아니면 전체 process에서 oom_evaluate_task를
+ *   수행한다.
+ */
     if (is_memcg_oom(oc))
         mem_cgroup_scan_tasks(oc->memcg, oom_evaluate_task, oc);
     else {
@@ -659,6 +807,10 @@ static int oom_reaper(void *unused)
     return 0;
 }
 
+/*
+ * IAMROOT, 2022.05.07:
+ * - @task를 oom_reaper에 등록시키고 깨운다.
+ */
 static void wake_oom_reaper(struct task_struct *tsk)
 {
     /* mm is already queued? */
@@ -697,16 +849,29 @@ static inline void wake_oom_reaper(struct task_struct *tsk)
  * tsk->mm has to be non NULL and caller has to guarantee it is stable (either
  * under task_lock or operate on the current).
  */
+/*
+ * IAMROOT, 2022.05.07:
+ * - @task의 flag 및 oom_mm을 설정하고. frozen일경우 wakeup시킨다.
+ */
 static void mark_oom_victim(struct task_struct *tsk)
 {
     struct mm_struct *mm = tsk->mm;
 
     WARN_ON(oom_killer_disabled);
+
+/*
+ * IAMROOT, 2022.05.07:
+ * - 이미 TIF_MEMDIE가 설정되있으면 return.
+ */
     /* OOM killer might race with memcg OOM */
     if (test_and_set_tsk_thread_flag(tsk, TIF_MEMDIE))
         return;
 
     /* oom_mm is bound to the signal struct life time. */
+/*
+ * IAMROOT, 2022.05.07:
+ * - oom_mm == NULL이면 mm으로 교체.
+ */
     if (!cmpxchg(&tsk->signal->oom_mm, NULL, mm)) {
         mmgrab(tsk->signal->oom_mm);
         set_bit(MMF_OOM_VICTIM, &mm->flags);
@@ -782,6 +947,11 @@ bool oom_killer_disable(signed long timeout)
     return true;
 }
 
+/*
+ * IAMROOT, 2022.05.07:
+ * - task가 free memory를 반환할수있는 상태인지 확인한다.
+ *   signal group이 죽고 있거나 task가 죽고있는지 확인한다.
+ */
 static inline bool __task_will_free_mem(struct task_struct *task)
 {
     struct signal_struct *sig = task->signal;
@@ -791,12 +961,24 @@ static inline bool __task_will_free_mem(struct task_struct *task)
      * so the oom killer cannot assume that the process will promptly exit
      * and release memory.
      */
+/*
+ * IAMROOT, 2022.05.07:
+ * - papgo
+ *   코어 덤핑 프로세스는 exit_mm()에서 장기간 sleep할 수 있으므로, oom 킬러는
+ *   프로세스가 즉시 종료되고 메모리를 방출한다고 가정할 수 없다. 
+ * - memory가 늦게 반환되니 false를 반환한다.
+ */
     if (sig->flags & SIGNAL_GROUP_COREDUMP)
         return false;
 
     if (sig->flags & SIGNAL_GROUP_EXIT)
         return true;
 
+/*
+ * IAMROOT, 2022.05.07:
+ * - thread group에 포함이 되지 않았고, 해당 task가 종료중이면 곧 종료중이다.
+ *   return true.
+ */
     if (thread_group_empty(task) && (task->flags & PF_EXITING))
         return true;
 
@@ -810,6 +992,10 @@ static inline bool __task_will_free_mem(struct task_struct *task)
  * Caller has to make sure that task->mm is stable (hold task_lock or
  * it operates on the current).
  */
+/*
+ * IAMROOT, 2022.05.07:
+ * - @task가 죽어가면서 free memrory를 반환할수있는 상태인지 확인한다.
+ */
 static bool task_will_free_mem(struct task_struct *task)
 {
     struct mm_struct *mm = task->mm;
@@ -821,9 +1007,18 @@ static bool task_will_free_mem(struct task_struct *task)
      * exit_oom_victim. oom_reaper could have rescued that but do not rely
      * on that for now. We can consider find_lock_task_mm in future.
      */
+/*
+ * IAMROOT, 2022.05.07:
+ * - exit_mm이나 exit_oom_victim으로 task가 죽고 있는중인지 확인한다.
+ */
     if (!mm)
         return false;
 
+/*
+ * IAMROOT, 2022.05.07:
+ * - task가 종료되고있는데, memory를 반환할수있는 상태인지 확인한다.
+ *   종료되는 task임에도 불구하고 memory를 확보할수 없으면 return false.
+ */
     if (!__task_will_free_mem(task))
         return false;
 
@@ -831,6 +1026,10 @@ static bool task_will_free_mem(struct task_struct *task)
      * This task has already been drained by the oom reaper so there are
      * only small chances it will free some more
      */
+/*
+ * IAMROOT, 2022.05.07:
+ * - mm이 이미 oom중이니 return false.
+ */
     if (test_bit(MMF_OOM_SKIP, &mm->flags))
         return false;
 
@@ -843,6 +1042,12 @@ static bool task_will_free_mem(struct task_struct *task)
      * b) the task is also reapable by the oom reaper.
      */
     rcu_read_lock();
+/*
+ * IAMROOT, 2022.05.07:
+ * - 모든 process를 iterate한다.
+ *   mm을 share 하고, 같은 thread group이 아닌 process를 찾아서
+ *   __task_will_free_mem()으로 확인한다.
+ */
     for_each_process(p) {
         if (!process_shares_mm(p, mm))
             continue;
@@ -890,6 +1095,13 @@ static void __oom_kill_process(struct task_struct *victim, const char *message)
      */
     do_send_sig_info(SIGKILL, SEND_SIG_PRIV, victim, PIDTYPE_TGID);
     mark_oom_victim(victim);
+/*
+ * IAMROOT, 2022.05.07:
+ * - ex)
+ *   Out of memory: Killed process 2446 (gnome-shell) total-vm:5424564kB,
+ *   anon-rss:255676kB, file-rss:100240kB, shmem-rss:38948kB, UID:1000
+ *   pgtables:1496kB oom_score_adj:0
+ */
     pr_err("%s: Killed process %d (%s) total-vm:%lukB, anon-rss:%lukB, file-rss:%lukB, shmem-rss:%lukB, UID:%u pgtables:%lukB oom_score_adj:%hd\n",
         message, task_pid_nr(victim), victim->comm, K(mm->total_vm),
         K(get_mm_counter(mm, MM_ANONPAGES)),
@@ -1002,8 +1214,17 @@ static void oom_kill_process(struct oom_control *oc, const char *message)
 /*
  * Determines whether the kernel must panic because of the panic_on_oom sysctl.
  */
+/*
+ * IAMROOT, 2022.05.07:
+ * - sysctl_panic_on_oom과 oc->constraint에 따라 panic을 일으킨다.
+ */
 static void check_panic_on_oom(struct oom_control *oc)
 {
+/*
+ * IAMROOT, 2022.05.07:
+ * - sysctl_panic_on_oom == 0
+ *   oom만 동작시킨다.
+ */
     if (likely(!sysctl_panic_on_oom))
         return;
     if (sysctl_panic_on_oom != 2) {
@@ -1012,9 +1233,20 @@ static void check_panic_on_oom(struct oom_control *oc)
          * does not panic for cpuset, mempolicy, or memcg allocation
          * failures.
          */
+/*
+ * IAMROOT, 2022.05.07:
+ * - sysctl_panic_on_oom == 1이면 mempolicy/cpusets, memcg인 상황에서는 oom에만
+ *   동작시킨다.
+ */
         if (oc->constraint != CONSTRAINT_NONE)
             return;
     }
+
+/*
+ * IAMROOT, 2022.05.07:
+ * - sysctl_panic_on_oom == 2이거나 CONSTRAINT_NONE인 경우 무조건 panic을 일으킨다.
+ * - 사용자 요청이면 panic을 안한다.
+ */
     /* Do not panic for oom kills triggered by sysrq */
     if (is_sysrq_oom(oc))
         return;
@@ -1054,6 +1286,11 @@ bool out_of_memory(struct oom_control *oc)
         return false;
 
     if (!is_memcg_oom(oc)) {
+/*
+ * IAMROOT, 2022.05.07:
+ * - oom_notify_list에 등록되있는 함수들을 호출한다. 해당 함수에서 free된게
+ *   있다면 return true.
+ */
         blocking_notifier_call_chain(&oom_notify_list, 0, &freed);
         if (freed > 0)
             /* Got some memory back in the last second. */
@@ -1065,6 +1302,11 @@ bool out_of_memory(struct oom_control *oc)
      * select it.  The goal is to allow it to allocate so that it may
      * quickly exit and free its memory.
      */
+/*
+ * IAMROOT, 2022.05.07:
+ * - current가 종료중이고 memory를 반환할수있는 상태라면 oom관련 설정, frozen상태일
+ *   경우 wakepup, oom_reaper에 등록 및 oom_reaper wakepup등을 수행하고 return true.
+ */
     if (task_will_free_mem(current)) {
         mark_oom_victim(current);
         wake_oom_reaper(current);
@@ -1078,6 +1320,13 @@ bool out_of_memory(struct oom_control *oc)
      * ___GFP_DIRECT_RECLAIM to get here. But mem_cgroup_oom() has to
      * invoke the OOM killer even if it is a GFP_NOFS allocation.
      */
+/*
+ * IAMROOT, 2022.05.07:
+ * - OOM 킬러는 IO가 없는 회수를 보상하지 않습니다.
+ *   pagefault_out_of_memory가 gfp 컨텍스트를 손실했기 때문에 0 마스크를 제외해야
+ *   합니다. 다른 모든 사용자는 __GFP_DIRECT_RECLAIM을 가지고 있어야 합니다.
+ *   그러나 mem_cgroup_oom()은 GFP_NOFS 할당인 경우에도 OOM 킬러를 호출해야 합니다. 
+ */
     if (oc->gfp_mask && !(oc->gfp_mask & __GFP_FS) && !is_memcg_oom(oc))
         return true;
 
@@ -1090,10 +1339,21 @@ bool out_of_memory(struct oom_control *oc)
         oc->nodemask = NULL;
     check_panic_on_oom(oc);
 
+/*
+ * IAMROOT, 2022.05.07:
+ * - check_panic_on_oom()에서 panic이 안일어났다면 oom을 준비한다.
+ * - sysctl_oom_kill_allocating_task이 설정되있고, 아직 종료가 안됬으며, 죽일수가없는
+ *   task이며 
+ */
+
     if (!is_memcg_oom(oc) && sysctl_oom_kill_allocating_task &&
         current->mm && !oom_unkillable_task(current) &&
         oom_cpuset_eligible(current, oc) &&
         current->signal->oom_score_adj != OOM_SCORE_ADJ_MIN) {
+/*
+ * IAMROOT, 2022.05.07:
+ * - oom_score_adj가 OOM_SCORE_ADJ_MIN이 아닌경우 현재 task를 oom한다.
+ */
         get_task_struct(current);
         oc->chosen = current;
         oom_kill_process(oc, "Out of memory (oom_kill_allocating_task)");
@@ -1103,6 +1363,10 @@ bool out_of_memory(struct oom_control *oc)
     select_bad_process(oc);
     /* Found nothing?!?! */
     if (!oc->chosen) {
+/*
+ * IAMROOT, 2022.05.07:
+ * - oom 대상을 못찾았다. deadlock
+ */
         dump_header(oc, NULL);
         pr_warn("Out of memory and no killable processes...\n");
         /*
@@ -1113,6 +1377,11 @@ bool out_of_memory(struct oom_control *oc)
         if (!is_sysrq_oom(oc) && !is_memcg_oom(oc))
             panic("System is deadlocked on memory\n");
     }
+
+/*
+ * IAMROOT, 2022.05.07:
+ * - chosen != -1UL. abort가 아니라는뜻. 즉 oom 대상 process가 찾아졌다.
+ */
     if (oc->chosen && oc->chosen != (void *)-1UL)
         oom_kill_process(oc, !is_memcg_oom(oc) ? "Out of memory" :
                  "Memory cgroup out of memory");
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 62315b3b0b88..639f3388bf23 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -279,6 +279,11 @@ void pm_restrict_gfp_mask(void)
     gfp_allowed_mask &= ~(__GFP_IO | __GFP_FS);
 }
 
+/*
+ * IAMROOT, 2022.05.07:
+ * - 절전모드면 gfp_allowed_mask에서 __GFP_IO, __GFP_FS가 제한된다.
+ *   즉 reclaim에 대해서 disk 이용 가능 여부를 확인한다.
+ */
 bool pm_suspended_storage(void)
 {
     if ((gfp_allowed_mask & (__GFP_IO | __GFP_FS)) == (__GFP_IO | __GFP_FS))
@@ -850,6 +855,10 @@ static inline unsigned int order_to_pindex(int migratetype, int order)
     return (MIGRATE_PCPTYPES * base) + migratetype;
 }
 
+/*
+ * IAMROOT, 2022.05.07:
+ * - pindex = order * MIGRATE_PCPTYPES + migratetype
+ */
 static inline int pindex_to_order(unsigned int pindex)
 {
     int order = pindex / MIGRATE_PCPTYPES;
@@ -1461,6 +1470,10 @@ static const char *page_bad_reason(struct page *page, unsigned long flags)
     return bad_reason;
 }
 
+/*
+ * IAMROOT, 2022.05.07:
+ * - bad page인지 확인.
+ */
 static void check_free_page_bad(struct page *page)
 {
     bad_page(page,
@@ -1685,12 +1698,20 @@ static bool free_pcp_prepare(struct page *page, unsigned int order)
         return free_pages_prepare(page, order, false, FPI_NONE);
 }
 
+/*
+ * IAMROOT, 2022.05.07:
+ * - bad page인지 확인.
+ */
 static bool bulkfree_pcp_prepare(struct page *page)
 {
     return check_free_page(page);
 }
 #endif /* CONFIG_DEBUG_VM */
 
+/*
+ * IAMROOT, 2022.05.07:
+ * - @page의 buddy page를 prefetch한다.
+ */
 static inline void prefetch_buddy(struct page *page)
 {
     unsigned long pfn = page_to_pfn(page);
@@ -1711,6 +1732,10 @@ static inline void prefetch_buddy(struct page *page)
  * And clear the zone's pages_scanned counter, to hold off the "all pages are
  * pinned" detection logic.
  */
+/*
+ * IAMROOT, 2022.05.07:
+ * - @zone에 따라 pcp가 있는 cpu들의 pcp를 @count만큼 buddy로 보낸다.
+ */
 static void free_pcppages_bulk(struct zone *zone, int count,
                     struct per_cpu_pages *pcp)
 {
@@ -1738,6 +1763,10 @@ static void free_pcppages_bulk(struct zone *zone, int count,
          * off fuller lists instead of spinning excessively around empty
          * lists
          */
+/*
+ * IAMROOT, 2022.05.07:
+ * - 비어있지 않은 pcp list를 찾는다.
+ */
         do {
             batch_free++;
             if (++pindex == NR_PCP_LISTS)
@@ -1758,6 +1787,10 @@ static void free_pcppages_bulk(struct zone *zone, int count,
             nr_freed += 1 << order;
             count -= 1 << order;
 
+/*
+ * IAMROOT, 2022.05.07:
+ * - bad page인지 확인.
+ */
             if (bulkfree_pcp_prepare(page))
                 continue;
 
@@ -1765,6 +1798,10 @@ static void free_pcppages_bulk(struct zone *zone, int count,
             page->index <<= NR_PCP_ORDER_WIDTH;
             page->index |= order;
 
+/*
+ * IAMROOT, 2022.05.07:
+ * - pcp에서 빼서 index를 encode후 local list에 넣어놓는다.
+ */
             list_add_tail(&page->lru, &head);
 
             /*
@@ -1776,6 +1813,10 @@ static void free_pcppages_bulk(struct zone *zone, int count,
              * avoid excessive prefetching due to large count, only
              * prefetch buddy for the first pcp->batch nr of pages.
              */
+/*
+ * IAMROOT, 2022.05.07:
+ * - buddy를 prefetch_nr만큼 prefetch한다.
+ */
             if (prefetch_nr) {
                 prefetch_buddy(page);
                 prefetch_nr--;
@@ -1795,6 +1836,10 @@ static void free_pcppages_bulk(struct zone *zone, int count,
      * Use safe version since after __free_one_page(),
      * page->lru.next will not point to original list.
      */
+/*
+ * IAMROOT, 2022.05.07:
+ * - local list에 모아놓은 page를 buddy로 돌려보낸다.
+ */
     list_for_each_entry_safe(page, tmp, &head, lru) {
         int mt = get_pcppage_migratetype(page);
 
@@ -3516,6 +3561,11 @@ static void reserve_highatomic_pageblock(struct page *page, struct zone *zone,
  * If @force is true, try to unreserve a pageblock even though highatomic
  * pageblock is exhausted.
  */
+/*
+ * IAMROOT, 2022.05.07:
+ * - force == true일때는 1block이상, 아니면 2block이상 highatomic을 가진 zone
+ *   을 찾아 존재하면 @ac type으로 변경후 가져온다.
+ */
 static bool unreserve_highatomic_pageblock(const struct alloc_context *ac,
                         bool force)
 {
@@ -3533,6 +3583,10 @@ static bool unreserve_highatomic_pageblock(const struct alloc_context *ac,
          * Preserve at least one pageblock unless memory pressure
          * is really high.
          */
+/*
+ * IAMROOT, 2022.05.07:
+ * - 1block 초과로 reseve된 highatomic을 찾는다.
+ */
         if (!force && zone->nr_reserved_highatomic <=
                     pageblock_nr_pages)
             continue;
@@ -3552,6 +3606,10 @@ static bool unreserve_highatomic_pageblock(const struct alloc_context *ac,
              * from highatomic to ac->migratetype. So we should
              * adjust the count once.
              */
+/*
+ * IAMROOT, 2022.05.07:
+ * - fallback으로 가져올수도있어서 가져와고서도 한번 확인해본다.
+ */
             if (is_migrate_highatomic_page(page)) {
                 /*
                  * It should never happen but changes to
@@ -3574,6 +3632,10 @@ static bool unreserve_highatomic_pageblock(const struct alloc_context *ac,
              * of pageblocks that cannot be completely freed
              * may increase.
              */
+/*
+ * IAMROOT, 2022.05.07:
+ * - 요청 type으로 변경.
+ */
             set_pageblock_migratetype(page, ac->migratetype);
             ret = move_freepages_block(zone, page, ac->migratetype,
                                     NULL);
@@ -3872,7 +3934,7 @@ void drain_zone_pages(struct zone *zone, struct per_cpu_pages *pcp)
  */
 /*
  * IAMROOT, 2022.04.09:
- * - pcplist를 drain시킨다.
+ * - pcplist를 bulk drain시킨다.(pcp를 buddy로 돌려보낸다.)
  */
 static void drain_pages_zone(unsigned int cpu, struct zone *zone)
 {
@@ -3957,6 +4019,12 @@ static void drain_local_pages_wq(struct work_struct *work)
  * that need the guarantee that every CPU has drained can disable the
  * optimizing racy check.
  */
+/*
+ * IAMROOT, 2022.05.07:
+ * @force_all_cpus true면 무조건 drain 시도.
+ * @zone NULL이면 모든 zone, 아니면 @zone에 대해서 수행한다.
+ * - 모든 cpu에 대하여 @zone 및 @force_all_cpus에 따라 pcp를 bulk drain한다.
+ */
 static void __drain_all_pages(struct zone *zone, bool force_all_cpus)
 {
     int cpu;
@@ -3991,6 +4059,19 @@ static void __drain_all_pages(struct zone *zone, bool force_all_cpus)
      * cpu to drain that CPU pcps and on_each_cpu_mask
      * disables preemption as part of its processing
      */
+/*
+ * IAMROOT, 2022.05.07:
+ * - online cpu만큼 iterate를 하며 pcp에 page가 있는 cpu를 cpus_with_pcps cpumask에
+ *   기록한다.
+ * 1. force_all_cpus = true
+ *  모든 cpu에 대해서 set.
+ *
+ * 2. zone != NULL
+ *  해당 zone에 대한 pcp를 가진 모든 cpu.
+ *
+ * 3. zone == NULL
+ *  cpu마다 모든 zone의 범위 에대해서 pcp가 있는 cpu.
+ */
     for_each_online_cpu(cpu) {
         struct per_cpu_pages *pcp;
         struct zone *z;
@@ -4022,6 +4103,11 @@ static void __drain_all_pages(struct zone *zone, bool force_all_cpus)
             cpumask_clear_cpu(cpu, &cpus_with_pcps);
     }
 
+/*
+ * IAMROOT, 2022.05.07:
+ * - cpus_with_pcps에 기록된 cpu를 iterate하며 worker thread를 동작시켜
+ *   pcp를 drain한다.
+ */
     for_each_cpu(cpu, &cpus_with_pcps) {
         struct pcpu_drain *drain = per_cpu_ptr(&pcpu_drain, cpu);
 
@@ -4042,6 +4128,10 @@ static void __drain_all_pages(struct zone *zone, bool force_all_cpus)
  *
  * Note that this can be extremely slow as the draining happens in a workqueue.
  */
+/*
+ * IAMROOT, 2022.05.07:
+ * - @zone에 대해여 pcp drain을 시도한다.
+ */
 void drain_all_pages(struct zone *zone)
 {
     __drain_all_pages(zone, false);
@@ -5432,6 +5522,10 @@ __alloc_pages_may_oom(gfp_t gfp_mask, unsigned int order,
      * Acquire the oom lock.  If that fails, somebody else is
      * making progress for us.
      */
+/*
+ * IAMROOT, 2022.05.07:
+ * - cpu들이 동시에 oom처리하고잇는 경우를 확인한다.
+ */
     if (!mutex_trylock(&oom_lock)) {
         *did_some_progress = 1;
         schedule_timeout_uninterruptible(1);
@@ -5445,6 +5539,10 @@ __alloc_pages_may_oom(gfp_t gfp_mask, unsigned int order,
      * attempt shall not depend on __GFP_DIRECT_RECLAIM && !__GFP_NORETRY
      * allocation which will never fail due to oom_lock already held.
      */
+/*
+ * IAMROOT, 2022.05.07:
+ * - high watermark를 기준으로 할당을 시도한다.
+ */
     page = get_page_from_freelist((gfp_mask | __GFP_HARDWALL) &
                       ~__GFP_DIRECT_RECLAIM, order,
                       ALLOC_WMARK_HIGH|ALLOC_CPUSET, ac);
@@ -5452,6 +5550,10 @@ __alloc_pages_may_oom(gfp_t gfp_mask, unsigned int order,
         goto out;
 
     /* Coredumps can quickly deplete all memory reserves */
+/*
+ * IAMROOT, 2022.05.07:
+ * - core dump 중이면 out. 현재 task가 죽고 있다는것이다.
+ */
     if (current->flags & PF_DUMPCORE)
         goto out;
     /* The OOM killer will not help higher order allocs */
@@ -5465,9 +5567,17 @@ __alloc_pages_may_oom(gfp_t gfp_mask, unsigned int order,
      *
      * The OOM killer may not free memory on a specific node.
      */
+/*
+ * IAMROOT, 2022.05.07:
+ * - 현재 노드만 특정을 하거나 retry may fail이 존재하면 out.
+ */
     if (gfp_mask & (__GFP_RETRY_MAYFAIL | __GFP_THISNODE))
         goto out;
     /* The OOM killer does not needlessly kill tasks for lowmem */
+/*
+ * IAMROOT, 2022.05.07:
+ * - DMA 요청이면 out.
+ */
     if (ac->highest_zoneidx < ZONE_NORMAL)
         goto out;
     if (pm_suspended_storage())
@@ -5787,6 +5897,11 @@ EXPORT_SYMBOL_GPL(fs_reclaim_release);
 #endif
 
 /* Perform direct synchronous page reclaim */
+/*
+ * IAMROOT, 2022.05.07:
+ * @return reclaim 성공 page 개수
+ * - reclaim을 수행한다.
+ */
 static unsigned long
 __perform_reclaim(gfp_t gfp_mask, unsigned int order,
                     const struct alloc_context *ac)
@@ -5819,6 +5934,11 @@ __perform_reclaim(gfp_t gfp_mask, unsigned int order,
 }
 
 /* The really slow allocator path where we enter direct reclaim */
+/*
+ * IAMROOT, 2022.05.07:
+ * - reclaim을 실행한다. reclaim후에 buddy에서 할당이 실패했다면
+ *   1개 초과를 가진 highatomic에 대한 unreserve시도 및 pcp drain까지 수행한다.
+ */
 static inline struct page *
 __alloc_pages_direct_reclaim(gfp_t gfp_mask, unsigned int order,
         unsigned int alloc_flags, const struct alloc_context *ac,
@@ -5831,6 +5951,10 @@ __alloc_pages_direct_reclaim(gfp_t gfp_mask, unsigned int order,
     if (unlikely(!(*did_some_progress)))
         return NULL;
 
+/*
+ * IAMROOT, 2022.05.07:
+ * - 회수를 했으니 buddy에서 가져와본다.
+ */
 retry:
     page = get_page_from_freelist(gfp_mask, order, alloc_flags, ac);
 
@@ -5839,8 +5963,16 @@ __alloc_pages_direct_reclaim(gfp_t gfp_mask, unsigned int order,
      * pages are pinned on the per-cpu lists or in high alloc reserves.
      * Shrink them and try again
      */
+/*
+ * IAMROOT, 2022.05.07:
+ * - reclaim했는데도 페이지 할당이 실패한경우 pcpu cache까지 한번 지워보고 시도한다.
+ */
     if (!page && !drained) {
         unreserve_highatomic_pageblock(ac, false);
+/*
+ * IAMROOT, 2022.05.07:
+ * - 모든 zone에 대해서 pcp drain을 시도한다.
+ */
         drain_all_pages(NULL);
         drained = true;
         goto retry;
@@ -6036,6 +6168,14 @@ bool gfp_pfmemalloc_allowed(gfp_t gfp_mask)
  *
  * Returns true if a retry is viable or false to enter the oom path.
  */
+/*
+ * IAMROOT, 2022.05.07:
+ * @did_some_progress 이전 reclaim 성공여부
+ * - no_progress_loops를 갱신한다. 만약 한계를 초과하면 마지막 highatomic까지
+ *   사용한다.
+ *   그게 아니라면 min watermark와 비교를 하여 reclaim 가능여부를 결정한다.
+ *   (미래 회수 가능한 memory까지 고려)
+ */
 static inline bool
 should_reclaim_retry(gfp_t gfp_mask, unsigned order,
              struct alloc_context *ac, int alloc_flags,
@@ -6050,6 +6190,11 @@ should_reclaim_retry(gfp_t gfp_mask, unsigned order,
      * their order will become available due to high fragmentation so
      * always increment the no progress counter for them
      */
+/*
+ * IAMROOT, 2022.05.07:
+ * - 직전 reclaim에서 성공을 했고 order가 costly_order이내라면 no_progress_loops를
+ *   초기화한다.
+ */
     if (did_some_progress && order <= PAGE_ALLOC_COSTLY_ORDER)
         *no_progress_loops = 0;
     else
@@ -6059,6 +6204,10 @@ should_reclaim_retry(gfp_t gfp_mask, unsigned order,
      * Make sure we converge to OOM if we cannot make any progress
      * several times in the row.
      */
+/*
+ * IAMROOT, 2022.05.07:
+ * - no_progress_loops가 한계를 초과하면 마지막 남은 highatomic까지 사용해버린다.
+ */
     if (*no_progress_loops > MAX_RECLAIM_RETRIES) {
         /* Before OOM, exhaust highatomic_reserve */
         return unreserve_highatomic_pageblock(ac, true);
@@ -6084,6 +6233,10 @@ should_reclaim_retry(gfp_t gfp_mask, unsigned order,
          * Would the allocation succeed if we reclaimed all
          * reclaimable pages?
          */
+/*
+ * IAMROOT, 2022.05.07:
+ * - min watermark에 대해서 available과 비교한다.
+ */
         wmark = __zone_watermark_ok(zone, order, min_wmark,
                 ac->highest_zoneidx, alloc_flags, available);
         trace_reclaim_retry_zone(z, order, reclaimable,
@@ -6095,6 +6248,11 @@ should_reclaim_retry(gfp_t gfp_mask, unsigned order,
              * an IO to complete to slow down the reclaim and
              * prevent from pre mature OOM
              */
+/*
+ * IAMROOT, 2022.05.07:
+ * - 이전 reclaim이 실패를 했어도 write중인 page가 reclaimable의 2배이상이면
+ *   0.1 sec만 쉬고 true return.
+ */
             if (!did_some_progress) {
                 unsigned long write_pending;
 
@@ -6120,6 +6278,10 @@ should_reclaim_retry(gfp_t gfp_mask, unsigned order,
      * looping without ever sleeping. Therefore we have to do a short sleep
      * here rather than calling cond_resched().
      */
+/*
+ * IAMROOT, 2022.05.07:
+ * - current가 worker thread인 경우 interrupt무관 1 sec sleep
+ */
     if (current->flags & PF_WQ_WORKER)
         schedule_timeout_uninterruptible(1);
     else
@@ -6408,9 +6570,16 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,
     if (page)
         goto got_pg;
 
+/*
+ * IAMROOT, 2022.05.07:
+ * - 여기까지 왔다는건. reclaim을 시도해도 실패하고, highatomic 여유분 사용 및
+ *   pcp drain을 했는데도 실패했다는것이다.
+ */
+
     /* Try direct compaction and then allocating */
 /*
  * IAMROOT, 2022.04.09:
+ * - compact를 한번 실행해본다.
  * - retry등을 할때는 compact_priority에 따라서 수행한다.
  */
     page = __alloc_pages_direct_compact(gfp_mask, order, alloc_flags, ac,
@@ -6418,6 +6587,10 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,
     if (page)
         goto got_pg;
 
+/*
+ * IAMROOT, 2022.05.07:
+ * - retry 금지를 확인한다.
+ */
     /* Do not loop if specifically requested */
     if (gfp_mask & __GFP_NORETRY)
         goto nopage;
@@ -6426,9 +6599,17 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,
      * Do not retry costly high order allocations unless they are
      * __GFP_RETRY_MAYFAIL
      */
+/*
+ * IAMROOT, 2022.05.07:
+ * - costly_order같은 경우엔 retry가 있어도 실패로 간주한다.
+ */
     if (costly_order && !(gfp_mask & __GFP_RETRY_MAYFAIL))
         goto nopage;
 
+/*
+ * IAMROOT, 2022.05.07:
+ * - no_progress_loops를 갱신하고 reclaim 재시도 여부를 확인한다.
+ */
     if (should_reclaim_retry(gfp_mask, order, ac, alloc_flags,
                  did_some_progress > 0, &no_progress_loops))
         goto retry;
@@ -6439,13 +6620,20 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,
      * implementation of the compaction depends on the sufficient amount
      * of free memory (see __compaction_suitable)
      */
+/*
+ * IAMROOT, 2022.05.07:
+ * - compact retry 여부 확인을 하며 retries, priority--를 갱신한다.
+ */
     if (did_some_progress > 0 &&
             should_compact_retry(ac, order, alloc_flags,
                 compact_result, &compact_priority,
                 &compaction_retries))
         goto retry;
 
-
+/*
+ * IAMROOT, 2022.05.07:
+ * - 현재 task에 사용 가능 noide가 변경되었는지 확인한다. 변경되었으면 재시도한다.
+ */
     /* Deal with possible cpuset update races before we start OOM killing */
     if (check_retry_cpuset(cpuset_mems_cookie, ac))
         goto retry_cpuset;
diff --git a/mm/vmpressure.c b/mm/vmpressure.c
index 16a2700590cc..899654d1cc83 100644
--- a/mm/vmpressure.c
+++ b/mm/vmpressure.c
@@ -328,6 +328,8 @@ static void vmpressure_work_fn(struct work_struct *work)
  * - 누적 scanned, reclaimed 에 따라 vmpressure를 monitoring하고있는 task들한테
  *   signal을 보낸다.
  * - 누적 scanned가 vmpressure_win보다 작다면 누적만 시킨다.
+ * - android등에서 이 기능을 사용한다.(vmpressure, psi)
+ *   app측에서 memory 상태등을 확인해서 안쓰는 app등을 죽이는 용도등
  */
 void vmpressure(gfp_t gfp, struct mem_cgroup *memcg, bool tree,
         unsigned long scanned, unsigned long reclaimed)
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 7ff3b61d2764..f2b7d63343ba 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -940,6 +940,10 @@ static unsigned long shrink_slab_memcg(gfp_t gfp_mask, int nid,
  *
  * Returns the number of reclaimed slab objects.
  */
+/*
+ * IAMROOT, 2022.05.07:
+ * - TODO
+ */
 static unsigned long shrink_slab(gfp_t gfp_mask, int nid,
                  struct mem_cgroup *memcg,
                  int priority)
@@ -2769,6 +2773,11 @@ static int current_may_throttle(void)
  * shrink_inactive_list() is a helper for shrink_node().  It returns the number
  * of reclaimed pages
  */
+
+/*
+ * IAMROOT, 2022.05.07:
+ * - reclaim을 수행한다.
+ */
 static unsigned long
 shrink_inactive_list(unsigned long nr_to_scan, struct lruvec *lruvec,
              struct scan_control *sc, enum lru_list lru)
@@ -2856,6 +2865,18 @@ shrink_inactive_list(unsigned long nr_to_scan, struct lruvec *lruvec,
      * the flushers simply cannot keep up with the allocation
      * rate. Nudge the flusher threads in case they are asleep.
      */
+/*
+ * IAMROOT, 2022.05.07:
+ * - papago
+ *   IO를 위해 대기열에 있지 않은 더러운 페이지가 검색되면 플러셔가 작업을 수행하지
+ *   않고 있음을 의미합니다. 메모리 압력이 더티 한계를 위반하고 더티 데이터가
+ *   만료되기 전에 더티 페이지를 LRU의 끝으로 밀어넣을 때 발생할 수 있습니다.
+ *   또한 쓰기가 아닌 모든 클린 캐시를 회수하는 메모리 압력으로 인해 dirty page의
+ *   비율이 증가할 때 발생할 수 있습니다. 그리고 어떤 경우에는, 플러셔가 단순히
+ *   할당 비율을 따라가지 못한다. 잠들어 있을 때를 대비해서 밀어라
+ * - unqueue
+ *   dirty && !writeback.
+ */
     if (stat.nr_unqueued_dirty == nr_taken)
         wakeup_flusher_threads(WB_REASON_VMSCAN);
 
@@ -3129,6 +3150,26 @@ static unsigned long shrink_list(enum lru_list lru, unsigned long nr_to_scan,
  *    1TB     101        10GB
  *   10TB     320        32GB
  */
+
+/*
+ * IAMROOT, 2022.05.07:
+ * - papago
+ * inactive anon list는 VM이 너무 많은 작업을 수행할 필요가 없을 정도로 작아야
+ * 합니다.
+ *
+ * 비활성 파일 목록은 대부분의 메모리를 검사 방지 활성 목록에 설정된 workingsets에
+ * 남겨둘 수 있을 만큼 작아야 하지만, 전체 읽기 미리 실행된 창이 스레싱되지 않도록
+ * 충분히 커야 합니다.
+ *
+ * 또한 두 비활성 목록은 각 비활성 페이지가 회수되기 전에 다시 참조될 수 있을
+ * 정도로 충분히 커야 합니다.
+ * 
+ * 이 작업이 실패하여 재장애가 관찰되면 비활성 목록이 증가합니다.
+ *
+ * inactive_ratio는 이 LRU의 ACTIVE 페이지와 ICTIVE 페이지의 목표 비율이며,
+ * 페이지아웃 코드에 의해 유지된다. 3의 inactive_ratio는 3을 의미한다.
+ * 페이지의 1 또는 25%가 비활성 목록에 보관됩니다.
+ */
 static bool inactive_is_low(struct lruvec *lruvec, enum lru_list inactive_lru)
 {
     enum lru_list active_lru = inactive_lru + LRU_ACTIVE;
@@ -3140,11 +3181,27 @@ static bool inactive_is_low(struct lruvec *lruvec, enum lru_list inactive_lru)
     active = lruvec_page_state(lruvec, NR_LRU_BASE + active_lru);
 
     gb = (inactive + active) >> (30 - PAGE_SHIFT);
+
+/*
+ * IAMROOT, 2022.05.07:
+ * - int_sqrt(10 * gb) = root(10 * gb)
+ */
     if (gb)
         inactive_ratio = int_sqrt(10 * gb);
     else
         inactive_ratio = 1;
 
+/*
+ * IAMROOT, 2022.05.07:
+ * - 1GB 미만으로 차이나면 inactive < active
+ * - 1GB 이상 차이나면 inactive * root(10 * gb) < active
+ *   ex) gb 
+ *       1    inactive : active = 1 : 3
+ *       2    inactive : active = 1 : 4
+ *       3    inactive : active = 1 : 5
+ *       10   inactive : active = 1 : 10
+ *       16   inactive : active = 1 : 12
+ */
     return inactive * inactive_ratio < active;
 }
 
@@ -3453,6 +3510,11 @@ static void get_scan_count(struct lruvec *lruvec, struct scan_control *sc,
  * Anonymous LRU management is a waste if there is
  * ultimately no way to reclaim the memory.
  */
+/*
+ * IAMROOT, 2022.05.07:
+ * - @pgdat에 대해서 anon page에 대해 page가 swap할 공간이 있거나
+ *   demote가 가능한지 알아온다.
+ */
 static bool can_age_anon_pages(struct pglist_data *pgdat,
                    struct scan_control *sc)
 {
@@ -3464,6 +3526,10 @@ static bool can_age_anon_pages(struct pglist_data *pgdat,
     return can_demote(pgdat->node_id, sc);
 }
 
+/*
+ * IAMROOT, 2022.05.07:
+ * - @lruvec에 대해서 reclaim을 수행한다.
+ */
 static void shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc)
 {
     unsigned long nr[NR_LRU_LISTS];
@@ -3578,6 +3644,12 @@ static void shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc)
          * Recalculate the other LRU scan count based on its original
          * scan target and the percentage scanning already complete
          */
+
+/*
+ * IAMROOT, 2022.05.07:
+ * - 위에서 정해진 lru의 반대(file <=> anon)의 nr을 산정한다. 최소 lru를 기준으로
+ *   반대측의 lru와 비율을 조정한다.
+ */
         lru = (lru == LRU_FILE) ? LRU_BASE : LRU_FILE;
         nr_scanned = targets[lru] - nr[lru];
         nr[lru] = targets[lru] * (100 - percentage) / 100;
@@ -3597,6 +3669,12 @@ static void shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc)
      * Even if we did not try to evict anon pages at all, we want to
      * rebalance the anon lru active/inactive ratio.
      */
+/*
+ * IAMROOT, 2022.05.07:
+ * - anon page에 대해서 inactive가 active에 비해 비율이 적으면 deactive 시도를한다.
+ *   SWAP_CLUSTER_MAX개씩만 reclaim을 하기때문에 anon page에 대해서만 조금더
+ *   신경 쓰는 개념.
+ */
     if (can_age_anon_pages(lruvec_pgdat(lruvec), sc) &&
         inactive_is_low(lruvec, LRU_INACTIVE_ANON))
         shrink_active_list(SWAP_CLUSTER_MAX, lruvec,
@@ -3604,6 +3682,13 @@ static void shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc)
 }
 
 /* Use reclaim/compaction for costly allocs or under memory pressure */
+
+/*
+ * IAMROOT, 2022.05.07:
+ * - @sc의 order와 priority에 대해서 reclaim중 compaction을 할지에 대해 정한다.
+ * - compaction은 order가 1이상이며 order가 costly_order보다 크거나 priority가 낮을때
+ *   (4번째 시도 이상) true로 return한다.
+ */
 static bool in_reclaim_compaction(struct scan_control *sc)
 {
     if (IS_ENABLED(CONFIG_COMPACTION) && sc->order &&
@@ -3621,6 +3706,11 @@ static bool in_reclaim_compaction(struct scan_control *sc)
  * calls try_to_compact_pages() that it will have enough free pages to succeed.
  * It will give up earlier than that if there is difficulty reclaiming pages.
  */
+/*
+ * IAMROOT, 2022.05.07:
+ * - @sc에 대해서 reclaim을 더 해야되는건지를 결정한다.
+ *   (모든 zone에 대해서 compaction을 못하는 상황에서만 reclaim 수행.)
+ */
 static inline bool should_continue_reclaim(struct pglist_data *pgdat,
                     unsigned long nr_reclaimed,
                     struct scan_control *sc)
@@ -3643,6 +3733,10 @@ static inline bool should_continue_reclaim(struct pglist_data *pgdat,
      * scan, but that approximation was wrong, and there were corner cases
      * where always a non-zero amount of pages were scanned.
      */
+/*
+ * IAMROOT, 2022.05.07:
+ * - 직전 reclaim에서 성공한게 하나도 없으면 false
+ */
     if (!nr_reclaimed)
         return false;
 
@@ -3662,6 +3756,10 @@ static inline bool should_continue_reclaim(struct pglist_data *pgdat,
         }
     }
 
+/*
+ * IAMROOT, 2022.05.07:
+ * - 모든 zone이 COMPACT_SKIPPED이면 진입.
+ */
     /*
      * If we have not reclaimed enough pages for compaction and the
      * inactive lists are large enough, continue reclaiming
@@ -3671,9 +3769,17 @@ static inline bool should_continue_reclaim(struct pglist_data *pgdat,
     if (can_reclaim_anon_pages(NULL, pgdat->node_id, sc))
         inactive_lru_pages += node_page_state(pgdat, NR_INACTIVE_ANON);
 
+/*
+ * IAMROOT, 2022.05.07:
+ * inactive file + swap가능한 anon > pages_for_compaction
+ */
     return inactive_lru_pages > pages_for_compaction;
 }
 
+/*
+ * IAMROOT, 2022.05.07:
+ * - @sc->target_mem_cgroup의 @pgdat의 memcg들에 대해 reclaim을 수행한다.
+ */
 static void shrink_node_memcgs(pg_data_t *pgdat, struct scan_control *sc)
 {
     struct mem_cgroup *target_memcg = sc->target_mem_cgroup;
@@ -3731,6 +3837,10 @@ static void shrink_node_memcgs(pg_data_t *pgdat, struct scan_control *sc)
     } while ((memcg = mem_cgroup_iter(target_memcg, memcg, NULL)));
 }
 
+/*
+ * IAMROOT, 2022.05.07:
+ * - @pgdat에 대해 reclaim을 수행한다.
+ */
 static void shrink_node(pg_data_t *pgdat, struct scan_control *sc)
 {
     struct reclaim_state *reclaim_state = current->reclaim_state;
@@ -3770,6 +3880,14 @@ static void shrink_node(pg_data_t *pgdat, struct scan_control *sc)
 
         refaults = lruvec_page_state(target_lruvec,
                 WORKINGSET_ACTIVATE_ANON);
+
+/*
+ * IAMROOT, 2022.05.07:
+ * - refault != target refaults(snpashot_refaults() 참고)
+ *   새로운 workingset activate가 있는경우 deactive(밀어내기)를 하겠다는것.
+ * - incative_is_low
+ *   inactive가 너무 적은경우 deactive를 하겠다는것.
+ */
         if (refaults != target_lruvec->refaults[0] ||
             inactive_is_low(target_lruvec, LRU_INACTIVE_ANON))
             sc->may_deactivate |= DEACTIVATE_ANON;
@@ -3874,6 +3992,23 @@ static void shrink_node(pg_data_t *pgdat, struct scan_control *sc)
          * immediate reclaim and stall if any are encountered
          * in the nr_immediate check below.
          */
+
+/*
+ * IAMROOT, 2022.05.07:
+ * - papgo
+ *   reclaim가 writeback에서 dirty page를 isolate하는 경우, 오래 지속되는 페이지
+ *   할당률이 페이지 laundering 속도를 초과하고 있음을 의미합니다. 영역 전체에 페이지
+ *   배포로 인해 조정 프로세스에서 전역 제한이 효과적이지 않거나 느린 backing device
+ *   가 많이 사용되고 있습니다. 유일한 옵션은 회수 컨텍스트에서 조정되는 것인데,
+ *   더티 프로세스가 balance_dirty_pages()가 관리하는 것과 동일한 방식으로
+ *   조정된다는 보장이 없기 때문에 이상적이지 않습니다.
+ *
+ *  노드에 PGDAT_WRITHBACK 플래그가 지정되면 kswapd는 즉시 회수 플래그가 지정된
+ *  페이지 아래의 페이지 수를 세고 아래의 nr_immediate 검사에서 해당 페이지 수가
+ *  발견되면 중지합니다.
+ *
+ * - backing device속도가 느리거나 요청등이 많은 이유로 node가 busy인것을 표시한다.
+ */
         if (sc->nr.writeback && sc->nr.writeback == sc->nr.taken)
             set_bit(PGDAT_WRITEBACK, &pgdat->flags);
 
@@ -3887,6 +4022,10 @@ static void shrink_node(pg_data_t *pgdat, struct scan_control *sc)
          * implies that pages are cycling through the LRU
          * faster than they are written so also forcibly stall.
          */
+/*
+ * IAMROOT, 2022.05.07:
+ * - rotate이후에도 node가 너무 바쁘다. 현재 task(kswpad)를 0.1 sec sleep
+ */
         if (sc->nr.immediate)
             congestion_wait(BLK_RW_ASYNC, HZ/10);
     }
@@ -3899,6 +4038,12 @@ static void shrink_node(pg_data_t *pgdat, struct scan_control *sc)
      * Legacy memcg will stall in page writeback so avoid forcibly
      * stalling in wait_iff_congested().
      */
+
+/*
+ * IAMROOT, 2022.05.07:
+ * - reclaimer가 kswpad이거나 writeback_throttling_sane을 지원하는 reclaimer일때
+ *   congested상태(rotate중인 상황)이면 lruvec에다가 LRUVEC_CONGESTED를 set한다.
+ */
     if ((current_is_kswapd() ||
          (cgroup_reclaim(sc) && writeback_throttling_sane(sc))) &&
         sc->nr.dirty && sc->nr.dirty == sc->nr.congested)
@@ -3910,6 +4055,12 @@ static void shrink_node(pg_data_t *pgdat, struct scan_control *sc)
      * starts encountering unqueued dirty pages or cycling through
      * the LRU too quickly.
      */
+
+/*
+ * IAMROOT, 2022.05.07:
+ * - direct reclaim이고, current_may_throttle상태, 절전모드가 아니고, lruvec이
+ *   congested상태라면 0.1초를 쉰다.
+ */
     if (!current_is_kswapd() && current_may_throttle() &&
         !sc->hibernation_mode &&
         test_bit(LRUVEC_CONGESTED, &target_lruvec->flags))
@@ -4000,6 +4151,10 @@ static inline bool compaction_ready(struct zone *zone, struct scan_control *sc)
  * If a zone is deemed to be full of pinned pages then just give it a light
  * scan then give up on it.
  */
+/*
+ * IAMROOT, 2022.05.07:
+ * - @zonelist에 대해서 reclaim을 수행한다.
+ */
 static void shrink_zones(struct zonelist *zonelist, struct scan_control *sc)
 {
     struct zoneref *z;
@@ -4106,6 +4261,11 @@ static void shrink_zones(struct zonelist *zonelist, struct scan_control *sc)
     sc->gfp_mask = orig_mask;
 }
 
+/*
+ * IAMROOT, 2022.05.07:
+ * - @target_memcg, @pgdat에 대한 lruvec에 refault 통계값을 적용한다.
+ *   refault가 변경됬는지에 대한 여부를 검사하는데 사용한다.
+ */
 static void snapshot_refaults(struct mem_cgroup *target_memcg, pg_data_t *pgdat)
 {
     struct lruvec *target_lruvec;
@@ -4134,6 +4294,10 @@ static void snapshot_refaults(struct mem_cgroup *target_memcg, pg_data_t *pgdat)
  * returns:    0, if no pages reclaimed
  *         else, the number of pages reclaimed
  */
+/*
+ * IAMROOT, 2022.05.07:
+ * - @zonelist에 대한 reclaim을 수행한다.
+ */
 static unsigned long do_try_to_free_pages(struct zonelist *zonelist,
                       struct scan_control *sc)
 {
@@ -4211,6 +4375,15 @@ static unsigned long do_try_to_free_pages(struct zonelist *zonelist,
      * entire cgroup subtree up front, we assume the estimates are
      * good, and retry with forcible deactivation if that fails.
      */
+/*
+ * IAMROOT, 2022.05.07:
+ * - papgo
+ *   노드의 메모리 구성을 기반으로 inactive:active 비율을 결정하지만 제한적인
+ *   reclaim_idx 또는 memory.low cgroup 설정은 많은 양의 메모리를 회수할 수 없게
+ *   할 수 있습니다. 둘 다 매우 흔하지 않기 때문에 전체 cgroup 하위 트리에 대해
+ *   비용이 많이 드는 적격성 계산을 수행하는 대신 추정치가 양호하다고 가정하고
+ *   실패하면 강제 비활성화를 통해 재시도한다.
+ */
     if (sc->skipped_deactivate) {
         sc->priority = initial_priority;
         sc->force_deactivate = 1;
@@ -4458,6 +4631,7 @@ static bool throttle_direct_reclaim(gfp_t gfp_mask, struct zonelist *zonelist,
 
 /*
  * IAMROOT, 2022.04.16:
+ * @return reclaim 한 page 개수
  * - direct reclaim을 수행하는데, 만약 memory가 너무 적을 경우 throttle을 수행한다.
  */
 unsigned long try_to_free_pages(struct zonelist *zonelist, int order,
 

XE Login