Skip to content

Instantly share code, notes, and snippets.

@alexclear
Created July 23, 2012 05:20
Show Gist options
  • Save alexclear/3162059 to your computer and use it in GitHub Desktop.
Save alexclear/3162059 to your computer and use it in GitHub Desktop.
A patch from https://bugzilla.kernel.org/show_bug.cgi?id=30702 adapted to 2.6.32-042stab057.1-el6-openvz
diff -u -r .//arch/alpha/include/asm/pgalloc.h ../linux-2.6.32/arch/alpha/include/asm/pgalloc.h
--- .//arch/alpha/include/asm/pgalloc.h 2009-12-03 06:51:21.000000000 +0300
+++ ../linux-2.6.32/arch/alpha/include/asm/pgalloc.h 2012-07-22 21:06:48.000000000 +0400
@@ -38,10 +38,15 @@
}
static inline pmd_t *
+__pmd_alloc_one(struct mm_struct *mm, unsigned long address, gfp_t gfp_mask)
+{
+ return (pmd_t *)__get_free_page(gfp_mask | __GFP_ZERO);
+}
+
+static inline pmd_t *
pmd_alloc_one(struct mm_struct *mm, unsigned long address)
{
- pmd_t *ret = (pmd_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
- return ret;
+ return __pmd_alloc_one(mm, address, GFP_KERNEL | __GFP_REPEAT);
}
static inline void
@@ -51,10 +56,15 @@
}
static inline pte_t *
+__pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addressi, gfp_t gfp_mask)
+{
+ return (pte_t *)__get_free_page(gfp_mask | __GFP_ZERO);
+}
+
+static inline pte_t *
pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
{
- pte_t *pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
- return pte;
+ return __pte_alloc_one_kernel(mm, address, GFP_KERNEL | __GFP_REPEAT);
}
static inline void
diff -u -r .//arch/avr32/include/asm/pgalloc.h ../linux-2.6.32/arch/avr32/include/asm/pgalloc.h
--- .//arch/avr32/include/asm/pgalloc.h 2009-12-03 06:51:21.000000000 +0300
+++ ../linux-2.6.32/arch/avr32/include/asm/pgalloc.h 2012-07-22 21:06:48.000000000 +0400
@@ -50,10 +50,16 @@
quicklist_free(QUICK_PGD, NULL, pgd);
}
+static inline pte_t *__pte_alloc_one_kernel(struct mm_struct *mm,
+ unsigned long address, gfp_t gfp_mask)
+{
+ return quicklist_alloc(QUICK_PT, gfp_mask, NULL);
+}
+
static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
unsigned long address)
{
- return quicklist_alloc(QUICK_PT, GFP_KERNEL | __GFP_REPEAT, NULL);
+ return __pte_alloc_one_kernel(mm, address, GFP_KERNEL | __GFP_REPEAT);
}
static inline pgtable_t pte_alloc_one(struct mm_struct *mm,
diff -u -r .//arch/cris/include/asm/pgalloc.h ../linux-2.6.32/arch/cris/include/asm/pgalloc.h
--- .//arch/cris/include/asm/pgalloc.h 2009-12-03 06:51:21.000000000 +0300
+++ ../linux-2.6.32/arch/cris/include/asm/pgalloc.h 2012-07-22 21:06:48.000000000 +0400
@@ -22,10 +22,16 @@
free_page((unsigned long)pgd);
}
+static inline pte_t *
+__pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address,
+ gfp_t gfp_mask)
+{
+ return (pte_t *) __get_free_page(gfp_mask | __GFP_ZERO);
+}
+
static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
{
- pte_t *pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
- return pte;
+ return __pte_alloc_one_kernel(mm, address, GFP_KERNEL | __GFP_REPEAT);
}
static inline pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long address)
diff -u -r .//arch/frv/include/asm/pgalloc.h ../linux-2.6.32/arch/frv/include/asm/pgalloc.h
--- .//arch/frv/include/asm/pgalloc.h 2009-12-03 06:51:21.000000000 +0300
+++ ../linux-2.6.32/arch/frv/include/asm/pgalloc.h 2012-07-22 21:06:48.000000000 +0400
@@ -35,8 +35,10 @@
extern void pgd_free(struct mm_struct *mm, pgd_t *);
extern pte_t *pte_alloc_one_kernel(struct mm_struct *, unsigned long);
+extern pte_t *__pte_alloc_one_kernel(struct mm_struct *, unsigned long, gfp_t);
extern pgtable_t pte_alloc_one(struct mm_struct *, unsigned long);
+extern pgtable_t __pte_alloc_one(struct mm_struct *, unsigned long, gfp_t);
static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
{
@@ -60,6 +62,7 @@
* inside the pgd, so has no extra memory associated with it.
* (In the PAE case we free the pmds as part of the pgd.)
*/
+#define __pmd_alloc_one(mm, addr,mask) ({ BUG(); ((pmd_t *) 2); })
#define pmd_alloc_one(mm, addr) ({ BUG(); ((pmd_t *) 2); })
#define pmd_free(mm, x) do { } while (0)
#define __pmd_free_tlb(tlb,x,a) do { } while (0)
diff -u -r .//arch/frv/include/asm/pgtable.h ../linux-2.6.32/arch/frv/include/asm/pgtable.h
--- .//arch/frv/include/asm/pgtable.h 2009-12-03 06:51:21.000000000 +0300
+++ ../linux-2.6.32/arch/frv/include/asm/pgtable.h 2012-07-22 21:06:48.000000000 +0400
@@ -223,6 +223,7 @@
* allocating and freeing a pud is trivial: the 1-entry pud is
* inside the pgd, so has no extra memory associated with it.
*/
+#define __pud_alloc_one(mm, address, mask) NULL
#define pud_alloc_one(mm, address) NULL
#define pud_free(mm, x) do { } while (0)
#define __pud_free_tlb(tlb, x, address) do { } while (0)
diff -u -r .//arch/frv/mm/pgalloc.c ../linux-2.6.32/arch/frv/mm/pgalloc.c
--- .//arch/frv/mm/pgalloc.c 2009-12-03 06:51:21.000000000 +0300
+++ ../linux-2.6.32/arch/frv/mm/pgalloc.c 2012-07-22 21:06:48.000000000 +0400
@@ -20,14 +20,19 @@
pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__((aligned(PAGE_SIZE)));
-pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
+pte_t *__pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address, gfp_t gfp_mask)
{
- pte_t *pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT);
+ pte_t *pte = (pte_t *)__get_free_page(gfp_mask);
if (pte)
clear_page(pte);
return pte;
}
+pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
+{
+ return __pte_alloc_one_kernel(mm, address, GFP_KERNEL | __GFP_REPEAT);
+}
+
pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long address)
{
struct page *page;
diff -u -r .//arch/ia64/include/asm/pgalloc.h ../linux-2.6.32/arch/ia64/include/asm/pgalloc.h
--- .//arch/ia64/include/asm/pgalloc.h 2009-12-03 06:51:21.000000000 +0300
+++ ../linux-2.6.32/arch/ia64/include/asm/pgalloc.h 2012-07-22 21:06:48.000000000 +0400
@@ -39,9 +39,15 @@
pgd_val(*pgd_entry) = __pa(pud);
}
+static inline pud_t *
+__pud_alloc_one(struct mm_struct *mm, unsigned long addr, gfp_t gfp_mask)
+{
+ return quicklist_alloc(0, gfp_mask, NULL);
+}
+
static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr)
{
- return quicklist_alloc(0, GFP_KERNEL, NULL);
+ return __pud_alloc_one(mm, addr, GFP_KERNEL);
}
static inline void pud_free(struct mm_struct *mm, pud_t *pud)
@@ -57,9 +63,15 @@
pud_val(*pud_entry) = __pa(pmd);
}
+static inline pmd_t *
+__pmd_alloc_one(struct mm_struct *mm, unsigned long addr, gfp_t gfp_mask)
+{
+ return quicklist_alloc(0, gfp_mask, NULL);
+}
+
static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
{
- return quicklist_alloc(0, GFP_KERNEL, NULL);
+ return __pmd_alloc_one(mm, addr, GFP_KERNEL);
}
static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
@@ -95,10 +107,16 @@
return page;
}
+static inline pte_t *__pte_alloc_one_kernel(struct mm_struct *mm,
+ unsigned long addr, gfp_t gfp_mask)
+{
+ return quicklist_alloc(0, gfp_mask, NULL);
+}
+
static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
unsigned long addr)
{
- return quicklist_alloc(0, GFP_KERNEL, NULL);
+ return __pte_alloc_one_kernel(mm, addr, GFP_KERNEL);
}
static inline void pte_free(struct mm_struct *mm, pgtable_t pte)
diff -u -r .//arch/m32r/include/asm/pgalloc.h ../linux-2.6.32/arch/m32r/include/asm/pgalloc.h
--- .//arch/m32r/include/asm/pgalloc.h 2009-12-03 06:51:21.000000000 +0300
+++ ../linux-2.6.32/arch/m32r/include/asm/pgalloc.h 2012-07-22 21:06:48.000000000 +0400
@@ -30,12 +30,16 @@
free_page((unsigned long)pgd);
}
+static __inline__ pte_t *__pte_alloc_one_kernel(struct mm_struct *mm,
+ unsigned long address, gfp_t gfp_mask)
+{
+ return (pte_t *)__get_free_page(gfp_mask | __GFP_ZERO);
+}
+
static __inline__ pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
unsigned long address)
{
- pte_t *pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_ZERO);
-
- return pte;
+ return __pte_alloc_one_kernel(mm, address, GFP_KERNEL);
}
static __inline__ pgtable_t pte_alloc_one(struct mm_struct *mm,
@@ -66,6 +70,7 @@
* (In the PAE case we free the pmds as part of the pgd.)
*/
+#define __pmd_alloc_one(mm, addr,mask) ({ BUG(); ((pmd_t *)2); })
#define pmd_alloc_one(mm, addr) ({ BUG(); ((pmd_t *)2); })
#define pmd_free(mm, x) do { } while (0)
#define __pmd_free_tlb(tlb, x, addr) do { } while (0)
diff -u -r .//arch/m68k/include/asm/motorola_pgalloc.h ../linux-2.6.32/arch/m68k/include/asm/motorola_pgalloc.h
--- .//arch/m68k/include/asm/motorola_pgalloc.h 2009-12-03 06:51:21.000000000 +0300
+++ ../linux-2.6.32/arch/m68k/include/asm/motorola_pgalloc.h 2012-07-22 21:06:48.000000000 +0400
@@ -5,13 +5,16 @@
#include <asm/tlbflush.h>
extern pmd_t *get_pointer_table(void);
+extern pmd_t *__get_pointer_table (gfp_t);
extern int free_pointer_table(pmd_t *);
-static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
+static inline pte_t *
+__pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address,
+ gfp_t gfp_mask)
{
pte_t *pte;
- pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
+ pte = (pte_t *)__get_free_page(gfp_mask | __GFP_ZERO);
if (pte) {
__flush_page_to_ram(pte);
flush_tlb_kernel_page(pte);
@@ -21,6 +24,12 @@
return pte;
}
+static inline pte_t *
+pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
+{
+ return __pte_alloc_one_kernel(mm, address, GFP_KERNEL | __GFP_REPEAT);
+}
+
static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
{
cache_page(pte);
@@ -61,10 +70,15 @@
__free_page(page);
}
+static inline pmd_t *
+__pmd_alloc_one(struct mm_struct *mm, unsigned long address, gfp_t gfp_mask)
+{
+ return __get_pointer_table(gfp_mask);
+}
static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address)
{
- return get_pointer_table();
+ return __pmd_alloc_one(mm, address, GFP_KERNEL);
}
static inline int pmd_free(struct mm_struct *mm, pmd_t *pmd)
diff -u -r .//arch/m68k/include/asm/sun3_pgalloc.h ../linux-2.6.32/arch/m68k/include/asm/sun3_pgalloc.h
--- .//arch/m68k/include/asm/sun3_pgalloc.h 2009-12-03 06:51:21.000000000 +0300
+++ ../linux-2.6.32/arch/m68k/include/asm/sun3_pgalloc.h 2012-07-22 21:06:48.000000000 +0400
@@ -18,6 +18,7 @@
extern const char bad_pmd_string[];
+#define __pmd_alloc_one(mm,address,mask) ({ BUG(); ((pmd_t *)2); })
#define pmd_alloc_one(mm,address) ({ BUG(); ((pmd_t *)2); })
@@ -38,10 +39,11 @@
tlb_remove_page((tlb), pte); \
} while (0)
-static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
- unsigned long address)
+static inline pte_t *
+__pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address,
+ gfp_t gfp_mask)
{
- unsigned long page = __get_free_page(GFP_KERNEL|__GFP_REPEAT);
+ unsigned long page = __get_free_page(gfp_mask);
if (!page)
return NULL;
@@ -50,6 +52,12 @@
return (pte_t *) (page);
}
+static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
+ unsigned long address)
+{
+ return __pte_alloc_one_kernel(mm, address, GFP_KERNEL | __GFP_REPEAT);
+}
+
static inline pgtable_t pte_alloc_one(struct mm_struct *mm,
unsigned long address)
{
diff -u -r .//arch/m68k/mm/memory.c ../linux-2.6.32/arch/m68k/mm/memory.c
--- .//arch/m68k/mm/memory.c 2009-12-03 06:51:21.000000000 +0300
+++ ../linux-2.6.32/arch/m68k/mm/memory.c 2012-07-22 21:06:48.000000000 +0400
@@ -59,7 +59,7 @@
return;
}
-pmd_t *get_pointer_table (void)
+pmd_t *__get_pointer_table (gfp_t gfp_mask)
{
ptable_desc *dp = ptable_list.next;
unsigned char mask = PD_MARKBITS (dp);
@@ -76,7 +76,7 @@
void *page;
ptable_desc *new;
- if (!(page = (void *)get_zeroed_page(GFP_KERNEL)))
+ if (!(page = (void *)get_zeroed_page(gfp_mask)))
return NULL;
flush_tlb_kernel_page(page);
@@ -99,6 +99,11 @@
return (pmd_t *) (page_address(PD_PAGE(dp)) + off);
}
+pmd_t *get_pointer_table (void)
+{
+ return __get_pointer_table(GFP_KERNEL);
+}
+
int free_pointer_table (pmd_t *ptable)
{
ptable_desc *dp;
diff -u -r .//arch/mips/include/asm/pgalloc.h ../linux-2.6.32/arch/mips/include/asm/pgalloc.h
--- .//arch/mips/include/asm/pgalloc.h 2009-12-03 06:51:21.000000000 +0300
+++ ../linux-2.6.32/arch/mips/include/asm/pgalloc.h 2012-07-22 21:06:48.000000000 +0400
@@ -64,14 +64,16 @@
free_pages((unsigned long)pgd, PGD_ORDER);
}
+static inline pte_t *__pte_alloc_one_kernel(struct mm_struct *mm,
+ unsigned long address, gfp_t gfp_mask)
+{
+ return (pte_t *) __get_free_pages(gfp_mask | __GFP_ZERO, PTE_ORDER);
+}
+
static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
unsigned long address)
{
- pte_t *pte;
-
- pte = (pte_t *) __get_free_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO, PTE_ORDER);
-
- return pte;
+ return __pte_alloc_one_kernel(mm, address, GFP_KERNEL | __GFP_REPEAT);
}
static inline struct page *pte_alloc_one(struct mm_struct *mm,
@@ -106,16 +108,22 @@
#ifdef CONFIG_64BIT
-static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address)
+static inline pmd_t *
+__pmd_alloc_one(struct mm_struct *mm, unsigned long address, gfp_t gfp_mask)
{
pmd_t *pmd;
- pmd = (pmd_t *) __get_free_pages(GFP_KERNEL|__GFP_REPEAT, PMD_ORDER);
+ pmd = (pmd_t *) __get_free_pages(gfp_mask, PMD_ORDER);
if (pmd)
pmd_init((unsigned long)pmd, (unsigned long)invalid_pte_table);
return pmd;
}
+static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address)
+{
+ return __pmd_alloc_one(mm, address, GFP_KERNEL | __GFP_REPEAT);
+}
+
static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
{
free_pages((unsigned long)pmd, PMD_ORDER);
diff -u -r .//arch/mn10300/include/asm/pgalloc.h ../linux-2.6.32/arch/mn10300/include/asm/pgalloc.h
--- .//arch/mn10300/include/asm/pgalloc.h 2009-12-03 06:51:21.000000000 +0300
+++ ../linux-2.6.32/arch/mn10300/include/asm/pgalloc.h 2012-07-22 21:06:48.000000000 +0400
@@ -38,6 +38,8 @@
extern void pgd_free(struct mm_struct *, pgd_t *);
extern pte_t *pte_alloc_one_kernel(struct mm_struct *, unsigned long);
+extern pte_t *__pte_alloc_one_kernel(struct mm_struct *, unsigned long, gfp_t);
+
extern struct page *pte_alloc_one(struct mm_struct *, unsigned long);
static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
diff -u -r .//arch/mn10300/mm/pgtable.c ../linux-2.6.32/arch/mn10300/mm/pgtable.c
--- .//arch/mn10300/mm/pgtable.c 2009-12-03 06:51:21.000000000 +0300
+++ ../linux-2.6.32/arch/mn10300/mm/pgtable.c 2012-07-22 21:06:48.000000000 +0400
@@ -62,14 +62,20 @@
__flush_tlb_one(vaddr);
}
-pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
+pte_t *__pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address,
+ gfp_t gfp_mask)
{
- pte_t *pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT);
+ pte_t *pte = (pte_t *)__get_free_page(gfp_mask);
if (pte)
clear_page(pte);
return pte;
}
+pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
+{
+ return __pte_alloc_one_kernel(mm, address, GFP_KERNEL | __GFP_REPEAT);
+}
+
struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
{
struct page *pte;
diff -u -r .//arch/parisc/include/asm/pgalloc.h ../linux-2.6.32/arch/parisc/include/asm/pgalloc.h
--- .//arch/parisc/include/asm/pgalloc.h 2009-12-03 06:51:21.000000000 +0300
+++ ../linux-2.6.32/arch/parisc/include/asm/pgalloc.h 2012-07-22 21:06:48.000000000 +0400
@@ -61,15 +61,20 @@
(__u32)(__pa((unsigned long)pmd) >> PxD_VALUE_SHIFT));
}
-static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address)
+static inline pmd_t *
+__pmd_alloc_one(struct mm_struct *mm, unsigned long address, gfp_t gfp_mask)
{
- pmd_t *pmd = (pmd_t *)__get_free_pages(GFP_KERNEL|__GFP_REPEAT,
- PMD_ORDER);
+ pmd_t *pmd = (pmd_t *)__get_free_pages(gfp_mask, PMD_ORDER);
if (pmd)
memset(pmd, 0, PAGE_SIZE<<PMD_ORDER);
return pmd;
}
+static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address)
+{
+ return __pmd_alloc_one(mm, address, GFP_KERNEL | __GFP_REPEAT);
+}
+
static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
{
#ifdef CONFIG_64BIT
@@ -90,6 +95,7 @@
* inside the pgd, so has no extra memory associated with it.
*/
+#define __pmd_alloc_one(mm, addr, mask) ({ BUG(); ((pmd_t *)2); })
#define pmd_alloc_one(mm, addr) ({ BUG(); ((pmd_t *)2); })
#define pmd_free(mm, x) do { } while (0)
#define pgd_populate(mm, pmd, pte) BUG()
@@ -127,10 +133,15 @@
}
static inline pte_t *
+__pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr, gfp_t gfp_mask)
+{
+ return (pte_t *)__get_free_page(gfp_mask | __GFP_ZERO);
+}
+
+static inline pte_t *
pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr)
{
- pte_t *pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
- return pte;
+ return __pte_alloc_one_kernel(mm, addr, GFP_KERNEL | __GFP_REPEAT);
}
static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
diff -u -r .//arch/powerpc/include/asm/pgalloc-32.h ../linux-2.6.32/arch/powerpc/include/asm/pgalloc-32.h
--- .//arch/powerpc/include/asm/pgalloc-32.h 2009-12-03 06:51:21.000000000 +0300
+++ ../linux-2.6.32/arch/powerpc/include/asm/pgalloc-32.h 2012-07-22 21:06:48.000000000 +0400
@@ -34,6 +34,8 @@
#endif
extern pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr);
+extern pte_t *__pte_alloc_one_kernel(struct mm_struct *, unsigned long, gfp_t);
+
extern pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long addr);
static inline void pgtable_free(pgtable_free_t pgf)
diff -u -r .//arch/powerpc/mm/pgtable_32.c ../linux-2.6.32/arch/powerpc/mm/pgtable_32.c
--- .//arch/powerpc/mm/pgtable_32.c 2009-12-03 06:51:21.000000000 +0300
+++ ../linux-2.6.32/arch/powerpc/mm/pgtable_32.c 2012-07-22 21:06:48.000000000 +0400
@@ -93,14 +93,15 @@
#endif
}
-__init_refok pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
+__init_refok pte_t *
+__pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address, gfp_t gfp_mask)
{
pte_t *pte;
extern int mem_init_done;
extern void *early_get_page(void);
if (mem_init_done) {
- pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
+ pte = (pte_t *)__get_free_page(gfp_mask | __GFP_ZERO);
} else {
pte = (pte_t *)early_get_page();
if (pte)
@@ -109,6 +110,11 @@
return pte;
}
+__init_refok pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
+{
+ return __pte_alloc_one_kernel(mm, address, GFP_KERNEL | __GFP_REPEAT);
+}
+
pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long address)
{
struct page *ptepage;
diff -u -r .//arch/score/include/asm/pgalloc.h ../linux-2.6.32/arch/score/include/asm/pgalloc.h
--- .//arch/score/include/asm/pgalloc.h 2009-12-03 06:51:21.000000000 +0300
+++ ../linux-2.6.32/arch/score/include/asm/pgalloc.h 2012-07-22 21:06:48.000000000 +0400
@@ -37,15 +37,16 @@
free_pages((unsigned long)pgd, PGD_ORDER);
}
+static inline pte_t *
+__pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address, gfp_t gfp_mask)
+{
+ return (pte_t *) __get_free_pages(gfp_mask | __GFP_ZERO, PTE_ORDER);
+}
+
static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
unsigned long address)
{
- pte_t *pte;
-
- pte = (pte_t *) __get_free_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO,
- PTE_ORDER);
-
- return pte;
+ return __pte_alloc_one_kernel(mm, address, GFP_KERNEL | __GFP_REPEAT);
}
static inline struct page *pte_alloc_one(struct mm_struct *mm,
diff -u -r .//arch/sparc/include/asm/pgalloc_32.h ../linux-2.6.32/arch/sparc/include/asm/pgalloc_32.h
--- .//arch/sparc/include/asm/pgalloc_32.h 2009-12-03 06:51:21.000000000 +0300
+++ ../linux-2.6.32/arch/sparc/include/asm/pgalloc_32.h 2012-07-22 21:06:48.000000000 +0400
@@ -41,6 +41,9 @@
BTFIXUPDEF_CALL(pmd_t *, pmd_alloc_one, struct mm_struct *, unsigned long)
#define pmd_alloc_one(mm, address) BTFIXUP_CALL(pmd_alloc_one)(mm, address)
+BTFIXUPDEF_CALL(pmd_t *, __pmd_alloc_one, struct mm_struct *, unsigned long, gfp_t)
+#define __pmd_alloc_one(mm, address, gfp_mask) BTFIXUP_CALL(pmd_alloc_one)(mm, address)
+
BTFIXUPDEF_CALL(void, free_pmd_fast, pmd_t *)
#define free_pmd_fast(pmd) BTFIXUP_CALL(free_pmd_fast)(pmd)
@@ -57,6 +60,8 @@
#define pte_alloc_one(mm, address) BTFIXUP_CALL(pte_alloc_one)(mm, address)
BTFIXUPDEF_CALL(pte_t *, pte_alloc_one_kernel, struct mm_struct *, unsigned long)
#define pte_alloc_one_kernel(mm, addr) BTFIXUP_CALL(pte_alloc_one_kernel)(mm, addr)
+BTFIXUPDEF_CALL(pte_t *, __pte_alloc_one_kernel, struct mm_struct *, unsigned long, gfp_t)
+#define __pte_alloc_one_kernel(mm, addr, gfp_mask) BTFIXUP_CALL(pte_alloc_one_kernel)(mm, addr)
BTFIXUPDEF_CALL(void, free_pte_fast, pte_t *)
#define pte_free_kernel(mm, pte) BTFIXUP_CALL(free_pte_fast)(pte)
diff -u -r .//arch/sparc/include/asm/pgalloc_64.h ../linux-2.6.32/arch/sparc/include/asm/pgalloc_64.h
--- .//arch/sparc/include/asm/pgalloc_64.h 2009-12-03 06:51:21.000000000 +0300
+++ ../linux-2.6.32/arch/sparc/include/asm/pgalloc_64.h 2012-07-22 21:06:48.000000000 +0400
@@ -26,9 +26,15 @@
#define pud_populate(MM, PUD, PMD) pud_set(PUD, PMD)
+static inline pmd_t *
+__pmd_alloc_one(struct mm_struct *mm, unsigned long addr, gfp_t gfp_mask)
+{
+ return quicklist_alloc(0, gfp_mask, NULL);
+}
+
static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
{
- return quicklist_alloc(0, GFP_KERNEL, NULL);
+ return __pmd_alloc_one(mm, addr, GFP_KERNEL);
}
static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
@@ -36,10 +42,17 @@
quicklist_free(0, NULL, pmd);
}
+static inline pte_t *
+__pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address,
+ gfp_t gfp_mask)
+{
+ return quicklist_alloc(0, gfp_mask, NULL);
+}
+
static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
unsigned long address)
{
- return quicklist_alloc(0, GFP_KERNEL, NULL);
+ return __pte_alloc_one_kernel(mm, address, GFP_KERNEL);
}
static inline pgtable_t pte_alloc_one(struct mm_struct *mm,
diff -u -r .//arch/um/include/asm/pgalloc.h ../linux-2.6.32/arch/um/include/asm/pgalloc.h
--- .//arch/um/include/asm/pgalloc.h 2009-12-03 06:51:21.000000000 +0300
+++ ../linux-2.6.32/arch/um/include/asm/pgalloc.h 2012-07-22 21:06:48.000000000 +0400
@@ -27,6 +27,7 @@
extern void pgd_free(struct mm_struct *mm, pgd_t *pgd);
extern pte_t *pte_alloc_one_kernel(struct mm_struct *, unsigned long);
+extern pte_t *__pte_alloc_one_kernel(struct mm_struct *, unsigned long, gfp_t);
extern pgtable_t pte_alloc_one(struct mm_struct *, unsigned long);
static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
diff -u -r .//arch/um/kernel/mem.c ../linux-2.6.32/arch/um/kernel/mem.c
--- .//arch/um/kernel/mem.c 2009-12-03 06:51:21.000000000 +0300
+++ ../linux-2.6.32/arch/um/kernel/mem.c 2012-07-22 21:06:48.000000000 +0400
@@ -284,12 +284,15 @@
free_page((unsigned long) pgd);
}
-pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
+pte_t *
+__pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address, gfp_t gfp_mask)
{
- pte_t *pte;
+ return (pte_t *)__get_free_page(gfp_mask | __GFP_ZERO);
+}
- pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
- return pte;
+pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
+{
+ return __pte_alloc_one_kernel(mm, address, GFP_KERNEL | __GFP_REPEAT);
}
pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long address)
@@ -303,15 +306,21 @@
}
#ifdef CONFIG_3_LEVEL_PGTABLES
-pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address)
+pmd_t *
+__pmd_alloc_one(struct mm_struct *mm, unsigned long address, gfp_t gfp_mask)
{
- pmd_t *pmd = (pmd_t *) __get_free_page(GFP_KERNEL);
+ pmd_t *pmd = (pmd_t *) __get_free_page(gfp_mask);
if (pmd)
memset(pmd, 0, PAGE_SIZE);
return pmd;
}
+
+pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address)
+{
+ return __pmd_alloc_one(mm, address, GFP_KERNEL);
+}
#endif
void *uml_kmalloc(int size, int flags)
diff -u -r .//arch/x86/include/asm/pgalloc.h ../linux-2.6.32/arch/x86/include/asm/pgalloc.h
--- .//arch/x86/include/asm/pgalloc.h 2012-07-22 20:40:49.000000000 +0400
+++ ../linux-2.6.32/arch/x86/include/asm/pgalloc.h 2012-07-22 21:06:48.000000000 +0400
@@ -34,6 +34,7 @@
extern void pgd_free(struct mm_struct *mm, pgd_t *pgd);
extern pte_t *pte_alloc_one_kernel(struct mm_struct *, unsigned long);
+extern pte_t *__pte_alloc_one_kernel(struct mm_struct *, unsigned long, gfp_t);
extern pgtable_t pte_alloc_one(struct mm_struct *, unsigned long);
/* Should really implement gc for free page table pages. This could be
@@ -78,9 +79,15 @@
#define pmd_pgtable(pmd) pmd_page(pmd)
#if PAGETABLE_LEVELS > 2
+static inline pmd_t *
+__pmd_alloc_one(struct mm_struct *mm, unsigned long addr, gfp_t gfp_mask)
+{
+ return (pmd_t *)get_zeroed_page(gfp_mask);
+}
+
static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
{
- return (pmd_t *)get_zeroed_page(GFP_KERNEL|__GFP_REPEAT);
+ return __pmd_alloc_one(mm, addr, GFP_KERNEL | __GFP_REPEAT);
}
static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
@@ -114,9 +121,15 @@
set_pgd(pgd, __pgd(_PAGE_TABLE | __pa(pud)));
}
+static inline pud_t *
+__pud_alloc_one(struct mm_struct *mm, unsigned long addr, gfp_t gfp_mask)
+{
+ return (pud_t *)get_zeroed_page(gfp_mask);
+}
+
static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr)
{
- return (pud_t *)get_zeroed_page(GFP_KERNEL|__GFP_REPEAT);
+ return __pud_alloc_one(mm, addr, GFP_KERNEL | __GFP_REPEAT);
}
static inline void pud_free(struct mm_struct *mm, pud_t *pud)
diff -u -r .//arch/x86/mm/pgtable.c ../linux-2.6.32/arch/x86/mm/pgtable.c
--- .//arch/x86/mm/pgtable.c 2012-07-22 20:40:49.000000000 +0400
+++ ../linux-2.6.32/arch/x86/mm/pgtable.c 2012-07-22 21:18:58.000000000 +0400
@@ -17,9 +17,15 @@
gfp_t __userpte_alloc_gfp = PGALLOC_GFP | PGALLOC_USER_GFP;
+pte_t *
+__pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address, gfp_t gfp_mask)
+{
+ return (pte_t *)__get_free_page(gfp_mask | __GFP_NOTRACK | __GFP_ZERO);
+}
+
pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
{
- return (pte_t *)__get_free_page(PGALLOC_KERN_GFP);
+ return __pte_alloc_one_kernel(mm, address, GFP_KERNEL | __GFP_REPEAT);
}
pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long address)
diff -u -r .//arch/xtensa/include/asm/pgalloc.h ../linux-2.6.32/arch/xtensa/include/asm/pgalloc.h
--- .//arch/xtensa/include/asm/pgalloc.h 2009-12-03 06:51:21.000000000 +0300
+++ ../linux-2.6.32/arch/xtensa/include/asm/pgalloc.h 2012-07-22 21:06:48.000000000 +0400
@@ -41,10 +41,17 @@
extern struct kmem_cache *pgtable_cache;
+static inline pte_t *
+__pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address,
+ gfp_t gfp_mask)
+{
+ return kmem_cache_alloc(pgtable_cache, gfp_mask);
+}
+
static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
unsigned long address)
{
- return kmem_cache_alloc(pgtable_cache, GFP_KERNEL|__GFP_REPEAT);
+ return __pte_alloc_one_kernel(mm, address, GFP_KERNEL | __GFP_REPEAT);
}
static inline pgtable_t pte_alloc_one(struct mm_struct *mm,
diff -u -r .//arch/xtensa/mm/pgtable.c ../linux-2.6.32/arch/xtensa/mm/pgtable.c
--- .//arch/xtensa/mm/pgtable.c 2009-12-03 06:51:21.000000000 +0300
+++ ../linux-2.6.32/arch/xtensa/mm/pgtable.c 2012-07-22 21:06:48.000000000 +0400
@@ -12,13 +12,15 @@
#if (DCACHE_SIZE > PAGE_SIZE)
-pte_t* pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
+pte_t*
+__pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address,
+ gfp_t gfp_mask)
{
pte_t *pte = NULL, *p;
int color = ADDR_COLOR(address);
int i;
- p = (pte_t*) __get_free_pages(GFP_KERNEL|__GFP_REPEAT, COLOR_ORDER);
+ p = (pte_t*) __get_free_pages(gfp_mask, COLOR_ORDER);
if (likely(p)) {
split_page(virt_to_page(p), COLOR_ORDER);
@@ -35,6 +37,11 @@
return pte;
}
+pte_t* pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
+{
+ return __pte_alloc_one_kernel(mm, address, GFP_KERNEL | __GFP_REPEAT);
+}
+
#ifdef PROFILING
int mask;
diff -u -r .//include/asm-generic/4level-fixup.h ../linux-2.6.32/include/asm-generic/4level-fixup.h
--- .//include/asm-generic/4level-fixup.h 2009-12-03 06:51:21.000000000 +0300
+++ ../linux-2.6.32/include/asm-generic/4level-fixup.h 2012-07-22 21:06:48.000000000 +0400
@@ -10,10 +10,14 @@
#define pud_t pgd_t
-#define pmd_alloc(mm, pud, address) \
- ((unlikely(pgd_none(*(pud))) && __pmd_alloc(mm, pud, address))? \
+#define pmd_alloc_with_mask(mm, pud, address, mask) \
+ ((unlikely(pgd_none(*(pud))) && __pmd_alloc(mm, pud, address, mask))? \
NULL: pmd_offset(pud, address))
+#define pmd_alloc(mm, pud, address) \
+ pmd_alloc_with_mask(mm, pud, address, GFP_KERNEL)
+
+#define pud_alloc_with_mask(mm, pgd, address, mask) (pgd)
#define pud_alloc(mm, pgd, address) (pgd)
#define pud_offset(pgd, start) (pgd)
#define pud_none(pud) 0
diff -u -r .//include/asm-generic/pgtable-nopmd.h ../linux-2.6.32/include/asm-generic/pgtable-nopmd.h
--- .//include/asm-generic/pgtable-nopmd.h 2009-12-03 06:51:21.000000000 +0300
+++ ../linux-2.6.32/include/asm-generic/pgtable-nopmd.h 2012-07-22 21:06:48.000000000 +0400
@@ -55,7 +55,8 @@
* allocating and freeing a pmd is trivial: the 1-entry pmd is
* inside the pud, so has no extra memory associated with it.
*/
-#define pmd_alloc_one(mm, address) NULL
+#define __pmd_alloc_one(mm, address, mask) NULL
+#define pmd_alloc_one(mm, address) NULL
static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
{
}
diff -u -r .//include/asm-generic/pgtable-nopud.h ../linux-2.6.32/include/asm-generic/pgtable-nopud.h
--- .//include/asm-generic/pgtable-nopud.h 2009-12-03 06:51:21.000000000 +0300
+++ ../linux-2.6.32/include/asm-generic/pgtable-nopud.h 2012-07-22 21:06:48.000000000 +0400
@@ -50,6 +50,7 @@
* allocating and freeing a pud is trivial: the 1-entry pud is
* inside the pgd, so has no extra memory associated with it.
*/
+#define __pud_alloc_one(mm, address, mask) NULL
#define pud_alloc_one(mm, address) NULL
#define pud_free(mm, x) do { } while (0)
#define __pud_free_tlb(tlb, x, a) do { } while (0)
diff -u -r .//include/linux/mm.h ../linux-2.6.32/include/linux/mm.h
--- .//include/linux/mm.h 2012-07-22 20:40:51.000000000 +0400
+++ ../linux-2.6.32/include/linux/mm.h 2012-07-22 21:06:48.000000000 +0400
@@ -1033,44 +1033,60 @@
#ifdef __PAGETABLE_PUD_FOLDED
static inline int __pud_alloc(struct mm_struct *mm, pgd_t *pgd,
- unsigned long address)
+ unsigned long address, gfp_t gfp_mask)
{
return 0;
}
#else
-int __pud_alloc(struct mm_struct *mm, pgd_t *pgd, unsigned long address);
+int __pud_alloc(struct mm_struct *mm, pgd_t *pgd, unsigned long address,
+ gfp_t gfp_mask);
#endif
#ifdef __PAGETABLE_PMD_FOLDED
static inline int __pmd_alloc(struct mm_struct *mm, pud_t *pud,
- unsigned long address)
+ unsigned long address, gfp_t gfp_mask)
{
return 0;
}
#else
-int __pmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long address);
+int __pmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long address,
+ gfp_t gfp_mask);
#endif
int __pte_alloc(struct mm_struct *mm, struct vm_area_struct *vma,
pmd_t *pmd, unsigned long address);
-int __pte_alloc_kernel(pmd_t *pmd, unsigned long address);
+int __pte_alloc_kernel(pmd_t *pmd, unsigned long address, gfp_t gfp_mask);
/*
* The following ifdef needed to get the 4level-fixup.h header to work.
* Remove it when 4level-fixup.h has been removed.
*/
#if defined(CONFIG_MMU) && !defined(__ARCH_HAS_4LEVEL_HACK)
-static inline pud_t *pud_alloc(struct mm_struct *mm, pgd_t *pgd, unsigned long address)
+static inline pud_t *pud_alloc_with_mask(struct mm_struct *mm, pgd_t *pgd,
+ unsigned long address, gfp_t gfp_mask)
{
- return (unlikely(pgd_none(*pgd)) && __pud_alloc(mm, pgd, address))?
+ return (unlikely(pgd_none(*pgd)) && __pud_alloc(mm, pgd, address, gfp_mask))?
NULL: pud_offset(pgd, address);
}
-static inline pmd_t *pmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long address)
+static inline pud_t *pud_alloc(struct mm_struct *mm, pgd_t *pgd,
+ unsigned long address)
{
- return (unlikely(pud_none(*pud)) && __pmd_alloc(mm, pud, address))?
+ return pud_alloc_with_mask(mm, pgd, address, GFP_KERNEL);
+}
+
+static inline pmd_t *pmd_alloc_with_mask(struct mm_struct *mm, pud_t *pud,
+ unsigned long address, gfp_t gfp_mask)
+{
+ return (unlikely(pud_none(*pud)) && __pmd_alloc(mm, pud, address, gfp_mask))?
NULL: pmd_offset(pud, address);
}
+
+static inline pmd_t *pmd_alloc(struct mm_struct *mm, pud_t *pud,
+ unsigned long address)
+{
+ return pmd_alloc_with_mask(mm, pud, address, GFP_KERNEL);
+}
#endif /* CONFIG_MMU && !__ARCH_HAS_4LEVEL_HACK */
#if USE_SPLIT_PTLOCKS
@@ -1131,8 +1147,12 @@
pmd, address))? \
NULL: pte_offset_map_lock(mm, pmd, address, ptlp))
+#define pte_alloc_kernel_with_mask(pmd, address, mask) \
+ ((unlikely(pmd_none(*(pmd))) && __pte_alloc_kernel(pmd, address, mask))? \
+ NULL: pte_offset_kernel(pmd, address))
+
#define pte_alloc_kernel(pmd, address) \
- ((unlikely(pmd_none(*(pmd))) && __pte_alloc_kernel(pmd, address))? \
+ ((unlikely(pmd_none(*(pmd))) && __pte_alloc_kernel(pmd, address, GFP_KERNEL))? \
NULL: pte_offset_kernel(pmd, address))
extern void free_area_init(unsigned long * zones_size);
diff -u -r .//mm/memory.c ../linux-2.6.32/mm/memory.c
--- .//mm/memory.c 2012-07-22 20:40:51.000000000 +0400
+++ ../linux-2.6.32/mm/memory.c 2012-07-22 21:15:59.000000000 +0400
@@ -401,9 +401,9 @@
}
EXPORT_SYMBOL(__pte_alloc);
-int __pte_alloc_kernel(pmd_t *pmd, unsigned long address)
+int __pte_alloc_kernel(pmd_t *pmd, unsigned long address, gfp_t gfp_mask)
{
- pte_t *new = pte_alloc_one_kernel(&init_mm, address);
+ pte_t *new = __pte_alloc_one_kernel(&init_mm, address, gfp_mask);
if (!new)
return -ENOMEM;
@@ -3573,9 +3573,10 @@
* Allocate page upper directory.
* We've already handled the fast-path in-line.
*/
-int __pud_alloc(struct mm_struct *mm, pgd_t *pgd, unsigned long address)
+int __pud_alloc(struct mm_struct *mm, pgd_t *pgd, unsigned long address,
+ gfp_t gfp_mask)
{
- pud_t *new;
+ pud_t *new = __pud_alloc_one(mm, address, gfp_mask);
int one;
one = ub_page_table_get_one(mm);
@@ -3613,9 +3614,10 @@
* Allocate page middle directory.
* We've already handled the fast-path in-line.
*/
-int __pmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long address)
+int __pmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long address,
+ gfp_t gfp_mask)
{
- pmd_t *new;
+ pmd_t *new = __pmd_alloc_one(mm, address, gfp_mask);
int one;
one = ub_page_table_get_one(mm);
diff -u -r .//mm/vmalloc.c ../linux-2.6.32/mm/vmalloc.c
--- .//mm/vmalloc.c 2012-07-22 20:40:51.000000000 +0400
+++ ../linux-2.6.32/mm/vmalloc.c 2012-07-22 21:06:48.000000000 +0400
@@ -90,8 +90,8 @@
} while (pgd++, addr = next, addr != end);
}
-static int vmap_pte_range(pmd_t *pmd, unsigned long addr,
- unsigned long end, pgprot_t prot, struct page **pages, int *nr)
+static int vmap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
+ pgprot_t prot, struct page **pages, int *nr, gfp_t gfp_mask)
{
pte_t *pte;
@@ -100,7 +100,7 @@
* callers keep track of where we're up to.
*/
- pte = pte_alloc_kernel(pmd, addr);
+ pte = pte_alloc_kernel_with_mask(pmd, addr, gfp_mask);
if (!pte)
return -ENOMEM;
do {
@@ -117,34 +117,34 @@
}
static int vmap_pmd_range(pud_t *pud, unsigned long addr,
- unsigned long end, pgprot_t prot, struct page **pages, int *nr)
+ unsigned long end, pgprot_t prot, struct page **pages, int *nr, gfp_t gfp_mask)
{
pmd_t *pmd;
unsigned long next;
- pmd = pmd_alloc(&init_mm, pud, addr);
+ pmd = pmd_alloc_with_mask(&init_mm, pud, addr, gfp_mask);
if (!pmd)
return -ENOMEM;
do {
next = pmd_addr_end(addr, end);
- if (vmap_pte_range(pmd, addr, next, prot, pages, nr))
+ if (vmap_pte_range(pmd, addr, next, prot, pages, nr, gfp_mask))
return -ENOMEM;
} while (pmd++, addr = next, addr != end);
return 0;
}
-static int vmap_pud_range(pgd_t *pgd, unsigned long addr,
- unsigned long end, pgprot_t prot, struct page **pages, int *nr)
+static int vmap_pud_range(pgd_t *pgd, unsigned long addr, unsigned long end,
+ pgprot_t prot, struct page **pages, int *nr, gfp_t gfp_mask)
{
pud_t *pud;
unsigned long next;
- pud = pud_alloc(&init_mm, pgd, addr);
+ pud = pud_alloc_with_mask(&init_mm, pgd, addr, gfp_mask);
if (!pud)
return -ENOMEM;
do {
next = pud_addr_end(addr, end);
- if (vmap_pmd_range(pud, addr, next, prot, pages, nr))
+ if (vmap_pmd_range(pud, addr, next, prot, pages, nr, gfp_mask))
return -ENOMEM;
} while (pud++, addr = next, addr != end);
return 0;
@@ -156,8 +156,8 @@
*
* Ie. pte at addr+N*PAGE_SIZE shall point to pfn corresponding to pages[N]
*/
-static int vmap_page_range_noflush(unsigned long start, unsigned long end,
- pgprot_t prot, struct page **pages)
+static int __vmap_page_range_noflush(unsigned long start, unsigned long end,
+ pgprot_t prot, struct page **pages, gfp_t gfp_mask)
{
pgd_t *pgd;
unsigned long next;
@@ -169,7 +169,7 @@
pgd = pgd_offset_k(addr);
do {
next = pgd_addr_end(addr, end);
- err = vmap_pud_range(pgd, addr, next, prot, pages, &nr);
+ err = vmap_pud_range(pgd, addr, next, prot, pages, &nr, gfp_mask);
if (err)
return err;
} while (pgd++, addr = next, addr != end);
@@ -177,16 +177,29 @@
return nr;
}
-static int vmap_page_range(unsigned long start, unsigned long end,
- pgprot_t prot, struct page **pages)
+
+static int vmap_page_range_noflush(unsigned long start, unsigned long end,
+ pgprot_t prot, struct page **pages)
+{
+ return __vmap_page_range_noflush(start, end, prot, pages, GFP_KERNEL);
+}
+
+static int __vmap_page_range(unsigned long start, unsigned long end,
+ pgprot_t prot, struct page **pages, gfp_t gfp_mask)
{
int ret;
- ret = vmap_page_range_noflush(start, end, prot, pages);
+ ret = __vmap_page_range_noflush(start, end, prot, pages, gfp_mask);
flush_cache_vmap(start, end);
return ret;
}
+static int vmap_page_range(unsigned long start, unsigned long end,
+ pgprot_t prot, struct page **pages)
+{
+ return __vmap_page_range(start, end, prot, pages, GFP_KERNEL);
+}
+
int is_vmalloc_or_module_addr(const void *x)
{
/*
@@ -1196,13 +1209,14 @@
flush_tlb_kernel_range(addr, end);
}
-int map_vm_area(struct vm_struct *area, pgprot_t prot, struct page ***pages)
+int __map_vm_area(struct vm_struct *area, pgprot_t prot,
+ struct page ***pages, gfp_t gfp_mask)
{
unsigned long addr = (unsigned long)area->addr;
unsigned long end = addr + area->size - PAGE_SIZE;
int err;
- err = vmap_page_range(addr, end, prot, *pages);
+ err = __vmap_page_range(addr, end, prot, *pages, gfp_mask);
if (err > 0) {
*pages += err;
err = 0;
@@ -1210,6 +1224,11 @@
return err;
}
+
+int map_vm_area(struct vm_struct *area, pgprot_t prot, struct page ***pages)
+{
+ return __map_vm_area(area, prot, pages, GFP_KERNEL);
+}
EXPORT_SYMBOL_GPL(map_vm_area);
/*** Old vmalloc interfaces ***/
@@ -1534,7 +1553,7 @@
area->pages[i] = page;
}
- if (map_vm_area(area, prot, &pages))
+ if (__map_vm_area(area, prot, &pages, gfp_mask))
goto fail;
inc_vmalloc_charged(area, gfp_mask);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment