[커널 18차] 59주차
2022.07.09 22:32
cma 관련 진행중.
git : https://github.com/iamroot18/5.10/commit/e0c9f62f6a6479e641d894de6ac277b94112ab6d
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
index 704ce595542c..22a4c7f2d99d 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -209,6 +209,10 @@ struct cma_device {
refcount_t refcount;
struct list_head id_list;
enum ib_gid_type *default_gid_type;
+/*
+ * IAMROOT, 2022.07.09:
+ * - roce(RDMA용 프로토콜) 관련 정보.
+ */
u8 *default_roce_tos;
};
@@ -5105,6 +5109,10 @@ static struct pernet_operations cma_pernet_operations = {
.size = sizeof(struct cma_pernet),
};
+/*
+ * IAMROOT, 2022.07.09:
+ * - cma 관련 자료구조를 생성한다.
+ */
static int __init cma_init(void)
{
int ret;
@@ -5115,6 +5123,13 @@ static int __init cma_init(void)
* must never be nested under lock so it can find these without having
* to test with bonding.
*/
+/*
+ * IAMROOT, 2022.07.09:
+ * - papago
+ * 본딩이 활성화된 경우에만 발생하는 드문 잠금 순서 종속성이
+ * cma_netdev_callback()에 있습니다. lockdep에 rtnl이 잠금 상태에서 중첩되어서는
+ * 안 된다는 것을 가르쳐 본딩으로 테스트하지 않고도 찾을 수 있도록 합니다.
+ */
if (IS_ENABLED(CONFIG_LOCKDEP)) {
rtnl_lock();
mutex_lock(&lock);
@@ -5122,6 +5137,10 @@ static int __init cma_init(void)
rtnl_unlock();
}
+/*
+ * IAMROOT, 2022.07.09:
+ * - workqueue, net susys, InfiniBand SA module client를 생성한다.
+ */
cma_wq = alloc_ordered_workqueue("rdma_cm", WQ_MEM_RECLAIM);
if (!cma_wq)
return -ENOMEM;
diff --git a/include/linux/cma.h b/include/linux/cma.h
index 53fd8c3cdbd0..b420f279e46c 100644
--- a/include/linux/cma.h
+++ b/include/linux/cma.h
@@ -32,6 +32,12 @@ extern int __init cma_declare_contiguous_nid(phys_addr_t base,
phys_addr_t alignment, unsigned int order_per_bit,
bool fixed, const char *name, struct cma **res_cma,
int nid);
+
+/*
+ * IAMROOT, 2022.07.09:
+ * - cmdline or kernel config에 의한 cma 정보를 memblock reserved 영역을 할당하고
+ * @res_cma(struct cma)에 등록한다.
+ */
static inline int __init cma_declare_contiguous(phys_addr_t base,
phys_addr_t size, phys_addr_t limit,
phys_addr_t alignment, unsigned int order_per_bit,
diff --git a/include/linux/of_reserved_mem.h b/include/linux/of_reserved_mem.h
index 4de2a24cadc9..d5ad084c3c5a 100644
--- a/include/linux/of_reserved_mem.h
+++ b/include/linux/of_reserved_mem.h
@@ -15,6 +15,11 @@ struct reserved_mem {
const struct reserved_mem_ops *ops;
phys_addr_t base;
phys_addr_t size;
+
+/*
+ * IAMROOT, 2022.07.09:
+ * - cma : struct cma
+ */
void *priv;
};
diff --git a/include/rdma/rdma_cm.h b/include/rdma/rdma_cm.h
index d989f030fae0..4b7a7284fae1 100644
--- a/include/rdma/rdma_cm.h
+++ b/include/rdma/rdma_cm.h
@@ -17,6 +17,11 @@
* Upon receiving a device removal event, users must destroy the associated
* RDMA identifier and release all resources allocated with the device.
*/
+
+/*
+ * IAMROOT, 2022.07.09:
+ * - InfiniBand를 동작하기 위한 remote DMA.
+ */
enum rdma_cm_event_type {
RDMA_CM_EVENT_ADDR_RESOLVED,
RDMA_CM_EVENT_ADDR_ERROR,
diff --git a/init/main.c b/init/main.c
index c2215bb334c2..a04442f20429 100644
--- a/init/main.c
+++ b/init/main.c
@@ -1341,6 +1341,14 @@ asmlinkage __visible void __init __no_sanitize_address start_kernel(void)
* timer interrupt). Full topology setup happens at smp_init()
* time - but meanwhile we still have a functioning scheduler.
*/
+
+/*
+ * IAMROOT, 2022.07.09:
+ * -papago
+ * 인터럽트(예: 타이머 인터럽트)를 시작하기 전에 스케줄러를 설정하십시오.
+ * 전체 토폴로지 설정은 smp_init() 시간에 발생하지만 그 동안에는 여전히 작동하는
+ * 스케줄러가 있습니다.
+ */
sched_init();
if (WARN(!irqs_disabled(),
diff --git a/kernel/dma/contiguous.c b/kernel/dma/contiguous.c
index e69c9771c5cc..a073366bf51d 100644
--- a/kernel/dma/contiguous.c
+++ b/kernel/dma/contiguous.c
@@ -57,6 +57,10 @@
#define CMA_SIZE_MBYTES 0
#endif
+/*
+ * IAMROOT, 2022.07.09:
+ * - dma 할당 api가 사용할 기본 cma
+ */
struct cma *dma_contiguous_default_area;
/*
@@ -75,6 +79,13 @@ static phys_addr_t size_cmdline __initdata = -1;
static phys_addr_t base_cmdline __initdata;
static phys_addr_t limit_cmdline __initdata;
+/*
+ * IAMROOT, 2022.07.09:
+ * - admin-guide/kernel-parameters.txt 참고
+ * cma=nn[MG]@[start[MG][-end[MG]]]
+ * ^size
+ * - size는 무조건 있어야 된다.
+ */
static int __init early_cma(char *p)
{
if (!p) {
@@ -170,7 +181,11 @@ void __init dma_pernuma_cma_reserve(void)
*/
/*
* IAMROOT, 2021.12.18:
- * - TODO
+ * - cmdline에 cma정보가 있다면 해당정보로, 아니면 kernel default or config정보로
+ * cma size를 정한후 초기화한다.
+ * 1. cmdline or kernel config로 default cma 정보를 초기화.
+ * 2. dt에 default cma가 있을시. 1번에서 초기화했다면 안하고,
+ * 아니면 dt default cma로 수행.
*/
void __init dma_contiguous_reserve(phys_addr_t limit)
{
@@ -187,12 +202,20 @@ void __init dma_contiguous_reserve(phys_addr_t limit)
* 지정이 안되면 CONFIG에 따라서 selected_size를 지정한다.
*/
if (size_cmdline != -1) {
+/*
+ * IAMROOT, 2022.07.09:
+ * - cmdline
+ */
selected_size = size_cmdline;
selected_base = base_cmdline;
selected_limit = min_not_zero(limit_cmdline, limit);
if (base_cmdline + size_cmdline == limit_cmdline)
fixed = true;
} else {
+/*
+ * IAMROOT, 2022.07.09:
+ * - kernel config
+ */
#ifdef CONFIG_CMA_SIZE_SEL_MBYTES
selected_size = size_bytes;
#elif defined(CONFIG_CMA_SIZE_SEL_PERCENTAGE)
@@ -238,8 +261,9 @@ dma_contiguous_early_fixup(phys_addr_t base, unsigned long size)
* reserve in range from @base to @limit.
*/
/*
- * IAMROOT, 2021.10.23:
- * - cma memory allocator. TODO
+ * IAMROOT, 2022.07.09:
+ * - cmdline or kernel config에 의한 cma 정보를 memblock reserved 영역을 할당하고
+ * @res_cma(struct cma)에 등록한다.
*/
int __init dma_contiguous_reserve_area(phys_addr_t size, phys_addr_t base,
phys_addr_t limit, struct cma **res_cma,
@@ -397,6 +421,10 @@ void dma_free_contiguous(struct device *dev, struct page *page, size_t size)
#undef pr_fmt
#define pr_fmt(fmt) fmt
+/*
+ * IAMROOT, 2022.07.09:
+ * - rmem->priv에는 cma로 사용할때에 struct cma가 저장되있다.
+ */
static int rmem_cma_device_init(struct reserved_mem *rmem, struct device *dev)
{
dev->cma_area = rmem->priv;
@@ -414,8 +442,53 @@ static const struct reserved_mem_ops rmem_cma_ops = {
.device_release = rmem_cma_device_release,
};
+/*
+ * IAMROOT, 2022.07.09:
+ * - ex) boot/dts/amlogic/meson-a1.dtsi
+ * reserved-memory {
+ * #address-cells = <2>;
+ * #size-cells = <2>;
+ * ranges;
+ *
+ * linux,cma {
+ * compatible = "shared-dma-pool";
+ * reusable;
+ * size = <0x0 0x800000>;
+ * alignment = <0x0 0x400000>;
+ * linux,cma-default;
+ * };
+ * };
+ *
+ * - booting 시 순서
+ * loader -> SPL -> TPL -> UBOOT -> kernel
+ * uboot : DTB, config에서 아주 기본적인 정보를 읽어서 초기화
+ *
+ * - size = <0x0 0x800000>;
+ * size 정보만 제공했고, 시작 주소는 안정해서 아무데서나 만들어도 된다는뜻.
+ *
+ * - ex)
+ *
+ * reserved-memory {
+ * #address-cells = <1>;
+ * #size-cells = <1>;
+ * ranges;
+ *
+ * default-pool {
+ * compatible = "shared-dma-pool";
+ * size = <0x6000000>;
+ * alloc-ranges = <0x40000000 0x10000000>;
+ * reusable;
+ * linux,cma-default;
+ * };
+ * };
+ * - alloc-ranges(x,y) : x ~ y 사이에 size만큼 할당하라는 뜻.
+ */
static int __init rmem_cma_setup(struct reserved_mem *rmem)
{
+/*
+ * IAMROOT, 2022.07.09:
+ * - 4K * 1024 = 4M 단위 align
+ */
phys_addr_t align = PAGE_SIZE << max(MAX_ORDER - 1, pageblock_order);
phys_addr_t mask = align - 1;
unsigned long node = rmem->fdt_node;
@@ -423,12 +496,54 @@ static int __init rmem_cma_setup(struct reserved_mem *rmem)
struct cma *cma;
int err;
+/*
+ * IAMROOT, 2022.07.09:
+ * - dt가 default cma인데 cmdline에 의해 이미 default cma 정보가 있을 경우
+ * cmdline꺼를 우선으로 생각해서 dt를 안쓴다.
+ */
if (size_cmdline != -1 && default_cma) {
pr_info("Reserved memory: bypass %s node, using cmdline CMA params instead\n",
rmem->name);
return -EBUSY;
}
+/*
+ * IAMROOT, 2022.07.09:
+ * - documentation
+ * no-map (optional) - empty property
+ * - Indicates the operating system must not create a virtual mapping
+ * of the region as part of its standard mapping of system memory,
+ * nor permit speculative access to it under any circumstances other
+ * than under the control of the device driver using the region.
+ * reusable (optional) - empty property
+ * - The operating system can use the memory in this region with the
+ * limitation that the device driver(s) owning the region need to be
+ * able to reclaim it back. Typically that means that the operating
+ * system can use that region to store volatile or cached data that
+ * can be otherwise regenerated or migrated elsewhere.
+ * - papago
+ * no-map (optional) - empty property
+ * - 운영 체제가 시스템 메모리의 표준 매핑의 일부로 영역의 가상 매핑을
+ * 생성해서는 안 되며 영역을 사용하는 장치 드라이버의 제어 하에 있지 않은
+ * 상황에서 추측적인 액세스를 허용하지 않아야 함을 나타냅니다.
+ *
+ * reusable (optional) - empty property
+ * - 운영 체제는 영역을 소유한 장치 드라이버가 다시 회수할 수 있어야 하는
+ * 제한이 있는 이 영역의 메모리를 사용할 수 있습니다. 일반적으로 이는 운영
+ * 체제가 해당 영역을 사용하여 다른 곳에서 reclaim되거나 migrate될 수 있는
+ * 휘발성 또는 캐시된 데이터를 저장할 수 있음을 의미합니다.
+ *
+ * - reserved memory에서의 no-map의 이유
+ * 1. device가 직접 mapping을 하기때문이다. SRAM등 속도가 빠른 memory를 사용할때
+ * cpu에 있는 l1, l2 cache를 사용하지 않기 위함이다.
+ * 2. device 전용 memory로 cpu개입 없이 사용하기 위함.
+ *
+ * -----------------------
+ *
+ * - 무조건 cma는 reusable, !no-map
+ * reclaim, migrate가 가능해야 된다. 즉 system이 movable page로 사용하겠다는것.
+ * (cpu 개입)
+ */
if (!of_get_flat_dt_prop(node, "reusable", NULL) ||
of_get_flat_dt_prop(node, "no-map", NULL))
return -EINVAL;
@@ -446,6 +561,10 @@ static int __init rmem_cma_setup(struct reserved_mem *rmem)
/* Architecture specific contiguous memory fixup. */
dma_contiguous_early_fixup(rmem->base, rmem->size);
+/*
+ * IAMROOT, 2022.07.09:
+ * - prop가 default_cma라면 default로 넣는다.
+ */
if (default_cma)
dma_contiguous_default_area = cma;
diff --git a/mm/cma.c b/mm/cma.c
index 995e15480937..b081ce39ae3e 100644
--- a/mm/cma.c
+++ b/mm/cma.c
@@ -92,6 +92,10 @@ static void cma_clear_bitmap(struct cma *cma, unsigned long pfn,
spin_unlock_irqrestore(&cma->lock, flags);
}
+/*
+ * IAMROOT, 2022.07.09:
+ * - @cma 영역의 bitmap을 초기화하고 cma page들을 reserved를 풀고 cma buddy로 옮긴다.
+ */
static void __init cma_activate_area(struct cma *cma)
{
unsigned long base_pfn = cma->base_pfn, pfn;
@@ -107,6 +111,11 @@ static void __init cma_activate_area(struct cma *cma)
* same zone.
*/
WARN_ON_ONCE(!pfn_valid(base_pfn));
+
+/*
+ * IAMROOT, 2022.07.09:
+ * - cma는 전부 같은 zone에 있어야된다.
+ */
zone = page_zone(pfn_to_page(base_pfn));
for (pfn = base_pfn + 1; pfn < base_pfn + cma->count; pfn++) {
WARN_ON_ONCE(!pfn_valid(pfn));
@@ -139,6 +148,10 @@ static void __init cma_activate_area(struct cma *cma)
return;
}
+/*
+ * IAMROOT, 2022.07.09:
+ * - dt, cmline, kernel config등으로 미리 초기화된 cma_areas을 설정한다.
+ */
static int __init cma_init_reserved_areas(void)
{
int i;
@@ -162,6 +175,12 @@ core_initcall(cma_init_reserved_areas);
*
* This function creates custom contiguous area from already reserved memory.
*/
+
+/*
+ * IAMROOT, 2022.07.09:
+ * - size, align, reserved 영역 범위 검사등을 수행하고 cma 정보를 하나 얻고
+ * 초기화한다.
+ */
int __init cma_init_reserved_mem(phys_addr_t base, phys_addr_t size,
unsigned int order_per_bit,
const char *name,
@@ -176,6 +195,10 @@ int __init cma_init_reserved_mem(phys_addr_t base, phys_addr_t size,
return -ENOSPC;
}
+/*
+ * IAMROOT, 2022.07.09:
+ * - size가 없거나 이미 reserved 영역과 겹치는지 검사
+ */
if (!size || !memblock_is_region_reserved(base, size))
return -EINVAL;
@@ -231,6 +254,12 @@ int __init cma_init_reserved_mem(phys_addr_t base, phys_addr_t size,
* If @fixed is true, reserve contiguous area at exactly @base. If false,
* reserve in range from @base to @limit.
*/
+
+/*
+ * IAMROOT, 2022.07.09:
+ * - cmdline or kernel config에 의한 cma 정보를 memblock reserved 영역을 할당하고
+ * @res_cma(struct cma)에 등록한다.
+ */
int __init cma_declare_contiguous_nid(phys_addr_t base,
phys_addr_t size, phys_addr_t limit,
phys_addr_t alignment, unsigned int order_per_bit,
@@ -315,6 +344,12 @@ int __init cma_declare_contiguous_nid(phys_addr_t base,
/* Reserve memory */
if (fixed) {
+
+/*
+ * IAMROOT, 2022.07.09:
+ * - start가 0이 아니면 해당 주소를 시작으로 할당한다.
+ * - 겹쳣거나 reserve 할당 실패면 error.
+ */
if (memblock_is_region_reserved(base, size) ||
memblock_reserve(base, size) < 0) {
ret = -EBUSY;
@@ -323,6 +358,10 @@ int __init cma_declare_contiguous_nid(phys_addr_t base,
} else {
phys_addr_t addr = 0;
+/*
+ * IAMROOT, 2022.07.09:
+ * - start가 0이였으면 memblock의 lowmem 영역에서의 할당 정책을 따른다.
+ */
/*
* All pages in the reserved area must come from the same zone.
* If the requested region crosses the low/high memory boundary,
@@ -343,6 +382,15 @@ int __init cma_declare_contiguous_nid(phys_addr_t base,
* Avoid using first 4GB to not interfere with constrained zones
* like DMA/DMA32.
*/
+/*
+ * IAMROOT, 2022.07.09:
+ * - papago
+ * 메모리가 충분하면 상향식 할당을 먼저 시도하십시오.
+ * 새로운 cma 영역을 노드의 시작 부분에 가깝게 배치하고 compaction이 페이지를 cma
+ * 영역 밖으로 이동시키는 것이지 안으로 이동하지 않도록 보장합니다.
+ * DMA/DMA32와 같은 제한된 영역을 방해하지 않으려면 처음 4GB를 사용하지 마십시오.
+ * - DMA가 충분하면 4GB 밖에 cma영역을 생성한다.
+ */
#ifdef CONFIG_PHYS_ADDR_T_64BIT
if (!memblock_bottom_up() && memblock_end >= SZ_4G + size) {
memblock_set_bottom_up(true);
@@ -453,7 +501,18 @@ struct page *cma_alloc(struct cma *cma, unsigned long count,
if (bitmap_count > bitmap_maxno)
goto out;
+/*
+ * IAMROOT, 2022.07.09:
+ * - config 할당을 시도한다. 실패하는 경우 align단위로 점프하면서 재시도한다.
+ */
for (;;) {
+
+/*
+ * IAMROOT, 2022.07.09:
+ * - cma는 bitmap으로 관리하기때문에 cma끼리 관리는 불가능하다. frag 되버리고
+ * 후에 큰 범위 요청이 오면 못한다.
+ * - 여기서 spinlock을 통해 bitmap을 관리하므로 cpu 경합을 피한다.
+ */
spin_lock_irq(&cma->lock);
bitmap_no = bitmap_find_next_zero_area_off(cma->bitmap,
bitmap_maxno, start, bitmap_count, mask,
@@ -474,11 +533,19 @@ struct page *cma_alloc(struct cma *cma, unsigned long count,
ret = alloc_contig_range(pfn, pfn + count, MIGRATE_CMA,
GFP_KERNEL | (no_warn ? __GFP_NOWARN : 0));
+/*
+ * IAMROOT, 2022.07.09:
+ * - 성공하면 break.
+ */
if (ret == 0) {
page = pfn_to_page(pfn);
break;
}
+/*
+ * IAMROOT, 2022.07.09:
+ * - 실패한경우는 지금 정보를 clear하고 mask + 1(align)단위로 start를 바꾼다.
+ */
cma_clear_bitmap(cma, pfn, count);
if (ret != -EBUSY)
break;
@@ -534,6 +601,10 @@ struct page *cma_alloc(struct cma *cma, unsigned long count,
* It returns false when provided pages do not belong to contiguous area and
* true otherwise.
*/
+/*
+ * IAMROOT, 2022.07.09:
+ * - buddy로 돌려보내고 cma bitmap clear한다.
+ */
bool cma_release(struct cma *cma, const struct page *pages,
unsigned long count)
{
diff --git a/mm/cma.h b/mm/cma.h
index 2c775877eae2..00d7bd25d0c4 100644
--- a/mm/cma.h
+++ b/mm/cma.h
@@ -12,8 +12,16 @@ struct cma_kobject {
struct cma {
unsigned long base_pfn;
+/*
+ * IAMROOT, 2022.07.09:
+ * - page count
+ */
unsigned long count;
unsigned long *bitmap;
+/*
+ * IAMROOT, 2022.07.09:
+ * - cma에서 관리할때는 0, huge_tlb에서 관리할때는 huge tlb order(9. 2MB)
+ */
unsigned int order_per_bit; /* Order of pages represented by one bit */
spinlock_t lock;
#ifdef CONFIG_CMA_DEBUGFS
@@ -35,6 +43,10 @@ struct cma {
extern struct cma cma_areas[MAX_CMA_AREAS];
extern unsigned cma_area_count;
+/*
+ * IAMROOT, 2022.07.09:
+ * - cma에서 관리할때는 0, huge_tlb에서 관리할때는 huge tlb order(9. 2MB)
+ */
static inline unsigned long cma_bitmap_maxno(struct cma *cma)
{
return cma->count >> cma->order_per_bit;
diff --git a/mm/compaction.c b/mm/compaction.c
index f6400e2605aa..18ef483c37e1 100644
--- a/mm/compaction.c
+++ b/mm/compaction.c
@@ -89,6 +89,10 @@ static unsigned long release_freepages(struct list_head *freelist)
return high_pfn;
}
+/*
+ * IAMROOT, 2022.07.09:
+ * - page들의 order를 다 풀어서 single page로 만들어서 @list에 다시 넣는다.
+ */
static void split_map_pages(struct list_head *list)
{
unsigned int i, order, nr_pages;
@@ -757,6 +761,26 @@ static bool compact_unlock_should_abort(spinlock_t *lock,
* returning 0 on any invalid PFNs or non-free pages inside of the pageblock
* (even though it may still end up isolating some pages).
*/
+/*
+ * IAMROOT, 2022.07.09:
+ * @strict true 면 무조건 1 page씩 하며 처음부터 끝가지 다 하겠다는 의미.
+ * false 면 요청한 stride 만큼 page을 점프하면서 하고, migrate page보다
+ * free page가 많아지면 종료한다.
+ * @stride @strict가 true면 의미없다. 1로 고정.
+ * @strict가 false인 경우 요청값(1 ~ COMPACT_CLUSTER_MAX)으로 되며
+ * @stride 단위로 page을 skip한다.
+ *
+ * - stride를 1보다 큰값으로 단위로 검색을 하기도하는데, 한번 실패하게되면
+ * 연속으로 실패가능성이 크므로, 1, 2, 4.. 단위로 점프하면서 isolate가 되는 page를
+ * 찾기 위함도있다. 한번찾아지면 다시 단위가 1로 작아질것이다. stride를 쓰는
+ * 함수면 어짜피 migrate page보다만 free를 얻어오면되서 적당히 빨리 하기위함도
+ * 있는거같다. (isolate_freepages() 참고)
+ * - cma contig에서 할당받을때는 무조건 성공을 해야되기때문에 strice이 true가되서
+ * stride가 무조건 1로 고정으로되어 skip없이 모든 영역을 검사한다.
+ *
+ * - pageblock내에서 stride page 단위로 freelist에서 page를 제거한다. 제거된
+ * page는 @freelist로 넣어진다.
+ */
static unsigned long isolate_freepages_block(struct compact_control *cc,
unsigned long *start_pfn,
unsigned long end_pfn,
@@ -800,6 +824,11 @@ static unsigned long isolate_freepages_block(struct compact_control *cc,
* The check is racy, but we can consider only valid values
* and the only danger is skipping too much.
*/
+
+/*
+ * IAMROOT, 2022.07.09:
+ * - page가 compound page거나 buddy에 없으면 isolate fail.
+ */
if (PageCompound(page)) {
const unsigned int order = compound_order(page);
@@ -820,6 +849,10 @@ static unsigned long isolate_freepages_block(struct compact_control *cc,
* so it is correct to skip the suitable migration target
* recheck as well.
*/
+/*
+ * IAMROOT, 2022.07.09:
+ * - zone lock을 하고 buddy에 있는지 계속있는지 한번더 검사한다.
+ */
if (!locked) {
locked = compact_lock_irqsave(&cc->zone->lock,
&flags, cc);
@@ -830,6 +863,10 @@ static unsigned long isolate_freepages_block(struct compact_control *cc,
}
/* Found a free page, will break it into order-0 pages */
+/*
+ * IAMROOT, 2022.07.09:
+ * - buddy freelist에서 page를 제거한다.
+ */
order = buddy_order(page);
isolated = __isolate_free_page(page, order);
if (!isolated)
@@ -838,8 +875,17 @@ static unsigned long isolate_freepages_block(struct compact_control *cc,
total_isolated += isolated;
cc->nr_freepages += isolated;
+
+/*
+ * IAMROOT, 2022.07.09:
+ * - buddy에서 제거한 page를 local freelist에 넣어놓는다.
+ */
list_add_tail(&page->lru, freelist);
+/*
+ * IAMROOT, 2022.07.09:
+ * - @strict이 false면 free page를 migratge 했던 page이상이면 중단.
+ */
if (!strict && cc->nr_migratepages <= cc->nr_freepages) {
blockpfn += isolated;
break;
@@ -901,6 +947,17 @@ static unsigned long isolate_freepages_block(struct compact_control *cc,
* (which may be greater then end_pfn if end fell in a middle of
* a free page).
*/
+
+/*
+ * IAMROOT, 2022.07.09:
+ * - papago
+ * non-free 페이지, 유효하지 않은 PFN 또는 [start_pfn, end_pfn) 범위 내의
+ * 영역 경계는 오류로 간주되어 함수가 해당 작업을 실행 취소하고 0을 반환하게
+ * 합니다.
+ *
+ * 그렇지 않으면 함수는 isolate 페이지의 마지막 PFN을 반환합니다(종료가
+ * 빈 페이지의 중간에 있는 경우 end_pfn보다 클 수 있음).
+ */
unsigned long
isolate_freepages_range(struct compact_control *cc,
unsigned long start_pfn, unsigned long end_pfn)
@@ -956,9 +1013,18 @@ isolate_freepages_range(struct compact_control *cc,
}
/* __isolate_free_page() does not map the pages */
+
+/*
+ * IAMROOT, 2022.07.09:
+ * - single page로 나눈다.
+ */
split_map_pages(&freelist);
if (pfn < end_pfn) {
+/*
+ * IAMROOT, 2022.07.09:
+ * - 실패. buddy로 원복.
+ */
/* Loop terminated early, cleanup. */
release_freepages(&freelist);
return 0;
@@ -1644,6 +1710,10 @@ isolate_migratepages_block(struct compact_control *cc, unsigned long low_pfn,
* Returns -EAGAIN when contented, -EINTR in case of a signal pending, -ENOMEM
* in case we could not allocate a page, or 0.
*/
+/*
+ * IAMROOT, 2022.07.09:
+ * - @cc->migratepages에 요청범위의 page를 옮긴다.
+ */
int
isolate_migratepages_range(struct compact_control *cc, unsigned long start_pfn,
unsigned long end_pfn)
@@ -1668,6 +1738,10 @@ isolate_migratepages_range(struct compact_control *cc, unsigned long start_pfn,
block_end_pfn, cc->zone))
continue;
+/*
+ * IAMROOT, 2022.07.09:
+ * - ISOLATE_UNEVICTABLE : mlocked으로 잠긴 page조차 isolate시키라는 강제 명령.
+ */
ret = isolate_migratepages_block(cc, pfn, block_end_pfn,
ISOLATE_UNEVICTABLE);
@@ -2210,6 +2284,12 @@ static void isolate_freepages(struct compact_control *cc)
continue;
/* Found a block suitable for isolating free pages from. */
+/*
+ * IAMROOT, 2022.07.09:
+ * - stride를 1보다 큰값으로 단위로 검색을 하기도하는데, 한번 실패하게되면
+ * 연속으로 실패가능성이 크므로, 1, 2, 4.. 단위로 점프하면서 isolate가 되는 page를
+ * 찾기 위함도있다. 한번찾아지면 다시 단위가 1로 작아질것이다.
+ */
nr_isolated = isolate_freepages_block(cc, &isolate_start_pfn,
block_end_pfn, freelist, stride, false);
diff --git a/mm/migrate.c b/mm/migrate.c
index 207b1c53626b..f4ba07309f33 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -1431,6 +1431,7 @@ int next_demotion_node(int node)
*/
/*
* IAMROOT, 2022.04.02:
+ * @ reason trace, debug 용
* - 1. get_new_page를 통해서 new_page를 얻어온다.
* 2. @page를 newpage로 속성들을 복사한다. @page따라서 contents까지
* 복사한다.
@@ -1729,7 +1730,7 @@ static inline int try_split_thp(struct page *page, struct page **page2,
*/
/*
* IAMROOT, 2022.04.02:
- * @reason enum migrate_reason
+ * @reason enum migrate_reason. trace, debug 용
*/
int migrate_pages(struct list_head *from, new_page_t get_new_page,
free_page_t put_new_page, unsigned long private,
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index c017a743e7a4..8bb9ff44d09b 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -2017,7 +2017,7 @@ static void free_pcppages_bulk(struct zone *zone, int count,
* IAMROOT, 2022.05.14:
* - buddy로 free.
* - @zone에 isolate pageblock이 존재하거나, @page가 isolate일 경우
- * 대표 migratetype으로 변경한다.
+ * 해당 page를 대표 migratetype으로 변경후 buddy로 보낸다.
*/
static void free_one_page(struct zone *zone,
struct page *page, unsigned long pfn,
@@ -2837,6 +2837,11 @@ void __init page_alloc_init_late(void)
#ifdef CONFIG_CMA
/* Free whole pageblock and set its migration type to MIGRATE_CMA. */
+/*
+ * IAMROOT, 2022.07.09:
+ * - migrate cma buddy로 보내기 위해 reserved clear후 migratetype cma로 pageblock
+ * migratetype을 설정한다.
+ */
void __init init_cma_reserved_pageblock(struct page *page)
{
unsigned i = pageblock_nr_pages;
@@ -2849,6 +2854,10 @@ void __init init_cma_reserved_pageblock(struct page *page)
set_pageblock_migratetype(page, MIGRATE_CMA);
+/*
+ * IAMROOT, 2022.07.09:
+ * - ref up을 하고 MIGRATE_CMA buddy로 돌려보낸다.
+ */
if (pageblock_order >= MAX_ORDER) {
i = pageblock_nr_pages;
p = page;
@@ -2863,6 +2872,11 @@ void __init init_cma_reserved_pageblock(struct page *page)
}
adjust_managed_page_count(page, pageblock_nr_pages);
+
+/*
+ * IAMROOT, 2022.07.09:
+ * - 해당 존에 cma가 이제 생기는것이므로 카운팅 추가.
+ */
page_zone(page)->cma_pages += pageblock_nr_pages;
}
#endif
@@ -4612,6 +4626,11 @@ void split_page(struct page *page, unsigned int order)
}
EXPORT_SYMBOL_GPL(split_page);
+/*
+ * IAMROOT, 2022.07.09:
+ * - @order 단위로 freelist에서 제거한다.
+ * - alloc_contig_pages()로 들어왔으면 @page의 pageblock mt는 isolate일 것이다.
+ */
int __isolate_free_page(struct page *page, unsigned int order)
{
unsigned long watermark;
@@ -4623,6 +4642,11 @@ int __isolate_free_page(struct page *page, unsigned int order)
zone = page_zone(page);
mt = get_pageblock_migratetype(page);
+/*
+ * IAMROOT, 2022.07.09:
+ * - pageblock mt가 isolate가 아니라면 CMA에 할당가능한지 검사.
+ *
+ */
if (!is_migrate_isolate(mt)) {
/*
* Obey watermarks as if the page was being allocated. We can
@@ -4630,6 +4654,13 @@ int __isolate_free_page(struct page *page, unsigned int order)
* watermark, because we already know our high-order page
* exists.
*/
+/*
+ * IAMROOT, 2022.07.09:
+ * - papago
+ * 페이지가 할당되는 것처럼 워터마크를 준수합니다. 상위 페이지가 존재한다는
+ * 것을 이미 알고 있기 때문에 상위 워터마크 검사를 제기된 0차 워터마크로
+ * 에뮬레이트할 수 있습니다.
+ */
watermark = zone->_watermark[WMARK_MIN] + (1UL << order);
if (!zone_watermark_ok(zone, 0, watermark, 0, ALLOC_CMA))
return 0;
@@ -4645,6 +4676,11 @@ int __isolate_free_page(struct page *page, unsigned int order)
* Set the pageblock if the isolated page is at least half of a
* pageblock
*/
+/*
+ * IAMROOT, 2022.07.09:
+ * - order가 pageblock_order보다 클경우 pageblock단위로
+ * UNMOVABLE, RECLAIM인 경우 MOVABLE로 변경할지 확인하고 변경한다.
+ */
if (order >= pageblock_order - 1) {
struct page *endpage = page + (1 << order) - 1;
for (; page < endpage; page += pageblock_nr_pages) {
@@ -5198,6 +5234,7 @@ bool __zone_watermark_ok(struct zone *z, unsigned int order, unsigned long mark,
/*
* IAMROOT, 2022.03.05:
+ * @return 할당가능하면 true.
* - 가장 기본 형태의 free page 확인 함수.
* 러프한 값을 가지고 @order에 대한 free page를 확인한다.
*/
@@ -10856,6 +10893,11 @@ static int __init cmdline_parse_movablecore(char *p)
early_param("kernelcore", cmdline_parse_kernelcore);
early_param("movablecore", cmdline_parse_movablecore);
+/*
+ * IAMROOT, 2022.07.09:
+ * - @page : buddy system으로 관리하게 될 page.
+ * @page들을 counting한다.
+ */
void adjust_managed_page_count(struct page *page, long count)
{
atomic_long_add(count, &page_zone(page)->managed_pages);
@@ -11657,6 +11699,22 @@ void *__init alloc_large_system_hash(const char *tablename,
* cannot get removed (e.g., via memory unplug) concurrently.
*
*/
+/*
+ * IAMROOT, 2022.07.09:
+ * - papgo
+ * 이 함수는 pageblock에 움직일 수 없는 페이지가 포함되어 있는지 확인합니다.
+ *
+ * isolate 또는 lru_lock이 없는 PageLRU 검사가 경합하여 MIGRATE_MOVABLE 블록에
+ * 이동할 수 없는 페이지가 포함될 수 있습니다. 또한 lock_page가 없는
+ * __PageMovable 검사는 경쟁 조건에서 일부 이동 가능한 비 lru 페이지를
+ * 놓칠 수 있습니다. 따라서 이 함수가 정확해야 한다고 기대할 수는 없습니다.
+ *
+ * 참조를 보유하지 않고 페이지를 반환합니다. 호출자가 해당 페이지를
+ * 역참조(예: 덤프)하려는 경우 해당 페이지가 동시에 제거될 수
+ * 없도록(예: 메모리 분리를 통해) 확인해야 합니다.
+ *
+ * - page block내에서 이동불가인 page들이 있는지 확인한다. 있다면 return page
+ */
struct page *has_unmovable_pages(struct zone *zone, struct page *page,
int migratetype, int flags)
{
@@ -11670,6 +11728,12 @@ struct page *has_unmovable_pages(struct zone *zone, struct page *page,
* isolate CMA pageblocks even when they are not movable in fact
* so consider them movable here.
*/
+/*
+ * IAMROOT, 2022.07.09:
+ * - unmovable이 요청 범위에 있는지 확인하는 api에서, @page의 pageblock이 cma인데
+ * 다른 migrate type으로 변경을 요청한다면 unmovable로 취급해서 해당
+ * page를 return한다. 즉 변경 불가의 의미
+ */
if (is_migrate_cma(migratetype))
return NULL;
@@ -11685,6 +11749,10 @@ struct page *has_unmovable_pages(struct zone *zone, struct page *page,
* allocations inside ZONE_MOVABLE, for example when
* specifying "movablecore".
*/
+/*
+ * IAMROOT, 2022.07.09:
+ * - reserved는 변경불가. unmovable 취급.
+ */
if (PageReserved(page))
return page;
@@ -11693,6 +11761,10 @@ struct page *has_unmovable_pages(struct zone *zone, struct page *page,
* pages then it should be reasonably safe to assume the rest
* is movable.
*/
+/*
+ * IAMROOT, 2022.07.09:
+ * - movable zone은 변경가능. skip
+ */
if (zone_idx(zone) == ZONE_MOVABLE)
continue;
@@ -11702,6 +11774,11 @@ struct page *has_unmovable_pages(struct zone *zone, struct page *page,
* We need not scan over tail pages because we don't
* handle each tail page individually in migration.
*/
+/*
+ * IAMROOT, 2022.07.09:
+ * - huge page인데 migratge support안하면 return page.
+ * lru도 아니고 non-lru도 아니면 movable 불가이므로 return page.
+ */
if (PageHuge(page) || PageTransCompound(page)) {
struct page *head = compound_head(page);
unsigned int skip_pages;
@@ -11724,6 +11801,10 @@ struct page *has_unmovable_pages(struct zone *zone, struct page *page,
* This check already skips compound tails of THP
* because their page->_refcount is zero at all time.
*/
+/*
+ * IAMROOT, 2022.07.09:
+ * - free가 되버린 page. continue.
+ */
if (!page_ref_count(page)) {
if (PageBuddy(page))
iter += (1 << buddy_order(page)) - 1;
@@ -11734,6 +11815,11 @@ struct page *has_unmovable_pages(struct zone *zone, struct page *page,
* The HWPoisoned page may be not in buddy system, and
* page_count() is not 0.
*/
+/*
+ * IAMROOT, 2022.07.09:
+ * - buddy에 없는 offline page이면서 HWPoison 이거나 PageOfflinㅇ이면
+ * 움직일수있다고 판단.
+ */
if ((flags & MEMORY_OFFLINE) && PageHWPoison(page))
continue;
@@ -11750,6 +11836,10 @@ struct page *has_unmovable_pages(struct zone *zone, struct page *page,
if ((flags & MEMORY_OFFLINE) && PageOffline(page))
continue;
+/*
+ * IAMROOT, 2022.07.09:
+ * - non-lru movable이거나 lru면 이동가능.
+ */
if (__PageMovable(page) || PageLRU(page))
continue;
@@ -11758,6 +11848,10 @@ struct page *has_unmovable_pages(struct zone *zone, struct page *page,
* it. But now, memory offline itself doesn't call
* shrink_node_slabs() and it still to be fixed.
*/
+/*
+ * IAMROOT, 2022.07.09:
+ * - 그외에는 이동불가 취급.
+ */
return page;
}
return NULL;
@@ -11798,6 +11892,11 @@ static inline void alloc_contig_dump_pages(struct list_head *page_list)
#endif
/* [start, end) must belong to a single zone. */
+/*
+ * IAMROOT, 2022.07.09:
+ * - @start ~ @end까지 migrate를 수행한다. signal을 받거나 error가 나지 않는한은
+ * 될때까지 수행한다.
+ */
static int __alloc_contig_migrate_range(struct compact_control *cc,
unsigned long start, unsigned long end)
{
@@ -11819,6 +11918,10 @@ static int __alloc_contig_migrate_range(struct compact_control *cc,
break;
}
+/*
+ * IAMROOT, 2022.07.09:
+ * - cc->migratepages가 비어있다면 채운다.
+ */
if (list_empty(&cc->migratepages)) {
cc->nr_migratepages = 0;
ret = isolate_migratepages_range(cc, pfn, end);
@@ -11831,10 +11934,19 @@ static int __alloc_contig_migrate_range(struct compact_control *cc,
break;
}
+/*
+ * IAMROOT, 2022.07.09:
+ * - cc->migratepages에 있는 page들 중 clean page들을 reclaim한다.
+ * 못한 page들은 남아있다.
+ */
nr_reclaimed = reclaim_clean_pages_from_list(cc->zone,
&cc->migratepages);
cc->nr_migratepages -= nr_reclaimed;
+/*
+ * IAMROOT, 2022.07.09:
+ * - cc->migratepages에 남아있는것들은 migratge한다.
+ */
ret = migrate_pages(&cc->migratepages, alloc_migration_target,
NULL, (unsigned long)&mtc, cc->mode, MR_CONTIG_RANGE, NULL);
@@ -11847,6 +11959,11 @@ static int __alloc_contig_migrate_range(struct compact_control *cc,
}
lru_cache_enable();
+
+/*
+ * IAMROOT, 2022.07.09:
+ * - 실패했다면 원복후 dump debug 출력.
+ */
if (ret < 0) {
if (ret == -EBUSY)
alloc_contig_dump_pages(&cc->migratepages);
@@ -11877,6 +11994,20 @@ static int __alloc_contig_migrate_range(struct compact_control *cc,
* pages which PFN is in [start, end) are allocated for the caller and
* need to be freed with free_contig_range().
*/
+
+/*
+ * IAMROOT, 2022.07.09:
+ * - papago
+ * PFN 범위는 페이지 블록 또는 MAX_ORDER_NR_PAGES 정렬될 필요가 없습니다.
+ * PFN 범위는 단일 영역에 속해야 합니다.
+ *
+ * 이 루틴이 수행하는 첫 번째 작업은 범위의 모든 페이지 블록을
+ * MIGRATE_ISOLATE하려고 시도하는 것입니다. 일단 격리되면 페이지 블록은
+ * 다른 사람이 수정해서는 안 됩니다.
+ *
+ * Return: 성공 또는 음수 오류 코드의 경우 0입니다. 성공하면 PFN이 [시작, 끝]에
+ * 있는 모든 페이지가 호출자에게 할당되고 free_contig_range()로 해제되어야 합니다.
+ */
int alloc_contig_range(unsigned long start, unsigned long end,
unsigned migratetype, gfp_t gfp_mask)
{
@@ -11919,12 +12050,42 @@ int alloc_contig_range(unsigned long start, unsigned long end,
* aligned range but not in the unaligned, original range are
* put back to page allocator so that buddy can use them.
*/
-
+/*
+ * IAMROOT, 2022.07.09:
+ * -papago
+ * 여기에서는 범위 내의 모든 페이지 블록을 MIGRITE_ISOLATE로 표시합니다.
+ * 페이지 블록과 최대 순서 페이지는 크기가 다를 수 있으며 페이지 할당자의
+ * 작동 방식 때문에 페이지 할당자가 다른 페이지 블록의 buddy를 병합하거나
+ * MIGRITE_ISOLATE를 다른 마이그레이션 유형으로 변경하지 않도록 두 페이지 중
+ * 가장 큰 페이지에 범위를 맞춥니다.
+ *
+ * 페이지 블록이 MIGRATE_ISOLATE로 표시되면 정렬되지 않은 범위(즉, 관심 있는
+ * 페이지)에서 페이지를 마이그레이션합니다. 이렇게 하면 범위 내의 모든 페이지가
+ * 다시 페이지 할당자로 MIGRIGHT_ISOLATE됩니다.
+ *
+ * 이 작업이 완료되면 페이지 할당기에서 범위 내의 페이지를 가져와
+ * 버디 시스템에서 제거합니다. 이런 방식으로 페이지 할당자는 이러한 항목을
+ * 사용하는 것을 고려하지 않습니다.
+ *
+ * 이렇게 하면 페이지 블록을 다시 MIGRATE_CMA/MIGRATE_MOVIBLE로 표시하여
+ * 정렬된 범위에 있지만 정렬되지 않은 원래 범위에 있지 않은 사용 가능한
+ * 페이지가 다시 페이지 할당기에 표시되도록 하여 버디가 사용할 수 있도록 합니다.
+ */
+/*
+ * IAMROOT, 2022.07.09:
+ * - isolate 표식.
+ */
ret = start_isolate_page_range(pfn_max_align_down(start),
pfn_max_align_up(end), migratetype, 0);
if (ret)
return ret;
+/*
+ * IAMROOT, 2022.07.09:
+ * - pcplist에 있는 page들은 사용중으로 취급하기 때문에 일단 buddy로 돌려보낸다.
+ * - 연속된 memory할당을 해야되기때문에 잘려져서 할당되있는 pcp memory들
+ * 방해가 될수있기 때문이다.
+ */
drain_all_pages(cc.zone);
/*
@@ -11937,7 +12098,26 @@ int alloc_contig_range(unsigned long start, unsigned long end,
* allocated. So, if we fall through be sure to clear ret so that
* -EBUSY is not accidentally used or returned to caller.
*/
+/*
+ * IAMROOT, 2022.07.09:
+ * - papago
+ * -EBUSY의 경우, 어느 페이지에서 문제가 발생하는지 알고 싶습니다.
+ * test_pages_isolated()에는 사용 중인 페이지를 보고할 추적점이 있습니다.
+ *
+ * test_pages_isolated로 호출하기 전에 사용 중인 페이지를 사용할 수 있으며
+ * 범위가 실제로 할당될 수 있습니다. 따라서, 만약 우리가 실패한다면, -EBUSY가
+ * 실수로 사용되거나 호출자에게 반환되지 않도록 반드시 ret를 클리어해야
+ * 합니다.
+ *
+ * - isolate 표시만 해놨던 page들을 실제 isolate시킨다. 그리고 reclaim이 즉시
+ * 가능한것들은 수행하고, 아니면 migrate한다.
+ */
ret = __alloc_contig_migrate_range(&cc, start, end);
+
+/*
+ * IAMROOT, 2022.07.09:
+ * - !busy이면 error 처리.
+ */
if (ret && ret != -EBUSY)
goto done;
ret = 0;
@@ -11959,8 +12139,31 @@ int alloc_contig_range(unsigned long start, unsigned long end,
* isolated thus they won't get removed from buddy.
*/
+/*
+ * IAMROOT, 2022.07.09:
+ * -papago
+ * [start, end)의 페이지는 MIGRATE_ISOLATE로 표시된 MAX_ORDER_NR_PAGES
+ * aligned 블록 내에 있습니다. 또한 [start, end)의 모든 페이지는 페이지 할당자에서
+ * free입니다.
+ * 우리가 할 일은 [시작, 끝)에서 모든 페이지를 할당하는 것입니다(즉,
+ * 페이지 할당자에서 제거).
+ *
+ * 유일한 문제는 관심 범위의 시작과 끝에 있는 페이지가 페이지 할당자가 보유하는
+ * 페이지와 정렬되지 않을 수 있다는 것입니다. 그들은 highorder 페이지의 일부가
+ * 될 수 있습니다. 이 때문에 더 큰 범위를 예약하고 이 작업이 완료되면 관심이 없는
+ * 페이지를 해제합니다.
+ *
+ * 페이지가 격리되어 buddy로부터 제거되지 않기 때문에 여기에서
+ * zone->lock을 유지할 필요가 없습니다.
+ */
order = 0;
outer_start = start;
+
+/*
+ * IAMROOT, 2022.07.09:
+ * - migrate 끝난 범위를 이제 cma로 쓰기 위해 할당을 시작한다.
+ * - start page가 buddy가 아니라면 order 단위로증가하면서 start를 조정해본다.
+ */
while (!PageBuddy(pfn_to_page(outer_start))) {
if (++order >= MAX_ORDER) {
outer_start = start;
@@ -11969,6 +12172,10 @@ int alloc_contig_range(unsigned long start, unsigned long end,
outer_start &= ~0UL << order;
}
+/*
+ * IAMROOT, 2022.07.09:
+ * - start 지점이 옮겼다면, 해당 지점이 상위 buddy라면 하위 buddy로 변경한다.
+ */
if (outer_start != start) {
order = buddy_order(pfn_to_page(outer_start));
@@ -11978,17 +12185,33 @@ int alloc_contig_range(unsigned long start, unsigned long end,
* in this case to report failed page properly
* on tracepoint in test_pages_isolated()
*/
+/*
+ * IAMROOT, 2022.07.09:
+ * - papago
+ * outer_start 페이지는 small order buddy 페이지일 수 있으며 시작 페이지는
+ * 포함되지 않습니다. 이 경우 outer_start를 조정하여 test_pages_isolated()의
+ * 추적점에서 실패한 페이지를 제대로 보고합니다.
+ */
if (outer_start + (1UL << order) <= start)
outer_start = start;
}
/* Make sure the range is really isolated. */
+/*
+ * IAMROOT, 2022.07.09:
+ * - migrate해온 page들이 전부 buddy에 있는지 한번 test.
+ */
if (test_pages_isolated(outer_start, end, 0)) {
ret = -EBUSY;
goto done;
}
/* Grab isolated pages from freelists. */
+/*
+ * IAMROOT, 2022.07.09:
+ * - buddy에 isolate pageorder type으로 들어가있던 page들을 isolate하여
+ * single page로 가져온다.
+ */
outer_end = isolate_freepages_range(&cc, outer_start, end);
if (!outer_end) {
ret = -EBUSY;
@@ -12104,6 +12327,10 @@ struct page *alloc_contig_pages(unsigned long nr_pages, gfp_t gfp_mask,
}
#endif /* CONFIG_CONTIG_ALLOC */
+/*
+ * IAMROOT, 2022.07.09:
+ * - 이미 contig alloc을 했던(migrate통일, merge등) page이므로 free만 해준다.
+ */
void free_contig_range(unsigned long pfn, unsigned long nr_pages)
{
unsigned long count = 0;
diff --git a/mm/page_isolation.c b/mm/page_isolation.c
index a95c2c6562d0..c7c023638775 100644
--- a/mm/page_isolation.c
+++ b/mm/page_isolation.c
@@ -15,6 +15,11 @@
#define CREATE_TRACE_POINTS
#include <trace/events/page_isolation.h>
+/*
+ * IAMROOT, 2022.07.09:
+ * - @page가 소속된 page block단위로 @migratetype으로 이동이 가능한지 확인한다.
+ * 이동이 가능하다면 isolate한다.
+ */
static int set_migratetype_isolate(struct page *page, int migratetype, int isol_flags)
{
struct zone *zone = page_zone(page);
@@ -37,6 +42,10 @@ static int set_migratetype_isolate(struct page *page, int migratetype, int isol_
* FIXME: Now, memory hotplug doesn't call shrink_slab() by itself.
* We just check MOVABLE pages.
*/
+/*
+ * IAMROOT, 2022.07.09:
+ * - page block내에 움직일수없는 page가 있는지 확인한다. 없다면 isolate한다.
+ */
unmovable = has_unmovable_pages(zone, page, migratetype, isol_flags);
if (!unmovable) {
unsigned long nr_pages;
@@ -86,6 +95,15 @@ static void unset_migratetype_isolate(struct page *page, unsigned migratetype)
* approach in order to merge them. Isolation and free will make
* these pages to be merged.
*/
+/*
+ * IAMROOT, 2022.07.09:
+ * - papago
+ * isolated pageblock에 pageblock_order 이상의 freepage가 있는 freepage는
+ * freepage counting 문제로 merge가 제한되기 때문에 free buddy page가 있을
+ * 가능성이 있다.
+ * move_freepages_block()은 병합을 신경 쓰지 않으므로 병합하려면 다른 접근
+ * 방식이 필요합니다. Isolation 및 free는 이러한 페이지를 병합하도록 합니다.
+ */
if (PageBuddy(page)) {
order = buddy_order(page);
if (order >= pageblock_order && order < MAX_ORDER - 1) {
@@ -122,6 +140,10 @@ static void unset_migratetype_isolate(struct page *page, unsigned migratetype)
spin_unlock_irqrestore(&zone->lock, flags);
}
+/*
+ * IAMROOT, 2022.07.09:
+ * - 첫번째 online page를 return.
+ */
static inline struct page *
__first_valid_page(unsigned long pfn, unsigned long nr_pages)
{
@@ -179,6 +201,37 @@ __first_valid_page(unsigned long pfn, unsigned long nr_pages)
*
* Return: 0 on success and -EBUSY if any part of range cannot be isolated.
*/
+/*
+ * IAMROOT, 2022.07.09:
+ * - papgo
+ * 페이지 할당 유형을 MIGRATE_ISOLATE로 설정하면 해당 범위의 사용 가능한
+ * 페이지가 할당되지 않습니다. 이후에 사용 가능한 페이지와 페이지는 다시
+ * 할당되지 않습니다. 지정된 범위에 MOVAL 또는 CMA가 아닌 마이그레이션 유형이
+ * 포함된 경우 -EBUSY에서 실패합니다. 범위의 모든 페이지를 마지막으로 분리하려면
+ * 호출자가 범위의 모든 페이지를 비워 두어야 합니다.
+ * test_page_filename은 테스트에 사용할 수 있습니다.
+ *
+ * 두 스레드가 겹치는 범위를 분리하는 것을 방지하는 높은 수준의 동기화
+ * 메커니즘은 없습니다. 이 경우, 한 스레드는 이미 분리되도록 설정된 겹치는
+ * 범위의 페이지 블록을 인식합니다.
+ * 이 문제는 set_migratetype_isolate에서 발생하며 set_migratetype_isolate는
+ * 오류를 반환합니다. 그런 다음 수정한 페이지 블록의 마이그레이션 유형을
+ * 복원하여 정리하고 -EBUSY를 호출자에게 반환합니다. 이렇게 하면 두 개의
+ * 스레드가 겹치는 범위에서 동시에 작동하지 않습니다.
+ *
+ * 페이지 할당기와의 강력한 동기화도 없습니다. 페이지 블록이 분리되어 있는
+ * 동안 페이지가 해제될 수 있습니다.
+ * 분리 후 drain_all_pages()를 호출하면 대부분의 페이지를 플러시할 수 있습니다.
+ * 그러나 경우에 따라서는 페이지가 pcp 목록에 남아 있을 수 있으며, 이는 페이지가
+ * 이미 격리되어 있는 경우에도 페이지 할당을 허용한다. 호출자에게 필요한 보증
+ * 강도에 따라 zone_pcp_disable/enable()을 사용하여 분리 전에 pcplist를 플러시
+ * 및 해제하고 분리 해제 후 활성화할 수 있습니다.
+ *
+ * Return: 성공 시 0이고 범위의 어느 부분도 분리할 수 없는 경우 -EBUSY입니다.
+ *
+ * - pageblock단위로 요청범위만큼 @migratetype으로 이동이 가능한지 확인하고
+ * isolate시킨다.
+ */
int start_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn,
unsigned migratetype, int flags)
{
@@ -189,6 +242,11 @@ int start_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn,
BUG_ON(!IS_ALIGNED(start_pfn, pageblock_nr_pages));
BUG_ON(!IS_ALIGNED(end_pfn, pageblock_nr_pages));
+/*
+ * IAMROOT, 2022.07.09:
+ * - @start_pfn ~ @end_pfn 을 순회하며 online page가 있는지 확인한다.
+ * online page들은 isolate를 시킨다.
+ */
for (pfn = start_pfn;
pfn < end_pfn;
pfn += pageblock_nr_pages) {
@@ -202,6 +260,10 @@ int start_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn,
}
return 0;
undo:
+/*
+ * IAMROOT, 2022.07.09:
+ * - 도중에 실패했다면 원복시킨다.
+ */
for (pfn = start_pfn;
pfn < undo_pfn;
pfn += pageblock_nr_pages) {
@@ -242,6 +304,17 @@ void undo_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn,
*
* Returns the last tested pfn.
*/
+/*
+ * IAMROOT, 2022.07.09:
+ * -papago
+ * 범위의 모든 페이지가 비어 있는지(격리됨을 의미) 테스트하십시오.
+ * [start_pfn...end_pfn)의 모든 페이지는 동일한 영역에 있어야 합니다.
+ * 이것을 호출하기 전에 zone->lock을 유지해야 합니다.
+ *
+ * 마지막으로 테스트한 pfn을 반환합니다.
+ *
+ * - [pfn, end_pfn) 까지 buddy에 있는지 확인한다.
+ */
static unsigned long
__test_page_isolated_in_pageblock(unsigned long pfn, unsigned long end_pfn,
int flags)
@@ -256,6 +329,13 @@ __test_page_isolated_in_pageblock(unsigned long pfn, unsigned long end_pfn,
* the correct MIGRATE_ISOLATE freelist. There is no
* simple way to verify that as VM_BUG_ON(), though.
*/
+/*
+ * IAMROOT, 2022.07.09:
+ * - papago
+ * 페이지가 사용 가능 목록에 있으면 올바른 MIGRATE_ISOLATE 사용 가능 목록에
+ * 있어야 합니다. 그러나 VM_BUG_ON()으로 이를 확인할 수 있는 간단한 방법은
+ * 없습니다.
+ */
pfn += 1 << buddy_order(page);
else if ((flags & MEMORY_OFFLINE) && PageHWPoison(page))
/* A HWPoisoned page cannot be also PageBuddy */
@@ -276,6 +356,10 @@ __test_page_isolated_in_pageblock(unsigned long pfn, unsigned long end_pfn,
}
/* Caller should ensure that requested range is in a single zone */
+/*
+ * IAMROOT, 2022.07.09:
+ * - 요청범위 page가 전부 buddy에 있는지 확인한다.
+ */
int test_pages_isolated(unsigned long start_pfn, unsigned long end_pfn,
int isol_flags)
{
@@ -289,6 +373,12 @@ int test_pages_isolated(unsigned long start_pfn, unsigned long end_pfn,
* are not aligned to pageblock_nr_pages.
* Then we just check migratetype first.
*/
+/*
+ * IAMROOT, 2022.07.09:
+ * - papago
+ * pageblock_nr_pages != MAX_ORDER. 그런 다음 사용 가능한 페이지 청크가
+ * pageblock_nr_pages에 정렬되지 않습니다. 그런 다음 먼저 migratetype을 확인합니다.
+ */
for (pfn = start_pfn; pfn < end_pfn; pfn += pageblock_nr_pages) {
page = __first_valid_page(pfn, pageblock_nr_pages);
if (page && !is_migrate_isolate_page(page))
diff --git a/mm/vmscan.c b/mm/vmscan.c
index b9e511ee2594..20265b0a24bb 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -1842,7 +1842,7 @@ static unsigned int shrink_page_list(struct list_head *page_list,
if (!PageSwapCache(page)) {
/*
* IAMROOT, 2022.05.04:
- * - swap요청이 없다. kepp.
+ * - swap요청이 없다. keep.
*/
if (!(sc->gfp_mask & __GFP_IO))
goto keep_locked;
@@ -2012,7 +2012,7 @@ static unsigned int shrink_page_list(struct list_head *page_list,
SetPageReclaim(page);
goto activate_locked;
- }
+ }
if (references == PAGEREF_RECLAIM_CLEAN)
goto keep_locked;
@@ -2225,6 +2225,11 @@ static unsigned int shrink_page_list(struct list_head *page_list,
return nr_reclaimed;
}
+/*
+ * IAMROOT, 2022.07.09:
+ * - 즉시 reclaim이 가능한 page들을 @page_list에서 찾아서 reclaim을 시도한다.
+ * reclaim못한 page들은 @page_list에 남아있다.
+ */
unsigned int reclaim_clean_pages_from_list(struct zone *zone,
struct list_head *page_list)
{
@@ -2238,6 +2243,16 @@ unsigned int reclaim_clean_pages_from_list(struct zone *zone,
LIST_HEAD(clean_pages);
unsigned int noreclaim_flag;
+/*
+ * IAMROOT, 2022.07.09:
+ * - !PageHuge : huge page가 아님
+ * page_is_file_lru : clean anon page or file lru
+ * !PageDirty : clean.
+ * !__PageMovable : non-lru-movable이 아님.
+ * !PageUnevictable : evictable
+ * - clean anon page or non dirty file cache 인 경우.
+ * - 특별한걸 안한 page라 바로 buddy로 넣을수있는 상태인지 확인.
+ */
list_for_each_entry_safe(page, next, page_list, lru) {
if (!PageHuge(page) && page_is_file_lru(page) &&
!PageDirty(page) && !__PageMovable(page) &&
@@ -2254,10 +2269,19 @@ unsigned int reclaim_clean_pages_from_list(struct zone *zone,
* change in the future.
*/
noreclaim_flag = memalloc_noreclaim_save();
+
+/*
+ * IAMROOT, 2022.07.09:
+ * - clean_pages에 잇는 page들을 reclaim 한다.
+ */
nr_reclaimed = shrink_page_list(&clean_pages, zone->zone_pgdat, &sc,
&stat, true);
memalloc_noreclaim_restore(noreclaim_flag);
+/*
+ * IAMROOT, 2022.07.09:
+ * - relcaim에 실패하고 남은 page들은 page_list에 옮긴다.
+ */
list_splice(&clean_pages, page_list);
mod_node_page_state(zone->zone_pgdat, NR_ISOLATED_FILE,
-(long)nr_reclaimed);
댓글 0
번호 | 제목 | 글쓴이 | 날짜 | 조회 수 |
---|---|---|---|---|
공지 | [공지] 스터디 정리 노트 공간입니다. | woos | 2016.05.14 | 627 |
148 | [커널 17차] 103주차 | ㅇㅇㅇ | 2022.08.28 | 35 |
147 | [커널 18차] 66주차 | kkr | 2022.08.27 | 76 |
146 | [커널 17차] 101~102주차 | ㅇㅇㅇ | 2022.08.21 | 47 |
145 | [커널 18차] 65주차 | kkr | 2022.08.20 | 28 |
144 | [커널 18차] 64주차 | kkr | 2022.08.13 | 75 |
143 | [커널 17차] 100주차 [1] | ㅇㅇㅇ | 2022.08.06 | 100 |
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 | 113 |
137 | [커널 18차] 60주차 | kkr | 2022.07.16 | 129 |
136 | [커널 17차] 95~96주차 | ㅇㅇㅇ | 2022.07.10 | 105 |
» | [커널 18차] 59주차 | kkr | 2022.07.09 | 126 |
134 | [커널 19차] 8주차 | kanlee | 2022.07.02 | 160 |
133 | [커널 19차] 7주차 | kanlee | 2022.07.02 | 96 |
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 |
.