Description of problem: Async fork是一个很好的功能,最近正在学习相关的源码,想请教下async fork为什么要在numa balance流程(change_prot_numa中)里主动触发同步? 我的理解,如果这里不触发同步,后续子进程在fork的时候,还是可以维持CoW语义去访问(父进程的PMD仍然是只读的,子进程后续还是会在__copy_present_ptes里面把父子进程的pte都改为只读的,虽然它的属性是prot_none(临时的不可访问),但是后续读写触发numa fault后 还是可以按cow的语义去访问,不破坏原有页面的内容) 相关提交: https://gitee.com/anolis/cloud-kernel/commit/af2823bdcdd3d0595ef6c05ab5e5b6aabee139ee mm/mempolicy.c 100644 -> 100644 @@ -635,6 +635,8 @@ unsigned long change_prot_numa(struct vm_area_struct *vma, struct mmu_gather tlb; long nr_updated; async_fork_fixup_vma(vma); tlb_gather_mmu(&tlb, vma->vm_mm); nr_updated = change_protection(&tlb, vma, addr, end, MM_CP_PROT_NUMA);
问这个问题的背景是想审视下内核中哪些页表修改需要去做主动同步,因为内核中改页表的地方还挺多的,像规整、回收、KSM、THP都会动到进程页表。 THP会动到PMD level的显然是要改的,但是其他pte级别的修改我理解很多是不必要的?比如numa balance这个?
感谢关注和反馈!这是一个很好的点,我跟宝林和我们的原始作者讨论了一下这个问题,在async fork论文中提到了,swapping和migration由于内容未发生变化不需要特殊处理页表同步的场景:请参考:https://arxiv.org/pdf/2301.05861 4.3。我们的代码里应该是没有处理swapout的(try_to_unmap)。migration的路径,也就是你提到的,应该是基于应用场景里关闭了numa balancing,为了覆盖潜在的修改了页表又不能大规模验证的情况下加上的(我们无法排除是否有其它的race -- 我们async fork有个假设就是fork完成之前只有父进程能操作内存页页表,但实际上也会有其它kthread,没有完全覆盖测试)。 感谢你提的这个点,后续我们会重新审视一下页表的修改路径评估其影响,经过验证之后持续迭代。 非常感谢
(In reply to sunnanyong from comment #1) > 问这个问题的背景是想审视下内核中哪些页表修改需要去做主动同步,因为内核中改页表的地方还挺多的,像规整、回收、KSM、THP都会动到进程页表。 > THP会动到PMD level的显然是要改的,但是其他pte级别的修改我理解很多是不必要的?比如numa balance这个? (In reply to sunnanyong from comment #0) > Description of problem: > Async fork是一个很好的功能,最近正在学习相关的源码,想请教下async fork为什么要在numa > balance流程(change_prot_numa中)里主动触发同步? > 我的理解,如果这里不触发同步,后续子进程在fork的时候,还是可以维持CoW语义去访问(父进程的PMD仍然是只读的,子进程后续还是会在__copy_pre > sent_ptes里面把父子进程的pte都改为只读的,虽然它的属性是prot_none(临时的不可访问),但是后续读写触发numa fault后 > 还是可以按cow的语义去访问,不破坏原有页面的内容) > > 相关提交: > https://gitee.com/anolis/cloud-kernel/commit/ > af2823bdcdd3d0595ef6c05ab5e5b6aabee139ee > > mm/mempolicy.c 100644 -> 100644 > @@ -635,6 +635,8 @@ unsigned long change_prot_numa(struct vm_area_struct > *vma, > struct mmu_gather tlb; > long nr_updated; > > async_fork_fixup_vma(vma); > > tlb_gather_mmu(&tlb, vma->vm_mm); > > nr_updated = change_protection(&tlb, vma, addr, end, MM_CP_PROT_NUMA); 感谢关注和反馈!这是一个很好的点,我跟宝林和我们的原始作者讨论了一下这个问题,在async fork论文中提到了,swapping和migration由于内容未发生变化不需要特殊处理页表同步的场景:请参考:https://arxiv.org/pdf/2301.05861 4.3。我们的代码里应该是没有处理swapout的(try_to_unmap)。migration的路径,也就是你提到的,应该是基于应用场景里关闭了numa balancing,为了覆盖潜在的修改了页表又不能大规模验证的情况下加上的(我们无法排除是否有其它的race -- 我们async fork有个假设就是fork完成之前只有父进程能操作内存页页表,但实际上也会有其它kthread,没有完全覆盖测试)。 感谢你提的这个点,后续我们会重新审视一下页表的修改路径评估其影响,经过验证之后持续迭代。 非常感谢
(In reply to zelin from comment #3) > (In reply to sunnanyong from comment #1) > > 问这个问题的背景是想审视下内核中哪些页表修改需要去做主动同步,因为内核中改页表的地方还挺多的,像规整、回收、KSM、THP都会动到进程页表。 > > THP会动到PMD level的显然是要改的,但是其他pte级别的修改我理解很多是不必要的?比如numa balance这个? > > (In reply to sunnanyong from comment #0) > > Description of problem: > > Async fork是一个很好的功能,最近正在学习相关的源码,想请教下async fork为什么要在numa > > balance流程(change_prot_numa中)里主动触发同步? > > 我的理解,如果这里不触发同步,后续子进程在fork的时候,还是可以维持CoW语义去访问(父进程的PMD仍然是只读的,子进程后续还是会在__copy_pre > > sent_ptes里面把父子进程的pte都改为只读的,虽然它的属性是prot_none(临时的不可访问),但是后续读写触发numa fault后 > > 还是可以按cow的语义去访问,不破坏原有页面的内容) > > > > 相关提交: > > https://gitee.com/anolis/cloud-kernel/commit/ > > af2823bdcdd3d0595ef6c05ab5e5b6aabee139ee > > > > mm/mempolicy.c 100644 -> 100644 > > @@ -635,6 +635,8 @@ unsigned long change_prot_numa(struct vm_area_struct > > *vma, > > struct mmu_gather tlb; > > long nr_updated; > > > > async_fork_fixup_vma(vma); > > > > tlb_gather_mmu(&tlb, vma->vm_mm); > > > > nr_updated = change_protection(&tlb, vma, addr, end, MM_CP_PROT_NUMA); > > 感谢关注和反馈!这是一个很好的点,我跟宝林和我们的原始作者讨论了一下这个问题,在async > fork论文中提到了,swapping和migration由于内容未发生变化不需要特殊处理页表同步的场景:请参考:https://arxiv.org/ > pdf/2301.05861 > 4. > 3。我们的代码里应该是没有处理swapout的(try_to_unmap)。migration的路径,也就是你提到的,应该是基于应用场景里关闭了numa > balancing,为了覆盖潜在的修改了页表又不能大规模验证的情况下加上的(我们无法排除是否有其它的race -- 我们async > fork有个假设就是fork完成之前只有父进程能操作内存页页表,但实际上也会有其它kthread,没有完全覆盖测试)。 > 感谢你提的这个点,后续我们会重新审视一下页表的修改路径评估其影响,经过验证之后持续迭代。 非常感谢 @
感谢非常及时的答复! 还想问下这个特性你们在产品环境已经用了吗? 我们最近正在测试这个特性,后面如果有补丁会及时同步;)