Re: [RFC][PATCH v3 10/22] mm, powerpc: add gfp flags variant of pud, pte, and pte allocations

2011-03-18 Thread Prasad Joshi

changes for 32 bit architecture
 - Added __pte_alloc_one_kernel() to allocated zeroed page using
   allocation flag passed as an argument. If the slab allocator is not
   initialized the allocation flag is not passed down the call hierarchy.
   i.e. the call to early_get_page() is not modified.

- Changed pte_alloc_one_kernel() to call __pte_alloc_one_kernel() passing
  correct gfp_t flags.

changes for 64 bit architecture
- Added __pud_alloc_one() which is similar to pud_alloc_one(). This newly
  added function accepts allocation flag as a parameter and does the PUD
  allocation using this GFP flag.

- The function pud_alloc_one() is changed to call __pud_alloc_one() passing
  GFP_KERNEL | __GFP_REPEAT allocation flags.

- Similar changes for pmd (cache) and pte (page) allocations.

- The changes for both architectures help in fixing Bug 30702

Signed-off-by: Prasad Joshi prasadjoshi...@gmail.com
Signed-off-by: Anand Mitra mi...@kqinfotech.com
---
 arch/powerpc/include/asm/pgalloc-32.h |2 ++
 arch/powerpc/include/asm/pgalloc-64.h |   27 ++-
 arch/powerpc/mm/pgtable_32.c  |   10 --
 3 files changed, 32 insertions(+), 7 deletions(-)

diff --git a/arch/powerpc/include/asm/pgalloc-32.h 
b/arch/powerpc/include/asm/pgalloc-32.h
index 580cf73..21b7a94 100644
--- a/arch/powerpc/include/asm/pgalloc-32.h
+++ b/arch/powerpc/include/asm/pgalloc-32.h
@@ -35,6 +35,8 @@ extern void pgd_free(struct mm_struct *mm, pgd_t *pgd);
 #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(void *table, unsigned index_size)
diff --git a/arch/powerpc/include/asm/pgalloc-64.h 
b/arch/powerpc/include/asm/pgalloc-64.h
index 292725c..e5ea650 100644
--- a/arch/powerpc/include/asm/pgalloc-64.h
+++ b/arch/powerpc/include/asm/pgalloc-64.h
@@ -51,10 +51,15 @@ static inline void pgd_free(struct mm_struct *mm, pgd_t 
*pgd)
 
 #define pgd_populate(MM, PGD, PUD) pgd_set(PGD, PUD)
 
