[커널 17차] 73주차

2022.01.23 02:15

ㅇㅇㅇ 조회 수:73

5.9 —> 5.15 변경 사항 논의 : memmap_init() 함수
- 원래는 node, zone 별로 루프를 돌던 것을 memblock 순서로 메모리 주소 순으로 돌도록 변경
- 이로써 원래 존재했던 overwrite 문제를 해결함
- https://github.com/torvalds/linux/commit/122e093c1734361dedb64f65c99b93e28e4624f4
- https://lkml.org/lkml/2021/6/24/961
- https://bugzilla.kernel.org/show_bug.cgi?id=213073

 

free_pages_prepare()
- page_cpupid_reset_last() 부터 진행
- 함수 page_cpupid_reset_last()로 해당 페이지의 last cpu id 정보를 all F로 reset한다
- 현재 페이지의 flag를 hwpoison flag를 제외하고 모두 클리어한다
- 함수 reset_page_owner()로 현재 페이지 owner bit를 클리어한다
- 페이지가 highmem 페이지가 아니면 CONFIG_LOCKDEP/CONFIG_DEBUG_OBJECTS_FREE 옵션에 따라 디버그를 위한 자료구조 처리를 수행한다. 현재는 옵션이 꺼져 있다
- 함수 kernel_poison_pages()로 현재 페이지에서 order 만큼 poisoning을 수행한다
- Kasan을 쓰지 않는 경우, init on free를 쓰는 지 보고, 쓰면 함수 kernel_init_free_pages()를 이용해서 현재 페이지들을 zeroing을 수행한다. 그리고 skip_kasan_poison이 0이면 함수 kasan_poison_pages()로 poison 작업을 수행한다
- arch_free_page() 함수는 빈 함수이다
- CONFIG_DEBUG_PAGEALLOC = n이므로 debug_pagealloc_unmap_pages()는 빈 함수이다

 

last cpu id flag
- 해당 페이지를 사용한 마지막 cpu의 id 및 pid를 저장한다
- NUMA 밸런싱을 위해서 사용된다
- http://jake.dothome.co.kr/mem_map/
- cpu id는 cpu_nr bit 만큼 사용되나 pid 표현은 8bit로 정해지는데 이는 hashing을 사용해서 그런 것으로 보인다
- https://github.com/torvalds/linux/commit/b795854b1fa70f6aee923ae5df74ff7afeaddcaa
- https://github.com/torvalds/linux/commit/1ae71d03194ea7424cbd14e449581f67c463d20d

 

__free_pages_ok()
- free_pages_prepare() 이후부터 계속
- 함수 get_pfnblock_migratetype()로 현재 페이지의 migrate type을 구한다
- zone spinlock을 건다
- 만약 현재 페이지가 속한 zone에 isolate page block이 존재하거나 현재 페이지의 migrate type이 MIGRATE_ISOLATE이면 다시 함수 get_pfnblock_migratetype()로 현재 페이지의 migrate type을 구한다

 

—> commit ad53f92eb416d81e469fa8ea57153e59455e7175 : https://lkml.org/lkml/2014/11/14/97
—> racing condition이 있어서 이를 보완하기 위해 현재와 같이 2번 읽는 구조가 되었다
- 관련 패치들
- https://github.com/torvalds/linux/commit/56f0e661ea8c0178e80048df7166653a51ef2c3d
- https://github.com/torvalds/linux/commit/cfc47a2803db42140167b92d991ef04018e162c7
- https://github.com/torvalds/linux/commit/ad53f92eb416d
- https://github.com/torvalds/linux/commit/28f836b6777b6f42dce068a40d83a891deaaca37

 

- 함수 __free_one_page()로 페이지 free를 수행한다
- zone spinlock을 푼다
- __count_vm_events() 함수로 vm event 관련 처리를 수행한다


Buddy system 이론 학습
- http://jake.dothome.co.kr/zonned-allocator-alloc-pages-fastpath/

 

__free_one_page()
- 인자로 page, pfn, zone, order, migrate type, fpi flag를 받는다
- 함수 task_capc()로 현재 zone의 capture_control을 받아온다. Compaction과 관련된 것이나 현재는 NULL이 리턴된다
- 현재 설정으로 MAX_ORDER = 11이고, huge page table이 사용되며 page block order = 9이다
- zone의 초기화 여부, page의 플래그 체크를 수행한다
- migratetype이 -1이 아님을 체크한다
- migratetype이 isolation type이 아니면 함수 __mod_zone_freepage_state()로 zone별 per_cpu_zonestate의 vm_stat_diff[NR_FREE_PAGES]에 1 << order 만큼의 값을 더해준다
- 값이 threshold 이상이 되면 percpu 값을 global 변수에 업데이트해준다
- 이미 spinlock을 잡고 들어왔기 때문에 IRQ disable된 상태이며 따라서 추가 protection은 필요없다
- 단 config가 Real Time인 경우에는 preempt_disable() preempt_enable()로 보호한다
- 만약 migratetype이 CMA이면 vm_stat_diff[NR_FREE_CMA_PAGES]에도 1 << order 만큼의 값을 더해준다
- pfn이 order 만큼의 align이 되어 있는지 체크한다
- page가 zone boundary 내에 존재하는지 체크한다
- page의 zone 설정이 인자로 받은 zone과 일치하는지 확인한다

XE Login