From: Stephen Rothwell Date: Mon, 10 Dec 2018 08:16:52 +0000 (+1100) Subject: Merge branch 'akpm-current/current' X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=3b665758b36a7fe38fdcee185fc410766a8fc75a;p=users%2Fwilly%2Flinux.git Merge branch 'akpm-current/current' --- 3b665758b36a7fe38fdcee185fc410766a8fc75a diff --cc arch/powerpc/include/asm/book3s/32/pgalloc.h index b5b955eb2fb7,af9e13555d95..3633502e102c --- a/arch/powerpc/include/asm/book3s/32/pgalloc.h +++ b/arch/powerpc/include/asm/book3s/32/pgalloc.h @@@ -56,16 -61,29 +56,16 @@@ static inline void pmd_populate_kernel( static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmdp, pgtable_t pte_page) { - *pmdp = __pmd((page_to_pfn(pte_page) << PAGE_SHIFT) | _PMD_PRESENT); -} - -#define pmd_pgtable(pmd) pmd_page(pmd) -#else - -static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmdp, - pte_t *pte) -{ - *pmdp = __pmd((unsigned long)pte | _PMD_PRESENT); -} - -static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmdp, - pgtable_t pte_page) -{ - *pmdp = __pmd((unsigned long)lowmem_page_address(pte_page) | _PMD_PRESENT); + *pmdp = __pmd(__pa(pte_page) | _PMD_PRESENT); } -#define pmd_pgtable(pmd) pmd_page(pmd) -#endif +#define pmd_pgtable(pmd) ((pgtable_t)pmd_page_vaddr(pmd)) - extern pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr); - extern pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long addr); + extern pte_t *pte_alloc_one_kernel(struct mm_struct *mm); + extern pgtable_t pte_alloc_one(struct mm_struct *mm); +void pte_frag_destroy(void *pte_frag); - pte_t *pte_fragment_alloc(struct mm_struct *mm, unsigned long vmaddr, int kernel); ++pte_t *pte_fragment_alloc(struct mm_struct *mm, int kernel); +void pte_fragment_free(unsigned long *table, int kernel); static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte) { diff --cc arch/powerpc/include/asm/book3s/64/pgalloc.h index 4aba625389c4,8f1d92e99fe5..9c1173283b96 --- a/arch/powerpc/include/asm/book3s/64/pgalloc.h +++ b/arch/powerpc/include/asm/book3s/64/pgalloc.h @@@ -37,9 -37,12 +37,9 @@@ extern struct vmemmap_backing *vmemmap_ #define MAX_PGTABLE_INDEX_SIZE 0xf extern struct kmem_cache *pgtable_cache[]; -#define PGT_CACHE(shift) ({ \ - BUG_ON(!(shift)); \ - pgtable_cache[(shift) - 1]; \ - }) +#define PGT_CACHE(shift) pgtable_cache[shift] - extern pte_t *pte_fragment_alloc(struct mm_struct *, unsigned long, int); + extern pte_t *pte_fragment_alloc(struct mm_struct *, int); extern pmd_t *pmd_fragment_alloc(struct mm_struct *, unsigned long); extern void pte_fragment_free(unsigned long *, int); extern void pmd_fragment_free(unsigned long *); diff --cc arch/powerpc/include/asm/nohash/32/pgalloc.h index 17963951bdb0,16623f53f0d4..bd186e85b4f7 --- a/arch/powerpc/include/asm/nohash/32/pgalloc.h +++ b/arch/powerpc/include/asm/nohash/32/pgalloc.h @@@ -73,17 -77,14 +73,17 @@@ static inline void pmd_populate_kernel( static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmdp, pgtable_t pte_page) { - *pmdp = __pmd((unsigned long)lowmem_page_address(pte_page) | _PMD_PRESENT); + *pmdp = __pmd((unsigned long)pte_page | _PMD_PRESENT); } -#define pmd_pgtable(pmd) pmd_page(pmd) +#define pmd_pgtable(pmd) ((pgtable_t)pmd_page_vaddr(pmd)) #endif - extern pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr); - extern pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long addr); + extern pte_t *pte_alloc_one_kernel(struct mm_struct *mm); + extern pgtable_t pte_alloc_one(struct mm_struct *mm); +void pte_frag_destroy(void *pte_frag); - pte_t *pte_fragment_alloc(struct mm_struct *mm, unsigned long vmaddr, int kernel); ++pte_t *pte_fragment_alloc(struct mm_struct *mm, int kernel); +void pte_fragment_free(unsigned long *table, int kernel); static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte) { diff --cc arch/powerpc/mm/pgtable-frag.c index af23a587f019,000000000000..a7b05214760c mode 100644,000000..100644 --- a/arch/powerpc/mm/pgtable-frag.c +++ b/arch/powerpc/mm/pgtable-frag.c @@@ -1,119 -1,0 +1,119 @@@ +// SPDX-License-Identifier: GPL-2.0 + +/* + * Handling Page Tables through page fragments + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void pte_frag_destroy(void *pte_frag) +{ + int count; + struct page *page; + + page = virt_to_page(pte_frag); + /* drop all the pending references */ + count = ((unsigned long)pte_frag & ~PAGE_MASK) >> PTE_FRAG_SIZE_SHIFT; + /* We allow PTE_FRAG_NR fragments from a PTE page */ + if (atomic_sub_and_test(PTE_FRAG_NR - count, &page->pt_frag_refcount)) { + pgtable_page_dtor(page); + __free_page(page); + } +} + +static pte_t *get_pte_from_cache(struct mm_struct *mm) +{ + void *pte_frag, *ret; + + if (PTE_FRAG_NR == 1) + return NULL; + + spin_lock(&mm->page_table_lock); + ret = pte_frag_get(&mm->context); + if (ret) { + pte_frag = ret + PTE_FRAG_SIZE; + /* + * If we have taken up all the fragments mark PTE page NULL + */ + if (((unsigned long)pte_frag & ~PAGE_MASK) == 0) + pte_frag = NULL; + pte_frag_set(&mm->context, pte_frag); + } + spin_unlock(&mm->page_table_lock); + return (pte_t *)ret; +} + +static pte_t *__alloc_for_ptecache(struct mm_struct *mm, int kernel) +{ + void *ret = NULL; + struct page *page; + + if (!kernel) { + page = alloc_page(PGALLOC_GFP | __GFP_ACCOUNT); + if (!page) + return NULL; + if (!pgtable_page_ctor(page)) { + __free_page(page); + return NULL; + } + } else { + page = alloc_page(PGALLOC_GFP); + if (!page) + return NULL; + } + + atomic_set(&page->pt_frag_refcount, 1); + + ret = page_address(page); + /* + * if we support only one fragment just return the + * allocated page. + */ + if (PTE_FRAG_NR == 1) + return ret; + spin_lock(&mm->page_table_lock); + /* + * If we find pgtable_page set, we return + * the allocated page with single fragement + * count. + */ + if (likely(!pte_frag_get(&mm->context))) { + atomic_set(&page->pt_frag_refcount, PTE_FRAG_NR); + pte_frag_set(&mm->context, ret + PTE_FRAG_SIZE); + } + spin_unlock(&mm->page_table_lock); + + return (pte_t *)ret; +} + - pte_t *pte_fragment_alloc(struct mm_struct *mm, unsigned long vmaddr, int kernel) ++pte_t *pte_fragment_alloc(struct mm_struct *mm, int kernel) +{ + pte_t *pte; + + pte = get_pte_from_cache(mm); + if (pte) + return pte; + + return __alloc_for_ptecache(mm, kernel); +} + +void pte_fragment_free(unsigned long *table, int kernel) +{ + struct page *page = virt_to_page(table); + + BUG_ON(atomic_read(&page->pt_frag_refcount) <= 0); + if (atomic_dec_and_test(&page->pt_frag_refcount)) { + if (!kernel) + pgtable_page_dtor(page); + __free_page(page); + } +} diff --cc arch/powerpc/mm/pgtable_32.c index 4fc77a99c9bf,1d8e2d98db98..5b1e1adeb4d2 --- a/arch/powerpc/mm/pgtable_32.c +++ b/arch/powerpc/mm/pgtable_32.c @@@ -43,17 -43,34 +43,17 @@@ EXPORT_SYMBOL(ioremap_bot); /* aka VMAL extern char etext[], _stext[], _sinittext[], _einittext[]; - __ref pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address) + __ref pte_t *pte_alloc_one_kernel(struct mm_struct *mm) { - pte_t *pte; + if (!slab_is_available()) + return memblock_alloc(PTE_FRAG_SIZE, PTE_FRAG_SIZE); - return (pte_t *)pte_fragment_alloc(mm, address, 1); - if (slab_is_available()) { - pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_ZERO); - } else { - pte = __va(memblock_phys_alloc(PAGE_SIZE, PAGE_SIZE)); - if (pte) - clear_page(pte); - } - return pte; ++ return (pte_t *)pte_fragment_alloc(mm, 1); } - pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long address) + pgtable_t pte_alloc_one(struct mm_struct *mm) { - return (pgtable_t)pte_fragment_alloc(mm, address, 0); - struct page *ptepage; - - gfp_t flags = GFP_KERNEL | __GFP_ZERO | __GFP_ACCOUNT; - - ptepage = alloc_pages(flags, 0); - if (!ptepage) - return NULL; - if (!pgtable_page_ctor(ptepage)) { - __free_page(ptepage); - return NULL; - } - return ptepage; ++ return (pgtable_t)pte_fragment_alloc(mm, 0); } void __iomem * diff --cc fs/autofs/init.c index d0b80ff8afcb,c0c1db2cc6ea..9d815c71b5cd --- a/fs/autofs/init.c +++ b/fs/autofs/init.c @@@ -11,12 -11,12 +11,12 @@@ #include "autofs_i.h" static struct dentry *autofs_mount(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) + int flags, const char *dev_name, void *data, size_t data_size) { - return mount_nodev(fs_type, flags, data, autofs_fill_super); + return mount_nodev(fs_type, flags, data, data_size, autofs_fill_super); } - static struct file_system_type autofs_fs_type = { + struct file_system_type autofs_fs_type = { .owner = THIS_MODULE, .name = "autofs", .mount = autofs_mount, diff --cc fs/autofs/inode.c index 93e014d7f813,501833cc49a8..d38b82c4f310 --- a/fs/autofs/inode.c +++ b/fs/autofs/inode.c @@@ -198,11 -210,10 +210,11 @@@ static int parse_options(char *options return 1; } } - return (*pipefd < 0); + return (sbi->pipefd < 0); } -int autofs_fill_super(struct super_block *s, void *data, int silent) +int autofs_fill_super(struct super_block *s, void *data, size_t data_size, + int silent) { struct inode *root_inode; struct dentry *root; diff --cc kernel/sysctl.c index 5fc724e4e454,2f445c82fe38..93352cfb3239 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@@ -1471,6 -1487,15 +1487,17 @@@ static struct ctl_table vm_table[] = .extra1 = &one, .extra2 = &one_thousand, }, ++#ifdef CONFIG_NUMA + { + .procname = "fragment_stall_order", + .data = &fragment_stall_order, + .maxlen = sizeof(fragment_stall_order), + .mode = 0644, + .proc_handler = fragment_stall_order_sysctl_handler, + .extra1 = &zero, + .extra2 = &max_order, + }, ++#endif { .procname = "percpu_pagelist_fraction", .data = &percpu_pagelist_fraction,