

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 <taka@valinux.co.jp>
Signed-off-by: Dave Hansen <haveblue@us.ibm.com>
---

 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                 |   14 ++++++++++++--
 7 files changed, 21 insertions(+), 6 deletions(-)

diff -puN arch/i386/kernel/sys_i386.c~P22-vm_immovable arch/i386/kernel/sys_i386.c
--- memhotplug/arch/i386/kernel/sys_i386.c~P22-vm_immovable	2004-12-10 13:53:18.000000000 -0800
+++ memhotplug-dave/arch/i386/kernel/sys_i386.c	2004-12-10 13:53:18.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~P22-vm_immovable include/asm-i386/mman.h
--- memhotplug/include/asm-i386/mman.h~P22-vm_immovable	2004-12-10 13:53:18.000000000 -0800
+++ memhotplug-dave/include/asm-i386/mman.h	2004-12-10 13:53:18.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~P22-vm_immovable include/asm-ia64/mman.h
--- memhotplug/include/asm-ia64/mman.h~P22-vm_immovable	2004-12-10 13:53:18.000000000 -0800
+++ memhotplug-dave/include/asm-ia64/mman.h	2004-12-10 13:53:18.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~P22-vm_immovable include/linux/mm.h
--- memhotplug/include/linux/mm.h~P22-vm_immovable	2004-12-10 13:53:18.000000000 -0800
+++ memhotplug-dave/include/linux/mm.h	2004-12-10 13:53:18.000000000 -0800
@@ -168,6 +168,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~P22-vm_immovable include/linux/mman.h
--- memhotplug/include/linux/mman.h~P22-vm_immovable	2004-12-10 13:53:18.000000000 -0800
+++ memhotplug-dave/include/linux/mman.h	2004-12-10 13:53:18.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~P22-vm_immovable kernel/fork.c
--- memhotplug/kernel/fork.c~P22-vm_immovable	2004-12-10 13:53:18.000000000 -0800
+++ memhotplug-dave/kernel/fork.c	2004-12-10 13:53:18.000000000 -0800
@@ -211,7 +211,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~P22-vm_immovable mm/memory.c
--- memhotplug/mm/memory.c~P22-vm_immovable	2004-12-10 13:53:18.000000000 -0800
+++ memhotplug-dave/mm/memory.c	2004-12-10 13:53:18.000000000 -0800
@@ -1370,7 +1370,12 @@ static int do_wp_page(struct mm_struct *
 
 	if (unlikely(anon_vma_prepare(vma)))
 		goto no_new_page;
-	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_cow_page(old_page,new_page,address);
@@ -1843,7 +1848,12 @@ do_anonymous_page(struct mm_struct *mm, 
 
 		if (unlikely(anon_vma_prepare(vma)))
 			goto no_mem;
-		page = alloc_page_vma(GFP_HIGHUSER, vma, addr);
+#ifdef CONFIG_MEMORY_HOTPLUG
+		if (vma->vm_flags & VM_IMMOVABLE)
+			page = alloc_page_vma(GFP_USER, vma, addr);
+		else
+#endif
+			page = alloc_page_vma(GFP_HIGHUSER, vma, addr);
 		if (!page)
 			goto no_mem;
 		clear_user_highpage(page, addr);
_
