๐ ํ์ด์ง Migration
๊ด๋ จ ์์ค: mm/migrate.c (2750์ค), mm/migrate_device.c (1491์ค)
๊ด๋ จ ๋ฌธ์: ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ ๊ฐ์ ยท Compaction ยท CMA ยท NUMA ยท HMM ยท Hotplug
๊ฐ์ (Overview)
ํ์ด์ง Migration์ ๋ฆฌ๋ ์ค ์ปค๋์ด ์คํ ์ค์ธ ํ๋ก์ธ์ค์ ํ์ด์ง๋ฅผ ๋ฌผ๋ฆฌ์ ์ผ๋ก ๋ค๋ฅธ ์์น๋ก ์ด๋์ํค๋ ๋ฉ์ปค๋์ฆ์ ๋๋ค. ์ด๋ Memory Compaction(๋จํธํ ํด์), NUMA ๋ฐธ๋ฐ์ฑ(๋ ธ๋ ๊ฐ ์ด๋), CMA(์ฐ์ ๋ฉ๋ชจ๋ฆฌ ํ๋ณด), ๋ฉ๋ชจ๋ฆฌ ํซํ๋ฌ๊ทธ(์จ๋ผ์ธ/์คํ๋ผ์ธ), HMM(์ด๊ธฐ์ข ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ) ๋ฑ ์ฌ๋ฌ ์๋ธ์์คํ ์์ ํต์ฌ ๋น๋ฉ ๋ธ๋ก์ผ๋ก ์ฌ์ฉ๋ฉ๋๋ค. ์๋ณธ ํ์ด์ง์ ๋ชจ๋ ๋งคํ(PTE)์ migration swap entry๋ก ๊ต์ฒดํ ๋ค, ์ ํ์ด์ง๋ก ๋ฐ์ดํฐ๋ฅผ ๋ณต์ฌํ๊ณ ๋งคํ์ ๋ณต์ํ๋ 3๋จ๊ณ ํ๋ก์ธ์ค๋ก ๋์ํฉ๋๋ค.
Migration์ ํต์ฌ ์์ด๋์ด๋ "ํ์ด์ง๊ฐ ์ด๋๋๋ ๋์ ํ๋ก์ธ์ค๊ฐ ์ ๊ทผํ๋ฉด ๋๊ธฐํ๊ฒ ๋ง๋๋ ๊ฒ"์
๋๋ค. PTE์ migration entry๋ฅผ ์ฝ์
ํ๋ฉด, ์ ๊ทผ ์ ํดํธ๊ฐ ๋ฐ์ํ๊ณ migration_entry_wait()๊ฐ ์๋ฃ๋ ๋๊น์ง ๋ธ๋ก๋ฉ๋๋ค. ์ด๋ฅผ ํตํด ๋ฌด๊ฒฐ์ฑ์ ๋ณด์ฅํ๋ฉด์ ๋ฌผ๋ฆฌ ๋ฉ๋ชจ๋ฆฌ ๋ด์์ ํ์ด์ง๋ฅผ ํฌ๋ช
ํ๊ฒ ์ด๋ํ ์ ์์ต๋๋ค.
๋์๊ด์ผ๋ก ๋น์ ํ๋ฉด, ์ฑ ์ ๋ค๋ฅธ ์๊ฐ๋ก ์ฎ๊ธฐ๋ ๋์ ์์ ์์ฝํ๋ฅผ ๋ถ์ฌ ๋๊ณ , ๋ค์ ๊ฝํ๊ธฐ ์ ๊น์ง๋ ๋์ถ ์์ฒญ์ ์ ๊น ๋ฉ์ถ๊ฒ ํ๋ ๋ฐฉ์๊ณผ ๋น์ทํฉ๋๋ค.
์์ค ํ์ผ:
mm/migrate.c โ ํต์ฌ ๋ง์ด๊ทธ๋ ์ด์
์์ง (2750์ค)
mm/migrate_device.c โ ๋๋ฐ์ด์ค ๋ฉ๋ชจ๋ฆฌ ๋ง์ด๊ทธ๋ ์ด์
(1491์ค)
include/linux/migrate.h โ ์ธ๋ถ API, struct movable_operations, migrate_vma
include/linux/migrate_mode.h โ enum migrate_mode, enum migrate_reason
๋น ๋ฅธ ์ ๊ฒ ๋ช ๋ น
# ๋ง์ด๊ทธ๋ ์ด์
ํต๊ณ ํ์ธ
cat /proc/vmstat | grep -E 'pgmigrate|thp_migration|numa_pages_migrated'
# NUMA ๋ฐธ๋ฐ์ฑ ํ์ฑํ ์ํ ํ์ธ
cat /proc/sys/kernel/numa_balancing
# ํ์ฌ NUMA ์ ์ฑ
๊ณผ ๋
ธ๋ ๋ฐฐ์น ํ์ธ
numactl --show
numastat -p $$
# ๋ฉ๋ชจ๋ฆฌ ํซํ๋ฌ๊ทธ ๋ธ๋ก ์ํ ํ์ธ
cat /sys/devices/system/memory/auto_online_blocks 2>/dev/null
ls /sys/devices/system/memory/ | grep memory | head -5
# Compaction๊ณผ ํจ๊ป ๋ง์ด๊ทธ๋ ์ด์
๋์ ๊ด์ฐฐ
cat /proc/vmstat | grep -E 'compact_stall|compact_success|compact_fail'
cat /proc/buddyinfo | head -4
# ํ์ด์ง ํดํธ ๊ธฐ๋ฐ NUMA ์ด๋ฒคํธ ํ์ธ
cat /proc/vmstat | grep numa_hit
# NUMA ํ ํด๋ก์ง์ ๋
ธ๋ ๋ฉ๋ชจ๋ฆฌ ๋ถํฌ ํ์ธ
numactl -H
cat /proc/zoneinfo | grep -E 'Node|zone|present|managed|spanned' | head -40
# ๋ง์ด๊ทธ๋ ์ด์
๊ด๋ จ ์ปค๋ ํธ๋ ์ด์ค (root ๊ถํ)
sudo perf trace -e 'migrate:*' --duration 10 2>/dev/null || true
# CMA ์์ญ ์ ๋ณด ํ์ธ
cat /proc/meminfo | grep Cma
# ๋ฉ๋ชจ๋ฆฌ ์๋ฐ๊ณผ ํ์ ๊ฐ๋ ํ์ธ
cat /proc/pressure/memory
cat /proc/vmstat | grep -E 'allocstall|pgscan|pgsteal'
# ํซํ๋ฌ๊ทธ/์ด๊ธฐ์ข
๋ฉ๋ชจ๋ฆฌ ๊ด๋ จ ๋ฉ์์ง ํ์ธ
dmesg | grep -Ei 'migrate|numa|hotplug|cxl' | tail -20
ํต์ฌ ์๋ฃ๊ตฌ์กฐ
movable_operations โ ๋๋ผ์ด๋ฒ ์์ค ํ์ด์ง ์ด๋ ์ธํฐํ์ด์ค
balloon, zsmalloc, hotplug ๊ฐ์ ์ด๋ ๊ฐ๋ฅํ ํ์ด์ง ์๋น์๊ฐ ์ฐ๋ ์ฝ๋ฐฑ ์ธํฐํ์ด์ค์ ๋๋ค. LRU์ ์ง์ ์ฌ๋ผ๊ฐ์ง ์๋ ํ์ด์ง๋ ๋๋ผ์ด๋ฒ๊ฐ ๋ค์ ๋ฐ์ ์ฃผ๊ณ , ์ด๋์ด ๋๋๋ฉด ์๋ ์๋ฃ๊ตฌ์กฐ๋ก ๋๋๋ฆด ์ ์๊ฒ ํฉ๋๋ค.
/* include/linux/migrate.h:44-49 */
struct movable_operations {
bool (*isolate_page)(struct page *, isolate_mode_t);
int (*migrate_page)(struct page *dst, struct page *src,
enum migrate_mode);
void (*putback_page)(struct page *);
};
migrate_vma โ ๋๋ฐ์ด์ค ๋ฉ๋ชจ๋ฆฌ ๋ง์ด๊ทธ๋ ์ด์ ์ปจํ ์คํธ
GPU/๊ฐ์๊ธฐ ๋ฑ ๋๋ฐ์ด์ค ๋ฉ๋ชจ๋ฆฌ์ ์์คํ
๋ฉ๋ชจ๋ฆฌ ๊ฐ ํ์ด์ง ์ด๋์ ์ฌ์ฉ๋ฉ๋๋ค. src[]์ dst[] ๋ฐฐ์ด์ MIGRATE_PFN_* ํ๋๊ทธ์ PFN์ ์ธ์ฝ๋ฉํ์ฌ ๊ฐ ๊ฐ์ ์ฃผ์์ ํ์ด์ง ์ํ๋ฅผ ํํํฉ๋๋ค.
src[]์ dst[]๋ (end - start) >> PAGE_SHIFT ๊ฐ์๋งํผ ์ค๋น๋์ด์ผ ํ๋ฉฐ, migrate_vma_setup() ์ดํ์๋ src[]๋ฅผ ๊ฑด๋๋ฆฌ๋ฉด ์ ๋ฉ๋๋ค. migrate_vma_pages()๊ฐ ๋๋ ๋ค์๋ dst[]๋ ๋ ์ด์ ๋ฐ๊พธ์ง ์์์ผ ํ๊ณ , fault_page๋ migrate_to_ram() ํ๋ฆ์์ ๋๋ฐ์ด์ค ์ฌ์ค ํ์ด์ง๋ฅผ RAM์ผ๋ก ๋๋๋ฆด ๋ ์ฐ์
๋๋ค.
/* include/linux/migrate.h:158-191 */
struct migrate_vma {
struct vm_area_struct *vma;
/*
* src์ dst ๋ฐฐ์ด์
* (end - start) >> PAGE_SHIFT ๊ฐ์๋งํผ ์ถฉ๋ถํ ์ปค์ผ ํ๋ค.
*
* ํธ์ถ์๋ migrate_vma_setup() ์ดํ src ๋ฐฐ์ด์ ์์ ํ๋ฉด ์ ๋๊ณ ,
* migrate_vma_pages()๊ฐ ๋ฐํ๋ ๋ค์๋ dst ๋ฐฐ์ด๋ ๋ฐ๊พธ๋ฉด ์ ๋๋ค.
*/
unsigned long *dst;
unsigned long *src;
unsigned long cpages;
unsigned long npages;
unsigned long start;
unsigned long end;
/*
* device private memory์์ ์ฎ๊ธธ ๋ page_pgmap(page)->owner์
* ๋ค์ด ์๋ ์์ ์ ๊ฐ๊ณผ ๋ง์ถฐ ๋๋ ํ๋๋ค. ์ด ๊ฒฝ์ฐ flags๋
* MIGRATE_VMA_SELECT_DEVICE_PRIVATE๋ก ์ค์ ํด์ผ ํ๋ค.
* ํธ์ถ์๊ฐ mmu notifier ์ฝ๋ฐฑ์ ์ฌ์ฉํ ๋๋, ์ฎ๊ธฐ์ง ์์
* device private ํ์ด์ง์ ๋ํ device MMU invalidation์ ํผํ๋ ค๊ณ
* ์ด ๊ฐ์ ํญ์ ์ฑ์์ผ ํ๋ค.
*/
void *pgmap_owner;
unsigned long flags;
/*
* migrate_to_ram() ์ฝ๋ฐฑ์ ์ผ๋ถ๋ก ํ์ด์ง๋ฅผ ์ฎ๊ธธ ๋ vmf->page๋ฅผ ๋ฃ๋๋ค.
*/
struct page *fault_page;
};
migrate_pages_stats โ ๋ง์ด๊ทธ๋ ์ด์ ๊ฒฐ๊ณผ ํต๊ณ
๋ฐฐ์น ๋ง์ด๊ทธ๋ ์ด์
์ค ๋ฐ์ํ๋ ์ฑ๊ณต/์คํจ/THP ๋ถํ ํต๊ณ๋ฅผ ์ถ์ ํฉ๋๋ค. migrate_pages() ํจ์ ์ข
๋ฃ ํ vmstat ์นด์ดํฐ์ ๋ฐ์๋ฉ๋๋ค.
/* mm/migrate.c:1592-1601 */
struct migrate_pages_stats {
int nr_succeeded; /* base page ๋จ์๋ก ์ฑ๊ณตํ ์ผ๋ฐ/๋ํ folio ์ */
int nr_failed_pages; /* base page ๋จ์๋ก ์คํจํ ์ผ๋ฐ/๋ํ folio ์.
์๋ํ์ง ์์ folio๋ ์ ์ธ */
int nr_thp_succeeded; /* THP ์ฑ๊ณต ์ */
int nr_thp_failed; /* THP ์คํจ ์ */
int nr_thp_split; /* ๋ง์ด๊ทธ๋ ์ด์
์ ๋ถํ ๋ THP ์ */
int nr_split; /* THP๋ฅผ ํฌํจํ ๋ํ folio ๋ถํ ์ */
};
MIGRATE_PFN_* ํ๋๊ทธ โ src/dst ๋ฐฐ์ด ์ธ์ฝ๋ฉ
migrate_vma API์์ src[]์ dst[] ๋ฐฐ์ด์ ๊ฐ ์ํธ๋ฆฌ๋ PFN๊ณผ ํ๋๊ทธ๋ฅผ ๋นํธ ๋ง์คํนํ์ฌ ์ธ์ฝ๋ฉ๋ฉ๋๋ค. ๋นํธ 0-5๋ ํ๋๊ทธ, ๋นํธ 6 ์ด์์ PFN์
๋๋ค.
| ํ๋๊ทธ | ๋นํธ | ์๋ฏธ |
|---|---|---|
| `MIGRATE_PFN_VALID` | bit 0 | ์ ํจํ PFN ์ํธ๋ฆฌ |
| `MIGRATE_PFN_MIGRATE` | bit 1 | ๋ง์ด๊ทธ๋ ์ด์ ๋์์ผ๋ก ํ์ |
| `MIGRATE_PFN_WRITE` | bit 3 | ์ฐ๊ธฐ ๊ถํ์ด ์๋ ํ์ด์ง |
| `MIGRATE_PFN_COMPOUND` | bit 4 | ๋ณตํฉ(compound) ํ์ด์ง |
| `MIGRATE_PFN_SHIFT` | 6 | PFN ์์ ๋นํธ ์์น |
ํต์ฌ ํจ์
migrate_pages() โ ์ต์์ ๋ฐฐ์น ๋ง์ด๊ทธ๋ ์ด์ API
๋ง์ด๊ทธ๋ ์ด์ ์ ๋ฉ์ธ ์ง์ ์ ์ ๋๋ค. hugetlb ํ์ด์ง๋ฅผ ๋จผ์ ์ฒ๋ฆฌํ ๋ค, ๋๋จธ์ง folio๋ฅผ ๋ฐฐ์น(batch) ๋จ์๋ก ๋๋์ด ๋น๋๊ธฐ ๋๋ ๋๊ธฐ ๋ฐฉ์์ผ๋ก ๋ง์ด๊ทธ๋ ์ด์ ํฉ๋๋ค.
/* mm/migrate.c:2072-2074 */
int migrate_pages(struct list_head *from, new_folio_t get_new_folio,
free_folio_t put_new_folio, unsigned long private,
enum migrate_mode mode, int reason, unsigned int *ret_succeeded)
๋์ ํ๋ฆ:
1. migrate_hugetlbs()๋ก HugeTLB folio๋ฅผ ๋จผ์ ์ฒ๋ฆฌ
2. ๋จ์ folio๋ฅผ NR_MAX_BATCHED_MIGRATION(THP ์ฌ์ฉ ์ HPAGE_PMD_NR, ๊ทธ ์ธ 512) ๋จ์๋ก ๋ฐฐ์น ๋ถํ
3. MIGRATE_ASYNC์ด๋ฉด migrate_pages_batch(), ๊ทธ ์ธ์ด๋ฉด migrate_pages_sync()
4. ๋๊ธฐ ๋ชจ๋์์๋ ๋จผ์ ASYNC๋ก ์๋ํ ๋ค ์คํจ๋ถ์ ๊ฐ๋ณ ๋๊ธฐ ์ฒ๋ฆฌ
5. ๋ถํ ๋ split_folios๋ ASYNC ๋ชจ๋๋ก ํ ๋ฒ ๋ ์๋
6. count_vm_events()๋ก vmstat ์นด์ดํฐ ์
๋ฐ์ดํธ
migrate_folio_unmap() โ folio ๋งคํ ํด์ ๋จ๊ณ
์์ค folio์ ๋ชจ๋ PTE๋ฅผ migration entry๋ก ๊ต์ฒดํ๋ 1๋จ๊ณ ํจ์์
๋๋ค. ํ์ด์ง ์ ๊ธ, writeback ๋๊ธฐ, anon_vma ํ๋, try_to_migrate() ํธ์ถ์ด ํฌํจ๋ฉ๋๋ค.
/* mm/migrate.c:1203-1206 */
static int migrate_folio_unmap(new_folio_t get_new_folio,
free_folio_t put_new_folio, unsigned long private,
struct folio *src, struct folio **dstp, enum migrate_mode mode,
struct list_head *ret)
๋์ ํ๋ฆ:
1. get_new_folio()๋ก ๋์ folio ํ ๋น
2. ์์ค folio ์ ๊ธ (MIGRATE_ASYNC์์๋ trylock, ์คํจ ์ ๊ฑด๋๋)
3. writeback ์ค์ด๋ฉด MIGRATE_SYNC์์๋ง ๋๊ธฐ
4. ์ต๋ช
ํ์ด์ง์ด๋ฉด folio_get_anon_vma()๋ก anon_vma ์ฐธ์กฐ ํ๋
5. try_to_migrate()๋ก ๋ชจ๋ PTE๋ฅผ migration entry๋ก ๊ต์ฒด
6. ๋งคํ ํด์ ์ฑ๊ณต ์ __migrate_folio_record()๋ก ์ํ ์ ์ฅ ํ ๋ฐํ
migrate_folio_move() โ folio ์ด๋ ๋จ๊ณ
๋งคํ์ด ํด์ ๋ ์์ค folio๋ฅผ ๋์ folio๋ก ์ค์ ๋ก ์ด๋์ํค๋ 2๋จ๊ณ ํจ์์
๋๋ค. move_to_new_folio()๋ฅผ ํตํด address_space๋ฅผ ๊ต์ฒดํ๊ณ , ์ฑ๊ณต ์ remove_migration_ptes()๋ก ์ folio๋ฅผ ๋ค์ ๋งคํํฉ๋๋ค.
/* mm/migrate.c:1353-1356 */
static int migrate_folio_move(free_folio_t put_new_folio, unsigned long private,
struct folio *src, struct folio *dst,
enum migrate_mode mode, enum migrate_reason reason,
struct list_head *ret)
๋์ ํ๋ฆ:
1. __migrate_folio_extract()๋ก ์ด์ ์ํ ๋ณต์ ์ ๋ณด ์ถ์ถ
2. movable_ops ํ์ด์ง์ด๋ฉด migrate_movable_ops_page() ํธ์ถ
3. move_to_new_folio() โ mapping->a_ops->migrate_folio() ์ฝ๋ฐฑ ํธ์ถ
4. ์ฑ๊ณต ์ folio_add_lru(dst)๋ก ๋์ LRU ์ถ๊ฐ
5. ๋งคํ๋ ์ํ์์ผ๋ฉด remove_migration_ptes(src, dst)๋ก PTE ๋ณต์
6. ์์ค folio ํด์ ๋ฐ migrate_folio_done() ํธ์ถ
move_to_new_folio() โ address_space ๊ต์ฒด
์ค์ folio ๊ต์ฒด๋ฅผ ์ฒ๋ฆฌํ๋ ๋ด๋ถ ํจ์์ ๋๋ค. ๋งคํ ์ ํ(๋ฌด๋งคํ, inaccessible, filesystem, anonymous, fallback)์ ๋ฐ๋ผ ์ ์ ํ ๋ง์ด๊ทธ๋ ์ด์ ์ฝ๋ฐฑ์ ์ ํํฉ๋๋ค.
/* mm/migrate.c:1090-1092 */
static int move_to_new_folio(struct folio *dst, struct folio *src,
enum migrate_mode mode)
๋ถ๊ธฐ ๋ก์ง:
mapping == NULL โ migrate_folio() (๋จ์ ๋งคํ ์๋ folio)mapping_inaccessible(mapping) โ -EOPNOTSUPP (์ ๊ทผ ๋ถ๊ฐ ๋งคํ)mapping->a_ops->migrate_folio ์กด์ฌ โ filesystem/swap ์ฝ๋ฐฑ ํธ์ถfallback_migrate_folio() (writepages ๊ฒฝ๊ณ + ๊ฐ์ ํด์ )migrate_misplaced_folio() โ NUMA ๋ฐธ๋ฐ์ฑ์ฉ ๋จ์ผ folio ๋ง์ด๊ทธ๋ ์ด์
NUMA ๋ฐธ๋ฐ์ฑ์์ ์๋ชป ๋ฐฐ์น๋ ๋จ์ผ folio๋ฅผ ์ง์ ๋
ธ๋๋ก ์ด๋์ํต๋๋ค. migrate_misplaced_folio_prepare()๋ก ๊ฒฉ๋ฆฌ๋ folio๋ฅผ ๋ฐ์ migrate_pages()๋ฅผ ํธ์ถํฉ๋๋ค.
/* mm/migrate.c:2722-2723 */
int migrate_misplaced_folio(struct folio *folio, int node)
๋์ ํ๋ฆ:
1. folio๋ฅผ migratepages ๋ฆฌ์คํธ์ ์ถ๊ฐ
2. alloc_misplaced_dst_folio() ์ฝ๋ฐฑ์ผ๋ก ๋์ ๋
ธ๋์ ํ ๋น
3. MIGRATE_ASYNC + MR_NUMA_MISPLACED๋ก ๋ง์ด๊ทธ๋ ์ด์
์๋
4. ์คํจ ์ putback_movable_pages()๋ก ๋ณต์
5. ์ฑ๊ณต ์ NUMA_PAGE_MIGRATE vmstat ์นด์ดํฐ ์
๋ฐ์ดํธ
6. ํฐ์ด๋ง ๋ชจ๋์์ ์ ์โ๊ณ ์ ๋
ธ๋ ์ด๋ ์ PGPROMOTE_SUCCESS ๊ธฐ๋ก
migrate_vma_setup() / migrate_vma_pages() / migrate_vma_finalize() โ ๋๋ฐ์ด์ค ๊ฒฝ๋ก
migrate_vma_setup()์ VMA ์ ํจ์ฑ ๊ฒ์ฌ์ src[] ์์ง, migrate_vma_pages()๋ ๋๋ผ์ด๋ฒ๊ฐ ๋ณต์ฌํ ๋ค ํ์ด์ง ์ํ ๊ฐฑ์ , migrate_vma_finalize()๋ CPU ํ์ด์ง ํ
์ด๋ธ ๋ณต์์ ๋งก์ต๋๋ค.
/* include/linux/migrate.h:193-195 */
int migrate_vma_setup(struct migrate_vma *args);
void migrate_vma_pages(struct migrate_vma *migrate);
void migrate_vma_finalize(struct migrate_vma *migrate);
๋์ ํ๋ฆ:
1. migrate_vma_setup()์ด VMA, src[], dst[], fault_page๋ฅผ ๊ฒ์ฌํ๊ณ ํ์ด์ง๋ฅผ ์ ๊ทผ ๋ค ์ธ๋งคํ
2. ๋๋ผ์ด๋ฒ๊ฐ dst[]๋ฅผ ๊ธฐ์ค์ผ๋ก ๋๋ฐ์ด์ค ๋ฉ๋ชจ๋ฆฌ๋ฅผ ํ ๋นํ๊ณ ๋ฐ์ดํฐ๋ฅผ ๋ณต์ฌ
3. migrate_vma_pages()๊ฐ ์ฑ๊ณตํ PFN์ MIGRATE_PFN_MIGRATE๋ฅผ ๋จ๊น
4. migrate_vma_finalize()๊ฐ CPU ํ์ด์ง ํ
์ด๋ธ์ ์ ํ์ด์ง ๋๋ ์๋ ํ์ด์ง๋ก ์ ๋ฆฌ
๊ตฌํ์ migrate_vma_collect_pmd()๊ฐ PMD/PTE๋ฅผ ํ์ด src[]๋ฅผ ์ฑ์ฐ๊ณ , migrate_device_unmap()์ด ์ฅ์น ์ฌ์ค ํ์ด์ง๋ฅผ ๋ผ์ด๋ธ ๋ค migrate_device_pages()์ migrate_device_finalize()๊ฐ ๋ฉํ๋ฐ์ดํฐ์ PTE๋ฅผ ๋ง๋ฌด๋ฆฌํฉ๋๋ค.
ํธ์ถ ํ๋ฆ
migrate_pages() โ ์ต์์ API
โโโ migrate_hugetlbs() โ HugeTLB ๋จผ์ ์ฒ๋ฆฌ
โ โโโ unmap_and_move_huge_page()
โ โโโ get_new_folio() โ ๋์ ํ ๋น
โ โโโ try_to_migrate() โ PTE โ migration entry
โ โโโ move_to_new_folio() โ ์ค์ ์ด๋
โโโ migrate_pages_batch() โ ์ผ๋ฐ folio ๋ฐฐ์น ์ฒ๋ฆฌ
โ โโโ [pass 1] unmapping ๋จ๊ณ
โ โ โโโ try_split_folio() โ THP ๋ถํ ํ์ ์
โ โ โโโ migrate_folio_unmap() โ PTE ๊ต์ฒด
โ โ โ โโโ get_new_folio()
โ โ โ โโโ try_to_migrate()
โ โ โ โโโ __migrate_folio_record()
โ โ โโโ unmap_folios/dst_folios ๋ฆฌ์คํธ ๊ตฌ์ถ
โ โโโ [pass 2] moving ๋จ๊ณ
โ โโโ migrate_folios_move()
โ โโโ migrate_folio_move()
โ โโโ move_to_new_folio() โ ๋งคํ ๊ต์ฒด
โ โโโ folio_add_lru() โ ๋์ LRU ์ถ๊ฐ
โ โโโ remove_migration_ptes() โ PTE ๋ณต์
โโโ migrate_pages_sync() โ ๋๊ธฐ ๋ชจ๋ ์
โโโ migrate_pages_batch(ASYNC) โ ๋จผ์ ASYNC๋ก ์๋
โโโ ๊ฐ๋ณ ๋๊ธฐ ์ฒ๋ฆฌ (๋จ์ ์คํจ๋ถ)
migrate_vma_setup() โ ๋๋ฐ์ด์ค ๋ง์ด๊ทธ๋ ์ด์
์ง์
โโโ migrate_vma_collect() โ ํ์ด์ง ํ
์ด๋ธ ์ํฌ
โ โโโ walk_page_range(migrate_vma_walk_ops)
โ โโโ migrate_vma_collect_pmd()
โ โโโ migrate_vma_collect_huge_pmd()
โ โโโ [PTE ์ํ] โ src[] ๋ฐฐ์ด ์ฑ์ฐ๊ธฐ
โโโ migrate_vma_unmap() โ ๋งคํ ํด์
โโโ migrate_device_unmap()
โโโ folio_isolate_lru()
โโโ try_to_migrate()
์กฐ๊ฑด๋ณ ๋น๊ต
๋ง์ด๊ทธ๋ ์ด์ ๋ชจ๋ ๋น๊ต
| ๋ชจ๋ | ๋์ ๋ฐฉ์ | ์ ๊ธ ๋ธ๋ก | writeback ๋๊ธฐ | ์ฌ์ฉ ์์ |
|---|---|---|---|---|
| `MIGRATE_ASYNC` | ์ ๋ ๋ธ๋กํ์ง ์์ | trylock๋ง ์ฌ์ฉ | ๋๊ธฐ ์ ํจ | Compaction, proactive |
| `MIGRATE_SYNC_LIGHT` | ๋๋ถ๋ถ์ ์ ๊ธ์์ ๋ธ๋ก ๊ฐ๋ฅ | lock ํ์ฉ | uptodata ์๋ ๊ฒฝ์ฐ๋ง | NUMA ๋ฐธ๋ฐ์ฑ |
| `MIGRATE_SYNC` | ๋ชจ๋ ์ ๊ธ์์ ๋ธ๋ก | lock ํ์ฉ | ๋๊ธฐ | move_pages ์์คํ ์ฝ |
๋ง์ด๊ทธ๋ ์ด์ ์ฌ์ (migrate_reason) ๋น๊ต
| ์ฌ์ | ์์ | ํธ๋ฆฌ๊ฑฐ |
|---|---|---|
| Compaction | `MR_COMPACTION` | ๋จํธํ ํด์๋ฅผ ์ํ kcompactd/direct compaction |
| Memory Failure | `MR_MEMORY_FAILURE` | ํ๋์จ์ด ๋ฉ๋ชจ๋ฆฌ ์ค๋ฅ (ECC ์์ ๋ถ๊ฐ) |
| Memory Hotplug | `MR_MEMORY_HOTPLUG` | ๋ฉ๋ชจ๋ฆฌ ๋ธ๋ก ์คํ๋ผ์ธ |
| Syscall | `MR_SYSCALL` | `move_pages()` ์์คํ ์ฝ |
| mbind | `MR_MEMPOLICY_MBIND` | `mbind()`๋ก NUMA ์ ์ฑ ๋ณ๊ฒฝ ์ |
| NUMA Misplaced | `MR_NUMA_MISPLACED` | AutoNUMA๊ฐ ์๋ชป ๋ฐฐ์น๋ ํ์ด์ง ๊ฐ์ง |
| Contig Range | `MR_CONTIG_RANGE` | ์ฐ์ ๋ฒ์ ํ ๋น (CMA ๋ฑ) |
| Long-term Pin | `MR_LONGTERM_PIN` | VFIO/์ฅ์น ๋๋ผ์ด๋ฒ์ ์ฅ๊ธฐ ํning |
| Demotion | `MR_DEMOTION` | ๋ฉ๋ชจ๋ฆฌ ํฐ์ด๋ง์์ ๊ณ ์โ์ ์ ํํฅ |
| DAMON | `MR_DAMON` | DAMON ๊ธฐ๋ฐ ์ ๊ทผ ํจํด ๋ถ์ |
๋๋ฐ์ด์ค ๋ง์ด๊ทธ๋ ์ด์ vs ์ผ๋ฐ ๋ง์ด๊ทธ๋ ์ด์ ๋น๊ต
| ํญ๋ชฉ | ์ผ๋ฐ ๋ง์ด๊ทธ๋ ์ด์ (migrate.c) | ๋๋ฐ์ด์ค ๋ง์ด๊ทธ๋ ์ด์ (migrate_device.c) |
|---|---|---|
| ์ง์ ๋ฐฉ์ | `migrate_pages()` + `migrate_reason` | `migrate_vma_setup()` โ `migrate_vma_pages()` โ `migrate_vma_finalize()` |
| ๋์ | LRU์ ์๋ ์ผ๋ฐ folio | ZONE_DEVICE folio (GPU/HBM) |
| ๊ฒฉ๋ฆฌ | `folio_isolate_lru()` | `folio_get()`์ผ๋ก ๊ณ ์ (LRU ์์) |
| ๋งคํ ํด์ | `try_to_migrate()` + rmap walk | `try_to_migrate()` + mm_walk |
| ์ฝ๋ฐฑ | `mapping->a_ops->migrate_folio()` | ๋๋ผ์ด๋ฒ๊ฐ dst ํ ๋น + ๋ณต์ฌ |
| API | `migrate_pages()` | `migrate_vma_setup/pages/finalize()` |
| THP ์ฒ๋ฆฌ | ๋ฐฐ์น ๋ด ๋ถํ ์ง์ | `migrate_vma_split_folio()` |
| ๊ฒฐ๊ณผ ํ์ธ | ๋ฐํ๊ฐ + ret_succeeded | `src[]` ๋ฐฐ์ด์ MIGRATE_PFN_MIGRATE ํ๋๊ทธ |
์คํจ ์ ์ฒ๋ฆฌ ๋น๊ต
| ๋ฐํ๊ฐ | ์๋ฏธ | ์ฒ๋ฆฌ ๋ฐฉ๋ฒ |
|---|---|---|
| 0 | ์ฑ๊ณต | src folio ํด์ , dst LRU ์ถ๊ฐ |
| `-EAGAIN` | ์ผ์์ ์คํจ | ๋ฆฌ์คํธ์ ์ ์ง, ์ฌ์๋ |
| `-ENOMEM` | ๋ฉ๋ชจ๋ฆฌ ๋ถ์กฑ | ๋จ์ ์ฒ๋ฆฌ ์ค๋จ, ์คํจ ๋ชฉ๋ก์ผ๋ก ์ด๋ |
| `-EBUSY` | ์๊ตฌ ์คํจ | ์คํจ ๋ชฉ๋ก์ผ๋ก ์ด๋, ์ฌ์๋ ์ ํจ |
| `-EOPNOTSUPP` | ๋ฏธ์ง์ ๋งคํ | inaccessible ๋งคํ |