diff options
Diffstat (limited to 'mm/memory.c')
-rw-r--r-- | mm/memory.c | 196 |
1 files changed, 48 insertions, 148 deletions
diff --git a/mm/memory.c b/mm/memory.c index d902d0e25edc..7bb70728bb52 100644 --- a/mm/memory.c +++ b/mm/memory.c | |||
@@ -305,7 +305,7 @@ int __pte_alloc(struct mm_struct *mm, pmd_t *pmd, unsigned long address) | |||
305 | spin_lock(&mm->page_table_lock); | 305 | spin_lock(&mm->page_table_lock); |
306 | if (pmd_present(*pmd)) { /* Another has populated it */ | 306 | if (pmd_present(*pmd)) { /* Another has populated it */ |
307 | pte_lock_deinit(new); | 307 | pte_lock_deinit(new); |
308 | pte_free(new); | 308 | pte_free(mm, new); |
309 | } else { | 309 | } else { |
310 | mm->nr_ptes++; | 310 | mm->nr_ptes++; |
311 | inc_zone_page_state(new, NR_PAGETABLE); | 311 | inc_zone_page_state(new, NR_PAGETABLE); |
@@ -323,7 +323,7 @@ int __pte_alloc_kernel(pmd_t *pmd, unsigned long address) | |||
323 | 323 | ||
324 | spin_lock(&init_mm.page_table_lock); | 324 | spin_lock(&init_mm.page_table_lock); |
325 | if (pmd_present(*pmd)) /* Another has populated it */ | 325 | if (pmd_present(*pmd)) /* Another has populated it */ |
326 | pte_free_kernel(new); | 326 | pte_free_kernel(&init_mm, new); |
327 | else | 327 | else |
328 | pmd_populate_kernel(&init_mm, pmd, new); | 328 | pmd_populate_kernel(&init_mm, pmd, new); |
329 | spin_unlock(&init_mm.page_table_lock); | 329 | spin_unlock(&init_mm.page_table_lock); |
@@ -1109,7 +1109,8 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, | |||
1109 | } | 1109 | } |
1110 | EXPORT_SYMBOL(get_user_pages); | 1110 | EXPORT_SYMBOL(get_user_pages); |
1111 | 1111 | ||
1112 | pte_t * fastcall get_locked_pte(struct mm_struct *mm, unsigned long addr, spinlock_t **ptl) | 1112 | pte_t *get_locked_pte(struct mm_struct *mm, unsigned long addr, |
1113 | spinlock_t **ptl) | ||
1113 | { | 1114 | { |
1114 | pgd_t * pgd = pgd_offset(mm, addr); | 1115 | pgd_t * pgd = pgd_offset(mm, addr); |
1115 | pud_t * pud = pud_alloc(mm, pgd, addr); | 1116 | pud_t * pud = pud_alloc(mm, pgd, addr); |
@@ -1517,10 +1518,8 @@ static inline void cow_user_page(struct page *dst, struct page *src, unsigned lo | |||
1517 | memset(kaddr, 0, PAGE_SIZE); | 1518 | memset(kaddr, 0, PAGE_SIZE); |
1518 | kunmap_atomic(kaddr, KM_USER0); | 1519 | kunmap_atomic(kaddr, KM_USER0); |
1519 | flush_dcache_page(dst); | 1520 | flush_dcache_page(dst); |
1520 | return; | 1521 | } else |
1521 | 1522 | copy_user_highpage(dst, src, va, vma); | |
1522 | } | ||
1523 | copy_user_highpage(dst, src, va, vma); | ||
1524 | } | 1523 | } |
1525 | 1524 | ||
1526 | /* | 1525 | /* |
@@ -1629,6 +1628,7 @@ gotten: | |||
1629 | if (!new_page) | 1628 | if (!new_page) |
1630 | goto oom; | 1629 | goto oom; |
1631 | cow_user_page(new_page, old_page, address, vma); | 1630 | cow_user_page(new_page, old_page, address, vma); |
1631 | __SetPageUptodate(new_page); | ||
1632 | 1632 | ||
1633 | /* | 1633 | /* |
1634 | * Re-check the pte - we dropped the lock | 1634 | * Re-check the pte - we dropped the lock |
@@ -1909,50 +1909,49 @@ EXPORT_SYMBOL(unmap_mapping_range); | |||
1909 | */ | 1909 | */ |
1910 | int vmtruncate(struct inode * inode, loff_t offset) | 1910 | int vmtruncate(struct inode * inode, loff_t offset) |
1911 | { | 1911 | { |
1912 | struct address_space *mapping = inode->i_mapping; | 1912 | if (inode->i_size < offset) { |
1913 | unsigned long limit; | 1913 | unsigned long limit; |
1914 | 1914 | ||
1915 | if (inode->i_size < offset) | 1915 | limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur; |
1916 | goto do_expand; | 1916 | if (limit != RLIM_INFINITY && offset > limit) |
1917 | /* | 1917 | goto out_sig; |
1918 | * truncation of in-use swapfiles is disallowed - it would cause | 1918 | if (offset > inode->i_sb->s_maxbytes) |
1919 | * subsequent swapout to scribble on the now-freed blocks. | 1919 | goto out_big; |
1920 | */ | 1920 | i_size_write(inode, offset); |
1921 | if (IS_SWAPFILE(inode)) | 1921 | } else { |
1922 | goto out_busy; | 1922 | struct address_space *mapping = inode->i_mapping; |
1923 | i_size_write(inode, offset); | 1923 | |
1924 | /* | ||
1925 | * truncation of in-use swapfiles is disallowed - it would | ||
1926 | * cause subsequent swapout to scribble on the now-freed | ||
1927 | * blocks. | ||
1928 | */ | ||
1929 | if (IS_SWAPFILE(inode)) | ||
1930 | return -ETXTBSY; | ||
1931 | i_size_write(inode, offset); | ||
1932 | |||
1933 | /* | ||
1934 | * unmap_mapping_range is called twice, first simply for | ||
1935 | * efficiency so that truncate_inode_pages does fewer | ||
1936 | * single-page unmaps. However after this first call, and | ||
1937 | * before truncate_inode_pages finishes, it is possible for | ||
1938 | * private pages to be COWed, which remain after | ||
1939 | * truncate_inode_pages finishes, hence the second | ||
1940 | * unmap_mapping_range call must be made for correctness. | ||
1941 | */ | ||
1942 | unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1); | ||
1943 | truncate_inode_pages(mapping, offset); | ||
1944 | unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1); | ||
1945 | } | ||
1924 | 1946 | ||
1925 | /* | ||
1926 | * unmap_mapping_range is called twice, first simply for efficiency | ||
1927 | * so that truncate_inode_pages does fewer single-page unmaps. However | ||
1928 | * after this first call, and before truncate_inode_pages finishes, | ||
1929 | * it is possible for private pages to be COWed, which remain after | ||
1930 | * truncate_inode_pages finishes, hence the second unmap_mapping_range | ||
1931 | * call must be made for correctness. | ||
1932 | */ | ||
1933 | unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1); | ||
1934 | truncate_inode_pages(mapping, offset); | ||
1935 | unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1); | ||
1936 | goto out_truncate; | ||
1937 | |||
1938 | do_expand: | ||
1939 | limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur; | ||
1940 | if (limit != RLIM_INFINITY && offset > limit) | ||
1941 | goto out_sig; | ||
1942 | if (offset > inode->i_sb->s_maxbytes) | ||
1943 | goto out_big; | ||
1944 | i_size_write(inode, offset); | ||
1945 | |||
1946 | out_truncate: | ||
1947 | if (inode->i_op && inode->i_op->truncate) | 1947 | if (inode->i_op && inode->i_op->truncate) |
1948 | inode->i_op->truncate(inode); | 1948 | inode->i_op->truncate(inode); |
1949 | return 0; | 1949 | return 0; |
1950 | |||
1950 | out_sig: | 1951 | out_sig: |
1951 | send_sig(SIGXFSZ, current, 0); | 1952 | send_sig(SIGXFSZ, current, 0); |
1952 | out_big: | 1953 | out_big: |
1953 | return -EFBIG; | 1954 | return -EFBIG; |
1954 | out_busy: | ||
1955 | return -ETXTBSY; | ||
1956 | } | 1955 | } |
1957 | EXPORT_SYMBOL(vmtruncate); | 1956 | EXPORT_SYMBOL(vmtruncate); |
1958 | 1957 | ||
@@ -1980,67 +1979,6 @@ int vmtruncate_range(struct inode *inode, loff_t offset, loff_t end) | |||
1980 | return 0; | 1979 | return 0; |
1981 | } | 1980 | } |
1982 | 1981 | ||
1983 | /** | ||
1984 | * swapin_readahead - swap in pages in hope we need them soon | ||
1985 | * @entry: swap entry of this memory | ||
1986 | * @addr: address to start | ||
1987 | * @vma: user vma this addresses belong to | ||
1988 | * | ||
1989 | * Primitive swap readahead code. We simply read an aligned block of | ||
1990 | * (1 << page_cluster) entries in the swap area. This method is chosen | ||
1991 | * because it doesn't cost us any seek time. We also make sure to queue | ||
1992 | * the 'original' request together with the readahead ones... | ||
1993 | * | ||
1994 | * This has been extended to use the NUMA policies from the mm triggering | ||
1995 | * the readahead. | ||
1996 | * | ||
1997 | * Caller must hold down_read on the vma->vm_mm if vma is not NULL. | ||
1998 | */ | ||
1999 | void swapin_readahead(swp_entry_t entry, unsigned long addr,struct vm_area_struct *vma) | ||
2000 | { | ||
2001 | #ifdef CONFIG_NUMA | ||
2002 | struct vm_area_struct *next_vma = vma ? vma->vm_next : NULL; | ||
2003 | #endif | ||
2004 | int i, num; | ||
2005 | struct page *new_page; | ||
2006 | unsigned long offset; | ||
2007 | |||
2008 | /* | ||
2009 | * Get the number of handles we should do readahead io to. | ||
2010 | */ | ||
2011 | num = valid_swaphandles(entry, &offset); | ||
2012 | for (i = 0; i < num; offset++, i++) { | ||
2013 | /* Ok, do the async read-ahead now */ | ||
2014 | new_page = read_swap_cache_async(swp_entry(swp_type(entry), | ||
2015 | offset), vma, addr); | ||
2016 | if (!new_page) | ||
2017 | break; | ||
2018 | page_cache_release(new_page); | ||
2019 | #ifdef CONFIG_NUMA | ||
2020 | /* | ||
2021 | * Find the next applicable VMA for the NUMA policy. | ||
2022 | */ | ||
2023 | addr += PAGE_SIZE; | ||
2024 | if (addr == 0) | ||
2025 | vma = NULL; | ||
2026 | if (vma) { | ||
2027 | if (addr >= vma->vm_end) { | ||
2028 | vma = next_vma; | ||
2029 | next_vma = vma ? vma->vm_next : NULL; | ||
2030 | } | ||
2031 | if (vma && addr < vma->vm_start) | ||
2032 | vma = NULL; | ||
2033 | } else { | ||
2034 | if (next_vma && addr >= next_vma->vm_start) { | ||
2035 | vma = next_vma; | ||
2036 | next_vma = vma->vm_next; | ||
2037 | } | ||
2038 | } | ||
2039 | #endif | ||
2040 | } | ||
2041 | lru_add_drain(); /* Push any new pages onto the LRU now */ | ||
2042 | } | ||
2043 | |||
2044 | /* | 1982 | /* |
2045 | * We enter with non-exclusive mmap_sem (to exclude vma changes, | 1983 | * We enter with non-exclusive mmap_sem (to exclude vma changes, |
2046 | * but allow concurrent faults), and pte mapped but not yet locked. | 1984 | * but allow concurrent faults), and pte mapped but not yet locked. |
@@ -2068,8 +2006,8 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
2068 | page = lookup_swap_cache(entry); | 2006 | page = lookup_swap_cache(entry); |
2069 | if (!page) { | 2007 | if (!page) { |
2070 | grab_swap_token(); /* Contend for token _before_ read-in */ | 2008 | grab_swap_token(); /* Contend for token _before_ read-in */ |
2071 | swapin_readahead(entry, address, vma); | 2009 | page = swapin_readahead(entry, |
2072 | page = read_swap_cache_async(entry, vma, address); | 2010 | GFP_HIGHUSER_MOVABLE, vma, address); |
2073 | if (!page) { | 2011 | if (!page) { |
2074 | /* | 2012 | /* |
2075 | * Back out if somebody else faulted in this pte | 2013 | * Back out if somebody else faulted in this pte |
@@ -2163,6 +2101,7 @@ static int do_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
2163 | page = alloc_zeroed_user_highpage_movable(vma, address); | 2101 | page = alloc_zeroed_user_highpage_movable(vma, address); |
2164 | if (!page) | 2102 | if (!page) |
2165 | goto oom; | 2103 | goto oom; |
2104 | __SetPageUptodate(page); | ||
2166 | 2105 | ||
2167 | entry = mk_pte(page, vma->vm_page_prot); | 2106 | entry = mk_pte(page, vma->vm_page_prot); |
2168 | entry = maybe_mkwrite(pte_mkdirty(entry), vma); | 2107 | entry = maybe_mkwrite(pte_mkdirty(entry), vma); |
@@ -2263,6 +2202,7 @@ static int __do_fault(struct mm_struct *mm, struct vm_area_struct *vma, | |||
2263 | goto out; | 2202 | goto out; |
2264 | } | 2203 | } |
2265 | copy_user_highpage(page, vmf.page, address, vma); | 2204 | copy_user_highpage(page, vmf.page, address, vma); |
2205 | __SetPageUptodate(page); | ||
2266 | } else { | 2206 | } else { |
2267 | /* | 2207 | /* |
2268 | * If the page will be shareable, see if the backing | 2208 | * If the page will be shareable, see if the backing |
@@ -2563,7 +2503,7 @@ int __pud_alloc(struct mm_struct *mm, pgd_t *pgd, unsigned long address) | |||
2563 | 2503 | ||
2564 | spin_lock(&mm->page_table_lock); | 2504 | spin_lock(&mm->page_table_lock); |
2565 | if (pgd_present(*pgd)) /* Another has populated it */ | 2505 | if (pgd_present(*pgd)) /* Another has populated it */ |
2566 | pud_free(new); | 2506 | pud_free(mm, new); |
2567 | else | 2507 | else |
2568 | pgd_populate(mm, pgd, new); | 2508 | pgd_populate(mm, pgd, new); |
2569 | spin_unlock(&mm->page_table_lock); | 2509 | spin_unlock(&mm->page_table_lock); |
@@ -2585,12 +2525,12 @@ int __pmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long address) | |||
2585 | spin_lock(&mm->page_table_lock); | 2525 | spin_lock(&mm->page_table_lock); |
2586 | #ifndef __ARCH_HAS_4LEVEL_HACK | 2526 | #ifndef __ARCH_HAS_4LEVEL_HACK |
2587 | if (pud_present(*pud)) /* Another has populated it */ | 2527 | if (pud_present(*pud)) /* Another has populated it */ |
2588 | pmd_free(new); | 2528 | pmd_free(mm, new); |
2589 | else | 2529 | else |
2590 | pud_populate(mm, pud, new); | 2530 | pud_populate(mm, pud, new); |
2591 | #else | 2531 | #else |
2592 | if (pgd_present(*pud)) /* Another has populated it */ | 2532 | if (pgd_present(*pud)) /* Another has populated it */ |
2593 | pmd_free(new); | 2533 | pmd_free(mm, new); |
2594 | else | 2534 | else |
2595 | pgd_populate(mm, pud, new); | 2535 | pgd_populate(mm, pud, new); |
2596 | #endif /* __ARCH_HAS_4LEVEL_HACK */ | 2536 | #endif /* __ARCH_HAS_4LEVEL_HACK */ |
@@ -2618,46 +2558,6 @@ int make_pages_present(unsigned long addr, unsigned long end) | |||
2618 | return ret == len ? 0 : -1; | 2558 | return ret == len ? 0 : -1; |
2619 | } | 2559 | } |
2620 | 2560 | ||
2621 | /* | ||
2622 | * Map a vmalloc()-space virtual address to the physical page. | ||
2623 | */ | ||
2624 | struct page * vmalloc_to_page(void * vmalloc_addr) | ||
2625 | { | ||
2626 | unsigned long addr = (unsigned long) vmalloc_addr; | ||
2627 | struct page *page = NULL; | ||
2628 | pgd_t *pgd = pgd_offset_k(addr); | ||
2629 | pud_t *pud; | ||
2630 | pmd_t *pmd; | ||
2631 | pte_t *ptep, pte; | ||
2632 | |||
2633 | if (!pgd_none(*pgd)) { | ||
2634 | pud = pud_offset(pgd, addr); | ||
2635 | if (!pud_none(*pud)) { | ||
2636 | pmd = pmd_offset(pud, addr); | ||
2637 | if (!pmd_none(*pmd)) { | ||
2638 | ptep = pte_offset_map(pmd, addr); | ||
2639 | pte = *ptep; | ||
2640 | if (pte_present(pte)) | ||
2641 | page = pte_page(pte); | ||
2642 | pte_unmap(ptep); | ||
2643 | } | ||
2644 | } | ||
2645 | } | ||
2646 | return page; | ||
2647 | } | ||
2648 | |||
2649 | EXPORT_SYMBOL(vmalloc_to_page); | ||
2650 | |||
2651 | /* | ||
2652 | * Map a vmalloc()-space virtual address to the physical page frame number. | ||
2653 | */ | ||
2654 | unsigned long vmalloc_to_pfn(void * vmalloc_addr) | ||
2655 | { | ||
2656 | return page_to_pfn(vmalloc_to_page(vmalloc_addr)); | ||
2657 | } | ||
2658 | |||
2659 | EXPORT_SYMBOL(vmalloc_to_pfn); | ||
2660 | |||
2661 | #if !defined(__HAVE_ARCH_GATE_AREA) | 2561 | #if !defined(__HAVE_ARCH_GATE_AREA) |
2662 | 2562 | ||
2663 | #if defined(AT_SYSINFO_EHDR) | 2563 | #if defined(AT_SYSINFO_EHDR) |