This patch allows vm_area_struct can have non hot-pluggable attribute. Pages attached to the vma won't be allocated from hot-pluggable memory area. FIXME: This code is temporary, the base code assumes HighMem is hot-pluggable. The pages should be allocated from non hot-pluggable zone or non hot-pluggable memory area, not from Normal zone. Signed-off-by: Hirokazu Takahashi Signed-off-by: Dave Hansen --- memhotplug-dave/arch/i386/kernel/sys_i386.c | 5 +++-- memhotplug-dave/include/asm-i386/mman.h | 1 + memhotplug-dave/include/asm-ia64/mman.h | 1 + memhotplug-dave/include/linux/mm.h | 1 + memhotplug-dave/include/linux/mman.h | 3 ++- memhotplug-dave/kernel/fork.c | 2 +- memhotplug-dave/mm/memory.c | 16 ++++++++++++++-- 7 files changed, 23 insertions(+), 6 deletions(-) diff -puN arch/i386/kernel/sys_i386.c~AA-PM-22-vm_immovable arch/i386/kernel/sys_i386.c --- memhotplug/arch/i386/kernel/sys_i386.c~AA-PM-22-vm_immovable 2005-03-11 10:52:08.000000000 -0800 +++ memhotplug-dave/arch/i386/kernel/sys_i386.c 2005-03-11 10:52:08.000000000 -0800 @@ -70,7 +70,7 @@ asmlinkage long sys_mmap2(unsigned long unsigned long prot, unsigned long flags, unsigned long fd, unsigned long pgoff) { - return do_mmap2(addr, len, prot, flags, fd, pgoff); + return do_mmap2(addr, len, prot, flags & ~MAP_IMMOVABLE, fd, pgoff); } /* @@ -101,7 +101,8 @@ asmlinkage int old_mmap(struct mmap_arg_ if (a.offset & ~PAGE_MASK) goto out; - err = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT); + err = do_mmap2(a.addr, a.len, a.prot, a.flags & ~MAP_IMMOVABLE, + a.fd, a.offset >> PAGE_SHIFT); out: return err; } diff -puN include/asm-i386/mman.h~AA-PM-22-vm_immovable include/asm-i386/mman.h --- memhotplug/include/asm-i386/mman.h~AA-PM-22-vm_immovable 2005-03-11 10:52:08.000000000 -0800 +++ memhotplug-dave/include/asm-i386/mman.h 2005-03-11 10:52:08.000000000 -0800 @@ -22,6 +22,7 @@ #define MAP_NORESERVE 0x4000 /* don't check for reservations */ #define MAP_POPULATE 0x8000 /* populate (prefault) pagetables */ #define MAP_NONBLOCK 0x10000 /* do not block on IO */ +#define MAP_IMMOVABLE 0x20000 #define MS_ASYNC 1 /* sync memory asynchronously */ #define MS_INVALIDATE 2 /* invalidate the caches */ diff -puN include/asm-ia64/mman.h~AA-PM-22-vm_immovable include/asm-ia64/mman.h --- memhotplug/include/asm-ia64/mman.h~AA-PM-22-vm_immovable 2005-03-11 10:52:08.000000000 -0800 +++ memhotplug-dave/include/asm-ia64/mman.h 2005-03-11 10:52:08.000000000 -0800 @@ -30,6 +30,7 @@ #define MAP_NORESERVE 0x04000 /* don't check for reservations */ #define MAP_POPULATE 0x08000 /* populate (prefault) pagetables */ #define MAP_NONBLOCK 0x10000 /* do not block on IO */ +#define MAP_IMMOVABLE 0x20000 #define MS_ASYNC 1 /* sync memory asynchronously */ #define MS_INVALIDATE 2 /* invalidate the caches */ diff -puN include/linux/mm.h~AA-PM-22-vm_immovable include/linux/mm.h --- memhotplug/include/linux/mm.h~AA-PM-22-vm_immovable 2005-03-11 10:52:08.000000000 -0800 +++ memhotplug-dave/include/linux/mm.h 2005-03-11 10:52:08.000000000 -0800 @@ -164,6 +164,7 @@ extern unsigned int kobjsize(const void #define VM_ACCOUNT 0x00100000 /* Is a VM accounted object */ #define VM_HUGETLB 0x00400000 /* Huge TLB Page VM */ #define VM_NONLINEAR 0x00800000 /* Is non-linear (remap_file_pages) */ +#define VM_IMMOVABLE 0x01000000 /* Don't place in hot removable area */ #ifndef VM_STACK_DEFAULT_FLAGS /* arch can override this */ #define VM_STACK_DEFAULT_FLAGS VM_DATA_DEFAULT_FLAGS diff -puN include/linux/mman.h~AA-PM-22-vm_immovable include/linux/mman.h --- memhotplug/include/linux/mman.h~AA-PM-22-vm_immovable 2005-03-11 10:52:08.000000000 -0800 +++ memhotplug-dave/include/linux/mman.h 2005-03-11 10:52:08.000000000 -0800 @@ -61,7 +61,8 @@ calc_vm_flag_bits(unsigned long flags) return _calc_vm_trans(flags, MAP_GROWSDOWN, VM_GROWSDOWN ) | _calc_vm_trans(flags, MAP_DENYWRITE, VM_DENYWRITE ) | _calc_vm_trans(flags, MAP_EXECUTABLE, VM_EXECUTABLE) | - _calc_vm_trans(flags, MAP_LOCKED, VM_LOCKED ); + _calc_vm_trans(flags, MAP_LOCKED, VM_LOCKED ) | + _calc_vm_trans(flags, MAP_IMMOVABLE, VM_IMMOVABLE ); } #endif /* _LINUX_MMAN_H */ diff -puN kernel/fork.c~AA-PM-22-vm_immovable kernel/fork.c --- memhotplug/kernel/fork.c~AA-PM-22-vm_immovable 2005-03-11 10:52:08.000000000 -0800 +++ memhotplug-dave/kernel/fork.c 2005-03-11 10:52:08.000000000 -0800 @@ -209,7 +209,7 @@ static inline int dup_mmap(struct mm_str if (IS_ERR(pol)) goto fail_nomem_policy; vma_set_policy(tmp, pol); - tmp->vm_flags &= ~VM_LOCKED; + tmp->vm_flags &= ~(VM_LOCKED|VM_IMMOVABLE); tmp->vm_mm = mm; tmp->vm_next = NULL; anon_vma_link(tmp); diff -puN mm/memory.c~AA-PM-22-vm_immovable mm/memory.c --- memhotplug/mm/memory.c~AA-PM-22-vm_immovable 2005-03-11 10:52:08.000000000 -0800 +++ memhotplug-dave/mm/memory.c 2005-03-11 10:52:08.000000000 -0800 @@ -1334,12 +1334,19 @@ static int do_wp_page(struct mm_struct * if (unlikely(anon_vma_prepare(vma))) goto no_new_page; + if (old_page == ZERO_PAGE(address)) { new_page = alloc_zeroed_user_highpage(vma, address); if (!new_page) goto no_new_page; } else { - new_page = alloc_page_vma(GFP_HIGHUSER, vma, address); +#ifdef CONFIG_MEMORY_HOTPLUG + if (vma->vm_flags & VM_IMMOVABLE) + new_page = alloc_page_vma(GFP_USER, vma, address); + else +#endif + new_page = alloc_page_vma(GFP_HIGHUSER, vma, address); + if (!new_page) goto no_new_page; copy_user_highpage(new_page, old_page, address); @@ -1817,7 +1824,12 @@ do_anonymous_page(struct mm_struct *mm, if (unlikely(anon_vma_prepare(vma))) goto no_mem; - page = alloc_zeroed_user_highpage(vma, addr); +#ifdef CONFIG_MEMORY_HOTPLUG + if (vma->vm_flags & VM_IMMOVABLE) + page = alloc_page_vma(GFP_USER, vma, addr); + else +#endif + page = alloc_zeroed_user_highpage(vma, addr); if (!page) goto no_mem; _