.. include:: ../disclaimer-zh_CN.rst :Original: Documentation/mm/page_migration.rst :翻译: å¸å»¶è…¾ Yanteng Si <siyanteng@loongson.cn> :æ ¡è¯‘: ======== 页é¢è¿ç§» ======== 页é¢è¿ç§»å…许在进程è¿è¡Œæ—¶åœ¨NUMA系统的节点之间移动页é¢çš„物ç†ä½ç½®ã€‚è¿™æ„味ç€è¿›ç¨‹æ‰€çœ‹åˆ°çš„虚拟地 å€å¹¶æ²¡æœ‰æ”¹å˜ã€‚ç„¶è€Œï¼Œç³»ç»Ÿä¼šé‡æ–°å®‰æŽ’这些页é¢çš„物ç†ä½ç½®ã€‚ 也å¯ä»¥å‚è§ :ref: `<异构内å˜ç®¡ç† (HMM)>` 以了解将页é¢è¿ç§»åˆ°è®¾å¤‡ç§æœ‰å†…å˜æˆ–ä»Žè®¾å¤‡ç§æœ‰å†…å˜ä¸è¿ç§»ã€‚ 页é¢è¿ç§»çš„主è¦ç›®çš„æ˜¯é€šè¿‡å°†é¡µé¢ç§»åˆ°è®¿é—®è¯¥å†…å˜çš„进程所è¿è¡Œçš„处ç†å™¨é™„è¿‘æ¥å‡å°‘内å˜è®¿é—®çš„延迟。 页é¢è¿ç§»å…许进程通过MF_MOVEå’ŒMF_MOVE_ALLé€‰é¡¹æ‰‹åŠ¨é‡æ–°å®šä½å…¶é¡µé¢æ‰€åœ¨çš„èŠ‚ç‚¹ï¼ŒåŒæ—¶é€šè¿‡ mbind()设置一个新的内å˜ç–略。一个进程的页é¢ä¹Ÿå¯ä»¥é€šè¿‡sys_migrate_pages()å‡½æ•°è°ƒç”¨ä»Žå¦ ä¸€ä¸ªè¿›ç¨‹é‡æ–°å®šä½ã€‚migrate_pages()函数调用接收两组节点,并将一个进程ä½äºŽæ—§èŠ‚ç‚¹ä¸Šçš„é¡µé¢ç§» åŠ¨åˆ°ç›®æ ‡èŠ‚ç‚¹ä¸Šã€‚é¡µé¢è¿ç§»åŠŸèƒ½ç”±Andi Kleençš„numactl包æä¾›(需è¦0.9.3以上的版本,其仓库 地å€https://github.com/numactl/numactl.git)。numactlæä¾›äº†libnuma,它为页é¢è¿ç§» æä¾›äº†ä¸Žå…¶ä»–NUMA功能类似的接å£ã€‚执行 cat ``/proc/<pid>/numa_maps`` å…è®¸è½»æ¾æŸ¥çœ‹è¿› 程的页é¢ä½ç½®ã€‚å‚è§proc(5)手册ä¸çš„numa_maps文档。 如果调度程åºå°†ä¸€ä¸ªè¿›ç¨‹é‡æ–°å®‰ç½®åˆ°ä¸€ä¸ªé¥è¿œçš„节点上的处ç†å™¨ï¼Œæ‰‹åЍè¿ç§»æ˜¯å¾ˆæœ‰ç”¨çš„。批é‡è°ƒåº¦ç¨‹åº 或管ç†å‘˜å¯ä»¥æ£€æµ‹åˆ°è¿™ç§æƒ…况,并将进程的页é¢ç§»åˆ°æ–°å¤„ç†å™¨é™„è¿‘ã€‚å†…æ ¸æœ¬èº«åªæä¾›æ‰‹åŠ¨çš„é¡µè¿ç§»æ”¯æŒã€‚ 自动的页é¢è¿ç§»å¯ä»¥é€šè¿‡ç”¨æˆ·ç©ºé—´çš„è¿›ç¨‹ç§»åŠ¨é¡µé¢æ¥å®žçŽ°ã€‚ä¸€ä¸ªç‰¹æ®Šçš„å‡½æ•°è°ƒç”¨ "move_pages" å…许 在一个进程ä¸ç§»åЍå•个页é¢ã€‚例如,NUMA分æžå™¨å¯ä»¥èŽ·å¾—ä¸€ä¸ªæ˜¾ç¤ºé¢‘ç¹çš„节点外访问的日志,并å¯ä»¥ä½¿ 用这个结果将页é¢ç§»åŠ¨åˆ°æ›´æœ‰åˆ©çš„ä½ç½®ã€‚ 较大型的设备通常使用cpusets将系统分割æˆè‹¥å¹²ä¸ªèŠ‚ç‚¹ã€‚Paul Jackson为cpusetsé…备了当任务被 转移到å¦ä¸€ä¸ªcpuset时移动页é¢çš„能力(è§:ref:`CPUSETS <cpusets>`)。Cpusetså…许进程定 ä½çš„自动化。如果一个任务被移到一个新的cpuset上,那么它的所有页é¢ä¹Ÿä¼šéšä¹‹ç§»åŠ¨ï¼Œè¿™æ ·è¿›ç¨‹çš„ 性能就ä¸ä¼šæ€¥å‰§ä¸‹é™ã€‚如果cpusetå…许的内å˜èŠ‚ç‚¹å‘生å˜åŒ–,cpusetä¸çš„进程页也会被移动。 页é¢è¿ç§»å…许为所有è¿ç§»æŠ€æœ¯ä¿ç•™ä¸€ç»„节点ä¸é¡µé¢çš„相对ä½ç½®ï¼Œè¿™å°†ä¿ç•™ç”Ÿæˆçš„特定内å˜åˆ†é…模å¼å³ä½¿ 进程已被è¿ç§»ã€‚为了ä¿ç•™å†…å˜å»¶è¿Ÿï¼Œè¿™ä¸€ç‚¹æ˜¯å¿…è¦çš„。è¿ç§»åŽçš„进程将以类似的性能è¿è¡Œã€‚ 页é¢è¿ç§»åˆ†å‡ 个æ¥éª¤è¿›è¡Œã€‚é¦–å…ˆä¸ºé‚£äº›è¯•å›¾ä»Žå†…æ ¸ä¸ä½¿ç”¨migrate_pages()的进程åšä¸€ä¸ªé«˜å±‚次的 æè¿°ï¼ˆå¯¹äºŽç”¨æˆ·ç©ºé—´çš„使用,å¯ä»¥å‚è€ƒä¸Šé¢æåˆ°çš„Andi Kleençš„numactl包),然åŽå¯¹ä½Žæ°´å¹³çš„细 节工作åšä¸€ä¸ªä½Žæ°´å¹³æè¿°ã€‚ åœ¨å†…æ ¸ä¸ä½¿ç”¨ migrate_pages() ============================ 1. 从LRUä¸ç§»é™¤é¡µé¢ã€‚ è¦è¿ç§»çš„页é¢åˆ—表是通过扫æé¡µé¢å¹¶æŠŠå®ƒä»¬ç§»åˆ°åˆ—è¡¨ä¸æ¥ç”Ÿæˆçš„。这是通过调用 folio_isolate_lru() æ¥å®Œæˆçš„。调用folio_isolate_lru()å¢žåŠ äº†å¯¹è¯¥é¡µçš„å¼•ç”¨ï¼Œè¿™æ ·åœ¨é¡µé¢è¿ç§»å‘生时它就ä¸ä¼š 消失。它还å¯ä»¥é˜²æ¢äº¤æ¢å™¨æˆ–其他扫æå™¨é‡åˆ°è¯¥é¡µã€‚ 2. æˆ‘ä»¬éœ€è¦æœ‰ä¸€ä¸ªnew_folio_t类型的函数,å¯ä»¥ä¼ 递给migrate_pages()。这个函数应该计算 出如何在给定的旧页é¢ä¸åˆ†é…æ£ç¡®çš„æ–°é¡µé¢ã€‚ 3. migrate_pages()函数被调用,它试图进行è¿ç§»ã€‚它将调用该函数为æ¯ä¸ªè¢«è€ƒè™‘è¿ç§»çš„页é¢åˆ† é…æ–°çš„页é¢ã€‚ migrate_pages()如何工作 ======================= migrate_pages()对它的页é¢åˆ—表进行了多次处ç†ã€‚如果当时对一个页é¢çš„æ‰€æœ‰å¼•用都å¯ä»¥è¢«ç§»é™¤ï¼Œ 那么这个页é¢å°±ä¼šè¢«ç§»åŠ¨ã€‚è¯¥é¡µå·²ç»é€šè¿‡folio_isolate_lru()从LRUä¸ç§»é™¤ï¼Œå¹¶ä¸”refcount被 å¢žåŠ ï¼Œä»¥ä¾¿åœ¨é¡µé¢è¿ç§»å‘生时ä¸é‡Šæ”¾è¯¥é¡µã€‚ æ¥éª¤: 1. é”定è¦è¿ç§»çš„页é¢ã€‚ 2. ç¡®ä¿å›žå†™å·²ç»å®Œæˆã€‚ 3. é”定我们è¦è¿ç§»åˆ°çš„æ–°é¡µé¢ã€‚é”定它是为了在è¿ç§»è¿‡ç¨‹ä¸ç«‹å³é˜»æ¢å¯¹è¿™ä¸ªï¼ˆå°šæœªæ›´æ–°çš„)页é¢çš„ 访问。 4. 所有对该页的页表引用都被转æ¢ä¸ºè¿ç§»æ¡ç›®ã€‚这就å‡å°‘了一个页é¢çš„mapcount。如果产生的 mapcount䏿˜¯é›¶ï¼Œé‚£ä¹ˆæˆ‘们就ä¸è¿ç§»è¯¥é¡µã€‚所有试图访问该页的用户空间进程现在将ç‰å¾…页 é¢é”或者ç‰å¾…è¿ç§»é¡µè¡¨é¡¹è¢«ç§»é™¤ã€‚ 5. i_pagesçš„é”è¢«æŒæœ‰ã€‚è¿™å°†å¯¼è‡´æ‰€æœ‰è¯•å›¾é€šè¿‡æ˜ å°„è®¿é—®è¯¥é¡µçš„è¿›ç¨‹åœ¨è‡ªæ—‹é”上阻塞。 6. 检查该页的Refcount,如果还有引用,我们就退出。å¦åˆ™ï¼Œæˆ‘ä»¬çŸ¥é“æˆ‘们是唯一引用这个页 é¢çš„人。 7. æ£€æŸ¥åŸºæ•°æ ‘ï¼Œå¦‚æžœå®ƒä¸åŒ…嫿Œ‡å‘这个页é¢çš„æŒ‡é’ˆï¼Œé‚£ä¹ˆæˆ‘ä»¬å°±é€€å‡ºï¼Œå› ä¸ºå…¶ä»–äººä¿®æ”¹äº†åŸºæ•°æ ‘ã€‚ 8. 新的页é¢è¦ç”¨æ—§çš„页é¢çš„一些设置进行预处ç†ï¼Œè¿™æ ·è®¿é—®æ–°çš„页é¢å°±ä¼šå‘现一个具有æ£ç¡®è®¾ç½® 的页é¢ã€‚ 9. åŸºæ•°æ ‘è¢«æ”¹å˜ä»¥æŒ‡å‘新的页é¢ã€‚ 10. æ—§é¡µçš„å¼•ç”¨è®¡æ•°è¢«åˆ é™¤ï¼Œå› ä¸ºåœ°å€ç©ºé—´çš„å¼•ç”¨å·²ç»æ¶ˆå¤±ã€‚å¯¹æ–°é¡µçš„å¼•ç”¨è¢«å»ºç«‹ï¼Œå› ä¸ºæ–°é¡µè¢« 地å€ç©ºé—´å¼•用。 11. i_pagesé”è¢«æ”¾å¼ƒã€‚è¿™æ ·ä¸€æ¥ï¼Œåœ¨æ˜ å°„ä¸çš„æŸ¥æ‰¾åˆå˜å¾—å¯èƒ½äº†ã€‚进程将从在é”上自旋到在 被é”的新页上ç¡çœ 。 12. 页é¢å†…容被å¤åˆ¶åˆ°æ–°çš„页é¢ä¸Šã€‚ 13. å‰©ä½™çš„é¡µé¢æ ‡å¿—被å¤åˆ¶åˆ°æ–°çš„页é¢ä¸Šã€‚ 14. æ—§çš„é¡µé¢æ ‡å¿—被清除,以表明该页é¢ä¸å†æä¾›ä»»ä½•ä¿¡æ¯ã€‚ 15. 新页é¢ä¸Šçš„回写队列被触å‘了。 16. 如果è¿ç§»æ¡ç›®è¢«æ’入到页表ä¸ï¼Œé‚£ä¹ˆå°±ç”¨çœŸæ£çš„ptes替æ¢å®ƒä»¬ã€‚è¿™æ ·åšå°†ä½¿é‚£äº›å°šæœªç‰å¾…页 é”的用户空间进程能够访问。 17. 页é¢é”从新旧页é¢ä¸Šè¢«æ’¤é”€ã€‚ç‰å¾…页é”的进程将é‡åšä»–们的缺页异常,并将到达新的页é¢ã€‚ 18. 新的页é¢è¢«ç§»åˆ°LRUä¸ï¼Œå¯ä»¥è¢«äº¤æ¢å™¨ç‰å†æ¬¡æ‰«æã€‚ éžLRU页é¢è¿ç§» ============= 尽管è¿ç§»æœ€åˆçš„目的是为了å‡å°‘NUMA的内å˜è®¿é—®å»¶è¿Ÿï¼Œä½†åŽ‹ç¼©ä¹Ÿä½¿ç”¨è¿ç§»æ¥åˆ›å»ºé«˜é˜¶é¡µé¢ã€‚ ç›®å‰å®žçŽ°çš„é—®é¢˜æ˜¯ï¼Œå®ƒè¢«è®¾è®¡ä¸ºåªè¿ç§»*LRU*页。然而,有一些潜在的éžLRU页é¢å¯ä»¥åœ¨é©±åŠ¨ä¸ è¢«è¿ç§»ï¼Œä¾‹å¦‚,zsmalloc,virtio-balloon页é¢ã€‚ 对于virtio-balloon页é¢ï¼Œè¿ç§»ä»£ç 路径的æŸäº›éƒ¨åˆ†å·²ç»è¢«é’©ä½ï¼Œå¹¶æ·»åŠ äº†virtio-balloon çš„ç‰¹å®šå‡½æ•°æ¥æ‹¦æˆªè¿ç§»é€»è¾‘。这对一个驱动æ¥è¯´å¤ªç‰¹æ®Šäº†ï¼Œæ‰€ä»¥å…¶ä»–想让自己的页é¢å¯ç§»åŠ¨çš„é©± 动就必须在è¿ç§»è·¯å¾„䏿·»åŠ è‡ªå·±çš„ç‰¹å®šé’©å。 为了克æœè¿™ä¸ªé—®é¢˜ï¼ŒVM支æŒéžLRU页é¢è¿ç§»ï¼Œå®ƒä¸ºéžLRUå¯ç§»åŠ¨é¡µé¢æä¾›äº†é€šç”¨å‡½æ•°ï¼Œè€Œåœ¨è¿ç§» è·¯å¾„ä¸æ²¡æœ‰ç‰¹å®šçš„驱动程åºé’©å。 å¦‚æžœä¸€ä¸ªé©±åŠ¨ç¨‹åºæƒ³è®©å®ƒçš„页é¢å¯ç§»åŠ¨ï¼Œå®ƒåº”è¯¥å®šä¹‰ä¸‰ä¸ªå‡½æ•°ï¼Œè¿™äº›å‡½æ•°æ˜¯ struct address_space_operations的函数指针。 1. ``bool (*isolate_page) (struct page *page, isolate_mode_t mode);`` VM对驱动的isolate_page()函数的期望是,如果驱动æˆåŠŸéš”ç¦»äº†è¯¥é¡µï¼Œåˆ™è¿”å›ž*true*。 返回trueåŽï¼ŒVMä¼šå°†è¯¥é¡µæ ‡è®°ä¸ºPG_isolatedï¼Œè¿™æ ·å¤šä¸ªCPU的并å‘隔离就会跳过该 页进行隔离。如果驱动程åºä¸èƒ½éš”离该页,它应该返回*false*。 一旦页é¢è¢«æˆåŠŸéš”ç¦»ï¼ŒVM就会使用page.lruå—æ®µï¼Œå› æ¤é©±åŠ¨ç¨‹åºä¸åº”期望ä¿ç•™è¿™äº›å—段的值。 2. ``int (*migratepage) (struct address_space *mapping,`` | ``struct page *newpage, struct page *oldpage, enum migrate_mode);`` 隔离åŽï¼Œè™šæ‹Ÿæœºç”¨éš”离的页é¢è°ƒç”¨é©±åŠ¨çš„migratepage()。migratepage()的功能是将旧页 的内容移动到新页,并设置struct page newpageçš„å—æ®µã€‚请记ä½ï¼Œå¦‚æžœä½ æˆåŠŸè¿ç§»äº†æ—§é¡µ 并返回MIGRATEPAGE_SUCCESSï¼Œä½ åº”è¯¥é€šè¿‡page_lock下的__ClearPageMovable()å‘虚 拟机表明旧页ä¸å†å¯ç§»åŠ¨ã€‚å¦‚æžœé©±åŠ¨æš‚æ—¶ä¸èƒ½è¿ç§»è¯¥é¡µï¼Œé©±åЍå¯ä»¥è¿”回-EAGAIN。在-EAGAIN 时,VMä¼šåœ¨çŸæ—¶é—´å†…é‡è¯•页é¢è¿ç§»ï¼Œå› 为VMå°†-EAGAINç†è§£ä¸º "临时è¿ç§»å¤±è´¥"。在返回除 -EAGAIN以外的任何错误时,VM将放弃页é¢è¿ç§»è€Œä¸é‡è¯•。 在migratepage()函数ä¸ï¼Œé©±åŠ¨ç¨‹åºä¸åº”该接触page.lruå—æ®µã€‚ 3. ``void (*putback_page)(struct page *);`` 如果在隔离页上è¿ç§»å¤±è´¥ï¼ŒVMåº”è¯¥å°†éš”ç¦»é¡µè¿”å›žç»™é©±åŠ¨ï¼Œå› æ¤VM用隔离页调用驱动的 putback_page()。在这个函数ä¸ï¼Œé©±åŠ¨åº”è¯¥æŠŠéš”ç¦»é¡µæ”¾å›žè‡ªå·±çš„æ•°æ®ç»“æž„ä¸ã€‚ éžLRUå¯ç§»åŠ¨é¡µæ ‡å¿— æœ‰ä¸¤ä¸ªé¡µé¢æ ‡å¿—用于支æŒéžLRUå¯ç§»åЍ页é¢ã€‚ * PG_movable 驱动应该使用下é¢çš„函数æ¥ä½¿é¡µé¢åœ¨page_lock下å¯ç§»åŠ¨ã€‚:: void __SetPageMovable(struct page *page, struct address_space *mapping) 它需è¦address_spaceçš„å‚æ•°æ¥æ³¨å†Œå°†è¢«VM调用的migration family函数。确切地说, PG_movable䏿˜¯struct page的一个真æ£çš„æ ‡å¿—。相å,VMå¤ç”¨äº†page->mapping的低 使¥è¡¨ç¤ºå®ƒ:: #define PAGE_MAPPING_MOVABLE 0x2 page->mapping = page->mapping | PAGE_MAPPING_MOVABLE; 所以驱动ä¸åº”该直接访问page->mapping。相å,驱动应该使用page_mapping()ï¼Œå®ƒå¯ ä»¥åœ¨é¡µé¢é”下å±è”½æŽ‰page->mapping的低2ä½ï¼Œä»Žè€ŒèŽ·å¾—æ£ç¡®çš„struct address_space。 对于éžLRUå¯ç§»åЍ页é¢çš„æµ‹è¯•,VM支æŒ__PageMovable()函数。然而,它并ä¸èƒ½ä¿è¯è¯†åˆ« éžLRUå¯ç§»åЍ页é¢ï¼Œå› 为page->mappingå—æ®µä¸Žstruct pageä¸çš„å…¶ä»–å˜é‡æ˜¯ç»Ÿä¸€çš„。如 果驱动程åºåœ¨è¢«è™šæ‹Ÿæœºéš”离åŽé‡Šæ”¾äº†é¡µé¢ï¼Œå°½ç®¡page->mapping设置了PAGE_MAPPING_MOVABLE, 但它并没有一个稳定的值(看看__ClearPageMovable)。但是__PageMovable()在页 é¢è¢«éš”离åŽï¼Œæ— è®ºé¡µé¢æ˜¯LRU还是éžLRUå¯ç§»åŠ¨çš„ï¼Œè°ƒç”¨å®ƒå¼€é”€éƒ½å¾ˆä½Žï¼Œå› ä¸ºLRU页é¢åœ¨ page->mappingä¸ä¸å¯èƒ½æœ‰PAGE_MAPPING_MOVABLE设置。在用pfn扫æä¸çš„lock_page() 进行更大开销的检查æ¥é€‰æ‹©å—害者之å‰ï¼Œå®ƒä¹Ÿå¾ˆé€‚åˆåªæ˜¯çž¥ä¸€çœ¼æ¥æµ‹è¯•éžLRUå¯ç§»åŠ¨çš„é¡µé¢ã€‚ 为了ä¿è¯éžLRUçš„å¯ç§»åЍ页é¢ï¼ŒVMæä¾›äº†PageMovable()函数。与__PageMovable()ä¸ åŒï¼ŒPageMovable()在lock_page()下验è¯page->mappingå’Œ mapping->a_ops->isolate_page。lock_page()å¯ä»¥é˜²æ¢çªç„¶ç ´åpage->mapping。 使用__SetPageMovable()的驱动应该在释放页é¢ä¹‹å‰é€šè¿‡page_lock()下的 __ClearMovablePage()æ¸…é™¤è¯¥æ ‡å¿—ã€‚ * PG_isolated 为了防æ¢å‡ 个CPUåŒæ—¶è¿›è¡Œéš”离,VM在lock_page()ä¸‹å°†éš”ç¦»çš„é¡µé¢æ ‡è®°ä¸ºPG_isolated。 å› æ¤ï¼Œå¦‚果一个CPUé‡åˆ°PG_isolatedéžLRUå¯ç§»åЍ页é¢ï¼Œå®ƒå¯ä»¥è·³è¿‡å®ƒã€‚驱动程åºä¸éœ€è¦ æ“ä½œè¿™ä¸ªæ ‡å¿—ï¼Œå› ä¸ºVM会自动设置/清除它。请记ä½ï¼Œå¦‚果驱动程åºçœ‹åˆ°PG_isolated页, è¿™æ„味ç€è¯¥é¡µå·²ç»è¢«VM隔离,所以它ä¸åº”该碰page.lruå—æ®µã€‚PG_isolatedæ ‡å¿—ä¸Ž PG_reclaimæ ‡å¿—æ˜¯åŒä¹‰çš„,所以驱动程åºä¸åº”该为自己的目的使用PG_isolated。 监测è¿ç§» ======== 以下事件(计数器)å¯ç”¨äºŽç›‘控页é¢è¿ç§»ã€‚ 1. PGMIGRATE_SUCCESS: æ£å¸¸çš„页é¢è¿ç§»æˆåŠŸã€‚æ¯ä¸ªè®¡æ•°å™¨æ„味ç€ä¸€ä¸ªé¡µé¢è¢«è¿ç§»äº†ã€‚如果该 页是一个éžTHPå’Œéžhugetlbé¡µï¼Œé‚£ä¹ˆè¿™ä¸ªè®¡æ•°å™¨ä¼šå¢žåŠ 1ã€‚å¦‚æžœè¯¥é¡µé¢æ˜¯ä¸€ä¸ªTHP或hugetlb 页é¢ï¼Œé‚£ä¹ˆè¿™ä¸ªè®¡æ•°å™¨ä¼šéšç€THP或hugetlbå页é¢çš„æ•°é‡è€Œå¢žåŠ ã€‚ä¾‹å¦‚ï¼Œè¿ç§»ä¸€ä¸ªæœ‰4KBå¤§å° çš„åŸºç¡€é¡µï¼ˆå页)的2MB THPï¼Œå°†å¯¼è‡´è¿™ä¸ªè®¡æ•°å™¨å¢žåŠ 512。 2. PGMIGRATE_FAIL: æ£å¸¸çš„页é¢è¿ç§»å¤±è´¥ã€‚与上é¢PGMIGRATE_SUCCESS的计数规则相åŒï¼šå¦‚ 果是THP或hugetlb,这个计数将被å页的数é‡å¢žåŠ ã€‚ 3. THP_MIGRATION_SUCCESS: 一个THP被è¿ç§»è€Œæ²¡æœ‰è¢«åˆ†å‰²ã€‚ 4. THP_MIGRATION_FAIL: 一个THPä¸èƒ½è¢«è¿ç§»ï¼Œä¹Ÿä¸èƒ½è¢«åˆ†å‰²ã€‚ 5. THP_MIGRATION_SPLIT: 一个THP被è¿ç§»äº†ï¼Œä½†ä¸æ˜¯è¿™æ ·çš„:首先,这个THP必须被分割。 在拆分之åŽï¼Œå¯¹å®ƒçš„å页é¢è¿›è¡Œäº†è¿ç§»é‡è¯•。 THP_MIGRATION_* 事件也会更新相应的PGMIGRATE_SUCCESS或PGMIGRATE_FAIL事件。 例如,一个THPè¿ç§»å¤±è´¥å°†å¯¼è‡´THP_MIGRATION_FAILå’ŒPGMIGRATE_FAILå¢žåŠ ã€‚ Christoph Lameter,2006å¹´5月8日。 Minchan Kim,2016å¹´3月28日。