+static inline pud_t *
+__pud_alloc_one(struct mm_struct *mm, unsigned long addr, gfp_t gfp_mask)
+{
+   return kmem_cache_alloc(PGT_CACHE(PUD_INDEX_SIZE), gfp_mask);
+}
+
 static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr)
 {
-   return kmem_cache_alloc(PGT_CACHE(PUD_INDEX_SIZE),
-   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)
@@ -89,10 +94,15 @@ static inline void pmd_populate_kernel(struct mm_struct 
*mm, pmd_t *pmd,
 
 #endif /* CONFIG_PPC_64K_PAGES */
 
+static inline pmd_t *
+__pmd_alloc_one(struct mm_struct *mm, unsigned long addr, gfp_t gfp_mask)
+{
+   return kmem_cache_alloc(PGT_CACHE(PMD_INDEX_SIZE), gfp_mask);
+}
+
 static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
 {
-   return kmem_cache_alloc(PGT_CACHE(PMD_INDEX_SIZE),
-   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)
@@ -100,10 +110,17 @@ static inline void pmd_free(struct mm_struct *mm, pmd_t 
*pmd)
kmem_cache_free(PGT_CACHE(PMD_INDEX_SIZE), pmd);
 }
 
+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)
 {
-return (pte_t *)__get_free_page(GFP_KERNEL | __GFP_REPEAT | 
__GFP_ZERO);
+   return __pte_alloc_one_kernel(mm, address, GFP_KERNEL | __GFP_REPEAT);
 }
 
 static inline pgtable_t pte_alloc_one(struct mm_struct *mm,
diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c
index 8dc41c0..736593f 100644
--- a/arch/powerpc/mm/pgtable_32.c
+++ b/arch/powerpc/mm/pgtable_32.c
@@ -95,14 +95,15 @@ void pgd_free(struct mm_struct *mm, pgd_t *pgd)
 #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)
@@ -111,6 +112,11 @@ __init_refok pte_t *pte_alloc_one_kernel(struct mm_struct 
*mm, unsigned long add
return pte;
 }
 
+__init_refok pte_t

[RFC][PATCH v3 00/22] __vmalloc: Propagating GFP allocation flag inside __vmalloc()

2011-03-18 Thread Prasad Joshi
A filesystem might run into a problem while calling __vmalloc(GFP_NOFS)
inside a lock.

It is expected than __vmalloc when called with GFP_NOFS should not
callback the filesystem code even incase of the increased memory
pressure. But the problem is that even if we pass this flag, __vmalloc
itself allocates memory with GFP_KERNEL.

Using GFP_KERNEL allocations may go into the memory reclaim path and try
to free memory by calling file system evict_inode function. Which might
lead into deadlock.

For further details
http://marc.info/?l=linux-mmm=128942194520631w=4
https://bugzilla.kernel.org/show_bug.cgi?id=30702

The patch passes the gfp allocation flag all the way down to those
allocating functions.

 arch/arm/include/asm/pgalloc.h   |   11 +-
 arch/avr32/include/asm/pgalloc.h |8 -
 arch/cris/include/asm/pgalloc.h  |   10 -
 arch/frv/include/asm/pgalloc.h   |3 ++
 arch/frv/include/asm/pgtable.h   |1 +
 arch/frv/mm/pgalloc.c|9 -
 arch/ia64/include/asm/pgalloc.h  |   24 +++--
 arch/m32r/include/asm/pgalloc.h  |   11 --
 arch/m68k/include/asm/motorola_pgalloc.h |   20 +--
 arch/m68k/include/asm/sun3_pgalloc.h |   14 ++--
 arch/m68k/mm/memory.c|9 -
 arch/microblaze/include/asm/pgalloc.h|3 ++
 arch/microblaze/mm/pgtable.c |   13 +--
 arch/mips/include/asm/pgalloc.h  |   22 
 arch/mn10300/include/asm/pgalloc.h   |2 +
 arch/mn10300/mm/pgtable.c|   10 -
 arch/parisc/include/asm/pgalloc.h|   21 ---
 arch/powerpc/include/asm/pgalloc-32.h|2 +
 arch/powerpc/include/asm/pgalloc-64.h|   27 +++---
 arch/powerpc/mm/pgtable_32.c |   10 -
 arch/s390/include/asm/pgalloc.h  |   30 +---
 arch/s390/mm/pgtable.c   |   22 +---
 arch/score/include/asm/pgalloc.h |   13 ---
 arch/sh/include/asm/pgalloc.h|8 -
 arch/sh/mm/pgtable.c |8 -
 arch/sparc/include/asm/pgalloc_32.h  |5 +++
 arch/sparc/include/asm/pgalloc_64.h  |   17 -
 arch/tile/include/asm/pgalloc.h  |   13 ++-
 arch/tile/mm/pgtable.c   |   10 -
 arch/um/include/asm/pgalloc.h|1 +
 arch/um/kernel/mem.c |   21 ---
 arch/x86/include/asm/pgalloc.h   |   17 -
 arch/x86/mm/pgtable.c|8 -
 arch/xtensa/include/asm/pgalloc.h|9 -
 arch/xtensa/mm/pgtable.c |   11 +-
 include/asm-generic/4level-fixup.h   |8 +++-
 include/asm-generic/pgtable-nopmd.h  |3 +-
 include/asm-generic/pgtable-nopud.h  |1 +
 include/linux/mm.h   |   40 -
 mm/memory.c  |   14 ---
 mm/vmalloc.c |   57 --
 41 files changed, 427 insertions(+), 119 deletions(-)

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[RFC][PATCH v2 00/23] __vmalloc: Propagating GFP allocation flag inside __vmalloc().

2011-03-14 Thread Prasad Joshi
A filesystem might run into a problem while calling
__vmalloc(GFP_NOFS) inside a lock.

It is expected than __vmalloc when called with GFP_NOFS should not
callback the filesystem code even incase of the increased memory
pressure. But the problem is that even if we pass this flag, __vmalloc
itself allocates memory with GFP_KERNEL.

Using GFP_KERNEL allocations may go into the memory reclaim path and
try to free memory by calling file system evict_inode function. Which
might lead into deadlock.

For further details
http://marc.info/?l=linux-mmm=128942194520631w=4
https://bugzilla.kernel.org/show_bug.cgi?id=30702

The patch passes the gfp allocation flag all the way down to those
allocating functions.

 arch/alpha/include/asm/pgalloc.h |   18 +++--
 arch/arm/include/asm/pgalloc.h   |   11 +-
 arch/avr32/include/asm/pgalloc.h |8 -
 arch/cris/include/asm/pgalloc.h  |   10 -
 arch/frv/include/asm/pgalloc.h   |3 ++
 arch/frv/include/asm/pgtable.h   |1 +
 arch/frv/mm/pgalloc.c|9 -
 arch/ia64/include/asm/pgalloc.h  |   24 +++--
 arch/m32r/include/asm/pgalloc.h  |   11 --
 arch/m68k/include/asm/motorola_pgalloc.h |   20 +--
 arch/m68k/include/asm/sun3_pgalloc.h |   14 ++--
 arch/m68k/mm/memory.c|9 -
 arch/microblaze/include/asm/pgalloc.h|3 ++
 arch/microblaze/mm/pgtable.c |   13 +--
 arch/mips/include/asm/pgalloc.h  |   22 
 arch/mn10300/include/asm/pgalloc.h   |2 +
 arch/mn10300/mm/pgtable.c|   10 -
 arch/parisc/include/asm/pgalloc.h|   21 ---
 arch/powerpc/include/asm/pgalloc-32.h|2 +
 arch/powerpc/include/asm/pgalloc-64.h|   27 +++---
 arch/powerpc/mm/pgtable_32.c |   10 -
 arch/s390/include/asm/pgalloc.h  |   30 +---
 arch/s390/mm/pgtable.c   |   22 +---
 arch/score/include/asm/pgalloc.h |   13 ---
 arch/sh/include/asm/pgalloc.h|8 -
 arch/sh/mm/pgtable.c |8 -
 arch/sparc/include/asm/pgalloc_32.h  |5 +++
 arch/sparc/include/asm/pgalloc_64.h  |   17 -
 arch/tile/include/asm/pgalloc.h  |   13 ++-
 arch/tile/mm/pgtable.c   |   10 -
 arch/um/include/asm/pgalloc.h|1 +
 arch/um/kernel/mem.c |   21 ---
 arch/x86/include/asm/pgalloc.h   |   17 -
 arch/x86/mm/pgtable.c|8 -
 arch/xtensa/include/asm/pgalloc.h|9 -
 arch/xtensa/mm/pgtable.c |   11 +-
 include/asm-generic/4level-fixup.h   |8 +++-
 include/asm-generic/pgtable-nopmd.h  |3 +-
 include/asm-generic/pgtable-nopud.h  |1 +
 include/linux/mm.h   |   40 -
 mm/memory.c  |   14 ---
 mm/vmalloc.c |   57 --
 42 files changed, 441 insertions(+), 123 deletions(-)
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[RFC][PATCH v2 23/23] __vmalloc: add gfp flags variant of pte, pmd, and pud allocation

2011-03-14 Thread Prasad Joshi
__vmalloc: propagating GFP allocation flag.

- Added __map_vm_area, __vmap_page_range, __vmap_page_range_noflush
to accept the gfp_t allocation flag
- Added pud_alloc_with_mask(), similar to pud_alloc(), but also
accepts allocation flag
- Added pmd_alloc_with_mask
- Added pte_alloc_kernel_with_mask
- Modified __pte_alloc_kernel to accept allocation flag
- Every architecture has to add a function
__pte_alloc_one_kernel(struct mm_struct*, unsigned long, gfp_t)
- Modified __pmd_alloc to accept the allocation flag
- Every architecture has to add a function __pmd_alloc_one(struct
mm_struct *, unsigned long, gfp_t)
- Changed __pud_alloc to accepts gfp allocation flag
- Every architecture that uses pud has to add a function
__pud_alloc_one(struct mm_struct *, unsigned long, gfp_t)
- fixes the Bug 30702 (__vmalloc(GFP_NOFS) can callback file system
  evict_inode).

Signed-off-by: Anand Mitra mi...@kqinfotech.com
Signed-off-by: Prasad Joshi prasadjoshi...@gmail.com
---
Chnagelog:
include/linux/mm.h |   40 +++-
mm/memory.c|   14 +++-
mm/vmalloc.c   |   57 ++-
3 files changed, 76 insertions(+), 35 deletions(-)
---
diff --git a/include/linux/mm.h b/include/linux/mm.h
index f6385fc..5ff89df 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -1156,44 +1156,60 @@ static inline pte_t *get_locked_pte(struct
mm_struct *mm, unsigned long addr,

 #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
@@ -1254,8 +1270,12 @@ static inline void pgtable_page_dtor(struct page *page)
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 --git a/mm/memory.c b/mm/memory.c
index 5823698..dc4964e 100644