diff options
Diffstat (limited to 'mm')
| -rw-r--r-- | mm/Kconfig | 2 | ||||
| -rw-r--r-- | mm/hugetlb.c | 2 | ||||
| -rw-r--r-- | mm/maccess.c | 11 | ||||
| -rw-r--r-- | mm/memcontrol.c | 11 | ||||
| -rw-r--r-- | mm/memory-failure.c | 9 | ||||
| -rw-r--r-- | mm/mmap.c | 40 | ||||
| -rw-r--r-- | mm/nommu.c | 144 | ||||
| -rw-r--r-- | mm/page_alloc.c | 15 | ||||
| -rw-r--r-- | mm/percpu.c | 4 | ||||
| -rw-r--r-- | mm/slab.c | 4 | ||||
| -rw-r--r-- | mm/truncate.c | 30 | ||||
| -rw-r--r-- | mm/util.c | 46 | ||||
| -rw-r--r-- | mm/vmscan.c | 3 |
13 files changed, 204 insertions, 117 deletions
diff --git a/mm/Kconfig b/mm/Kconfig index ee9f3e0f2b69..17b8947aa7da 100644 --- a/mm/Kconfig +++ b/mm/Kconfig | |||
| @@ -253,7 +253,7 @@ config MEMORY_FAILURE | |||
| 253 | 253 | ||
| 254 | config HWPOISON_INJECT | 254 | config HWPOISON_INJECT |
| 255 | tristate "HWPoison pages injector" | 255 | tristate "HWPoison pages injector" |
| 256 | depends on MEMORY_FAILURE && DEBUG_KERNEL | 256 | depends on MEMORY_FAILURE && DEBUG_KERNEL && PROC_FS |
| 257 | select PROC_PAGE_MONITOR | 257 | select PROC_PAGE_MONITOR |
| 258 | 258 | ||
| 259 | config NOMMU_INITIAL_TRIM_EXCESS | 259 | config NOMMU_INITIAL_TRIM_EXCESS |
diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 65f38c218207..e91b81b63670 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c | |||
| @@ -402,7 +402,7 @@ static void clear_huge_page(struct page *page, | |||
| 402 | { | 402 | { |
| 403 | int i; | 403 | int i; |
| 404 | 404 | ||
| 405 | if (unlikely(sz > MAX_ORDER_NR_PAGES)) { | 405 | if (unlikely(sz/PAGE_SIZE > MAX_ORDER_NR_PAGES)) { |
| 406 | clear_gigantic_page(page, addr, sz); | 406 | clear_gigantic_page(page, addr, sz); |
| 407 | return; | 407 | return; |
| 408 | } | 408 | } |
diff --git a/mm/maccess.c b/mm/maccess.c index 9073695ff25f..4e348dbaecd7 100644 --- a/mm/maccess.c +++ b/mm/maccess.c | |||
| @@ -14,7 +14,11 @@ | |||
| 14 | * Safely read from address @src to the buffer at @dst. If a kernel fault | 14 | * Safely read from address @src to the buffer at @dst. If a kernel fault |
| 15 | * happens, handle that and return -EFAULT. | 15 | * happens, handle that and return -EFAULT. |
| 16 | */ | 16 | */ |
| 17 | long probe_kernel_read(void *dst, void *src, size_t size) | 17 | |
| 18 | long __weak probe_kernel_read(void *dst, void *src, size_t size) | ||
| 19 | __attribute__((alias("__probe_kernel_read"))); | ||
| 20 | |||
| 21 | long __probe_kernel_read(void *dst, void *src, size_t size) | ||
| 18 | { | 22 | { |
| 19 | long ret; | 23 | long ret; |
| 20 | mm_segment_t old_fs = get_fs(); | 24 | mm_segment_t old_fs = get_fs(); |
| @@ -39,7 +43,10 @@ EXPORT_SYMBOL_GPL(probe_kernel_read); | |||
| 39 | * Safely write to address @dst from the buffer at @src. If a kernel fault | 43 | * Safely write to address @dst from the buffer at @src. If a kernel fault |
| 40 | * happens, handle that and return -EFAULT. | 44 | * happens, handle that and return -EFAULT. |
| 41 | */ | 45 | */ |
| 42 | long notrace __weak probe_kernel_write(void *dst, void *src, size_t size) | 46 | long __weak probe_kernel_write(void *dst, void *src, size_t size) |
| 47 | __attribute__((alias("__probe_kernel_write"))); | ||
| 48 | |||
| 49 | long __probe_kernel_write(void *dst, void *src, size_t size) | ||
| 43 | { | 50 | { |
| 44 | long ret; | 51 | long ret; |
| 45 | mm_segment_t old_fs = get_fs(); | 52 | mm_segment_t old_fs = get_fs(); |
diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 488b644e0e8e..954032b80bed 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c | |||
| @@ -2586,7 +2586,7 @@ static int mem_cgroup_force_empty(struct mem_cgroup *mem, bool free_all) | |||
| 2586 | if (free_all) | 2586 | if (free_all) |
| 2587 | goto try_to_free; | 2587 | goto try_to_free; |
| 2588 | move_account: | 2588 | move_account: |
| 2589 | while (mem->res.usage > 0) { | 2589 | do { |
| 2590 | ret = -EBUSY; | 2590 | ret = -EBUSY; |
| 2591 | if (cgroup_task_count(cgrp) || !list_empty(&cgrp->children)) | 2591 | if (cgroup_task_count(cgrp) || !list_empty(&cgrp->children)) |
| 2592 | goto out; | 2592 | goto out; |
| @@ -2614,8 +2614,8 @@ move_account: | |||
| 2614 | if (ret == -ENOMEM) | 2614 | if (ret == -ENOMEM) |
| 2615 | goto try_to_free; | 2615 | goto try_to_free; |
| 2616 | cond_resched(); | 2616 | cond_resched(); |
| 2617 | } | 2617 | /* "ret" should also be checked to ensure all lists are empty. */ |
| 2618 | ret = 0; | 2618 | } while (mem->res.usage > 0 || ret); |
| 2619 | out: | 2619 | out: |
| 2620 | css_put(&mem->css); | 2620 | css_put(&mem->css); |
| 2621 | return ret; | 2621 | return ret; |
| @@ -2648,10 +2648,7 @@ try_to_free: | |||
| 2648 | } | 2648 | } |
| 2649 | lru_add_drain(); | 2649 | lru_add_drain(); |
| 2650 | /* try move_account...there may be some *locked* pages. */ | 2650 | /* try move_account...there may be some *locked* pages. */ |
| 2651 | if (mem->res.usage) | 2651 | goto move_account; |
| 2652 | goto move_account; | ||
| 2653 | ret = 0; | ||
| 2654 | goto out; | ||
| 2655 | } | 2652 | } |
| 2656 | 2653 | ||
| 2657 | int mem_cgroup_force_empty_write(struct cgroup *cont, unsigned int event) | 2654 | int mem_cgroup_force_empty_write(struct cgroup *cont, unsigned int event) |
diff --git a/mm/memory-failure.c b/mm/memory-failure.c index 6a0466ed5bfd..17299fd4577c 100644 --- a/mm/memory-failure.c +++ b/mm/memory-failure.c | |||
| @@ -52,6 +52,8 @@ int sysctl_memory_failure_recovery __read_mostly = 1; | |||
| 52 | 52 | ||
| 53 | atomic_long_t mce_bad_pages __read_mostly = ATOMIC_LONG_INIT(0); | 53 | atomic_long_t mce_bad_pages __read_mostly = ATOMIC_LONG_INIT(0); |
| 54 | 54 | ||
| 55 | #if defined(CONFIG_HWPOISON_INJECT) || defined(CONFIG_HWPOISON_INJECT_MODULE) | ||
| 56 | |||
| 55 | u32 hwpoison_filter_enable = 0; | 57 | u32 hwpoison_filter_enable = 0; |
| 56 | u32 hwpoison_filter_dev_major = ~0U; | 58 | u32 hwpoison_filter_dev_major = ~0U; |
| 57 | u32 hwpoison_filter_dev_minor = ~0U; | 59 | u32 hwpoison_filter_dev_minor = ~0U; |
| @@ -164,6 +166,13 @@ int hwpoison_filter(struct page *p) | |||
| 164 | 166 | ||
| 165 | return 0; | 167 | return 0; |
| 166 | } | 168 | } |
| 169 | #else | ||
| 170 | int hwpoison_filter(struct page *p) | ||
| 171 | { | ||
| 172 | return 0; | ||
| 173 | } | ||
| 174 | #endif | ||
| 175 | |||
| 167 | EXPORT_SYMBOL_GPL(hwpoison_filter); | 176 | EXPORT_SYMBOL_GPL(hwpoison_filter); |
| 168 | 177 | ||
| 169 | /* | 178 | /* |
| @@ -1043,6 +1043,46 @@ unsigned long do_mmap_pgoff(struct file *file, unsigned long addr, | |||
| 1043 | } | 1043 | } |
| 1044 | EXPORT_SYMBOL(do_mmap_pgoff); | 1044 | EXPORT_SYMBOL(do_mmap_pgoff); |
| 1045 | 1045 | ||
| 1046 | SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len, | ||
| 1047 | unsigned long, prot, unsigned long, flags, | ||
| 1048 | unsigned long, fd, unsigned long, pgoff) | ||
| 1049 | { | ||
| 1050 | struct file *file = NULL; | ||
| 1051 | unsigned long retval = -EBADF; | ||
| 1052 | |||
| 1053 | if (!(flags & MAP_ANONYMOUS)) { | ||
| 1054 | if (unlikely(flags & MAP_HUGETLB)) | ||
| 1055 | return -EINVAL; | ||
| 1056 | file = fget(fd); | ||
| 1057 | if (!file) | ||
| 1058 | goto out; | ||
| 1059 | } else if (flags & MAP_HUGETLB) { | ||
| 1060 | struct user_struct *user = NULL; | ||
| 1061 | /* | ||
| 1062 | * VM_NORESERVE is used because the reservations will be | ||
| 1063 | * taken when vm_ops->mmap() is called | ||
| 1064 | * A dummy user value is used because we are not locking | ||
| 1065 | * memory so no accounting is necessary | ||
| 1066 | */ | ||
| 1067 | len = ALIGN(len, huge_page_size(&default_hstate)); | ||
| 1068 | file = hugetlb_file_setup(HUGETLB_ANON_FILE, len, VM_NORESERVE, | ||
| 1069 | &user, HUGETLB_ANONHUGE_INODE); | ||
| 1070 | if (IS_ERR(file)) | ||
| 1071 | return PTR_ERR(file); | ||
| 1072 | } | ||
| 1073 | |||
| 1074 | flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); | ||
| 1075 | |||
| 1076 | down_write(¤t->mm->mmap_sem); | ||
| 1077 | retval = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); | ||
| 1078 | up_write(¤t->mm->mmap_sem); | ||
| 1079 | |||
| 1080 | if (file) | ||
| 1081 | fput(file); | ||
| 1082 | out: | ||
| 1083 | return retval; | ||
| 1084 | } | ||
| 1085 | |||
| 1046 | /* | 1086 | /* |
| 1047 | * Some shared mappigns will want the pages marked read-only | 1087 | * Some shared mappigns will want the pages marked read-only |
| 1048 | * to track write events. If so, we'll downgrade vm_page_prot | 1088 | * to track write events. If so, we'll downgrade vm_page_prot |
diff --git a/mm/nommu.c b/mm/nommu.c index 8687973462bb..48a2ecfaf059 100644 --- a/mm/nommu.c +++ b/mm/nommu.c | |||
| @@ -432,6 +432,7 @@ SYSCALL_DEFINE1(brk, unsigned long, brk) | |||
| 432 | /* | 432 | /* |
| 433 | * Ok, looks good - let it rip. | 433 | * Ok, looks good - let it rip. |
| 434 | */ | 434 | */ |
| 435 | flush_icache_range(mm->brk, brk); | ||
| 435 | return mm->brk = brk; | 436 | return mm->brk = brk; |
| 436 | } | 437 | } |
| 437 | 438 | ||
| @@ -551,11 +552,11 @@ static void free_page_series(unsigned long from, unsigned long to) | |||
| 551 | static void __put_nommu_region(struct vm_region *region) | 552 | static void __put_nommu_region(struct vm_region *region) |
| 552 | __releases(nommu_region_sem) | 553 | __releases(nommu_region_sem) |
| 553 | { | 554 | { |
| 554 | kenter("%p{%d}", region, atomic_read(®ion->vm_usage)); | 555 | kenter("%p{%d}", region, region->vm_usage); |
| 555 | 556 | ||
| 556 | BUG_ON(!nommu_region_tree.rb_node); | 557 | BUG_ON(!nommu_region_tree.rb_node); |
| 557 | 558 | ||
| 558 | if (atomic_dec_and_test(®ion->vm_usage)) { | 559 | if (--region->vm_usage == 0) { |
| 559 | if (region->vm_top > region->vm_start) | 560 | if (region->vm_top > region->vm_start) |
| 560 | delete_nommu_region(region); | 561 | delete_nommu_region(region); |
| 561 | up_write(&nommu_region_sem); | 562 | up_write(&nommu_region_sem); |
| @@ -1204,7 +1205,7 @@ unsigned long do_mmap_pgoff(struct file *file, | |||
| 1204 | if (!vma) | 1205 | if (!vma) |
| 1205 | goto error_getting_vma; | 1206 | goto error_getting_vma; |
| 1206 | 1207 | ||
| 1207 | atomic_set(®ion->vm_usage, 1); | 1208 | region->vm_usage = 1; |
| 1208 | region->vm_flags = vm_flags; | 1209 | region->vm_flags = vm_flags; |
| 1209 | region->vm_pgoff = pgoff; | 1210 | region->vm_pgoff = pgoff; |
| 1210 | 1211 | ||
| @@ -1271,7 +1272,7 @@ unsigned long do_mmap_pgoff(struct file *file, | |||
| 1271 | } | 1272 | } |
| 1272 | 1273 | ||
| 1273 | /* we've found a region we can share */ | 1274 | /* we've found a region we can share */ |
| 1274 | atomic_inc(&pregion->vm_usage); | 1275 | pregion->vm_usage++; |
| 1275 | vma->vm_region = pregion; | 1276 | vma->vm_region = pregion; |
| 1276 | start = pregion->vm_start; | 1277 | start = pregion->vm_start; |
| 1277 | start += (pgoff - pregion->vm_pgoff) << PAGE_SHIFT; | 1278 | start += (pgoff - pregion->vm_pgoff) << PAGE_SHIFT; |
| @@ -1288,7 +1289,7 @@ unsigned long do_mmap_pgoff(struct file *file, | |||
| 1288 | vma->vm_region = NULL; | 1289 | vma->vm_region = NULL; |
| 1289 | vma->vm_start = 0; | 1290 | vma->vm_start = 0; |
| 1290 | vma->vm_end = 0; | 1291 | vma->vm_end = 0; |
| 1291 | atomic_dec(&pregion->vm_usage); | 1292 | pregion->vm_usage--; |
| 1292 | pregion = NULL; | 1293 | pregion = NULL; |
| 1293 | goto error_just_free; | 1294 | goto error_just_free; |
| 1294 | } | 1295 | } |
| @@ -1353,10 +1354,14 @@ unsigned long do_mmap_pgoff(struct file *file, | |||
| 1353 | share: | 1354 | share: |
| 1354 | add_vma_to_mm(current->mm, vma); | 1355 | add_vma_to_mm(current->mm, vma); |
| 1355 | 1356 | ||
| 1356 | up_write(&nommu_region_sem); | 1357 | /* we flush the region from the icache only when the first executable |
| 1358 | * mapping of it is made */ | ||
| 1359 | if (vma->vm_flags & VM_EXEC && !region->vm_icache_flushed) { | ||
| 1360 | flush_icache_range(region->vm_start, region->vm_end); | ||
| 1361 | region->vm_icache_flushed = true; | ||
| 1362 | } | ||
| 1357 | 1363 | ||
| 1358 | if (prot & PROT_EXEC) | 1364 | up_write(&nommu_region_sem); |
| 1359 | flush_icache_range(result, result + len); | ||
| 1360 | 1365 | ||
| 1361 | kleave(" = %lx", result); | 1366 | kleave(" = %lx", result); |
| 1362 | return result; | 1367 | return result; |
| @@ -1398,6 +1403,31 @@ error_getting_region: | |||
| 1398 | } | 1403 | } |
| 1399 | EXPORT_SYMBOL(do_mmap_pgoff); | 1404 | EXPORT_SYMBOL(do_mmap_pgoff); |
| 1400 | 1405 | ||
| 1406 | SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len, | ||
| 1407 | unsigned long, prot, unsigned long, flags, | ||
| 1408 | unsigned long, fd, unsigned long, pgoff) | ||
| 1409 | { | ||
| 1410 | struct file *file = NULL; | ||
| 1411 | unsigned long retval = -EBADF; | ||
| 1412 | |||
| 1413 | if (!(flags & MAP_ANONYMOUS)) { | ||
| 1414 | file = fget(fd); | ||
| 1415 | if (!file) | ||
| 1416 | goto out; | ||
| 1417 | } | ||
| 1418 | |||
| 1419 | flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); | ||
| 1420 | |||
| 1421 | down_write(¤t->mm->mmap_sem); | ||
| 1422 | retval = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); | ||
| 1423 | up_write(¤t->mm->mmap_sem); | ||
| 1424 | |||
| 1425 | if (file) | ||
| 1426 | fput(file); | ||
| 1427 | out: | ||
| 1428 | return retval; | ||
| 1429 | } | ||
| 1430 | |||
| 1401 | /* | 1431 | /* |
| 1402 | * split a vma into two pieces at address 'addr', a new vma is allocated either | 1432 | * split a vma into two pieces at address 'addr', a new vma is allocated either |
| 1403 | * for the first part or the tail. | 1433 | * for the first part or the tail. |
| @@ -1411,10 +1441,9 @@ int split_vma(struct mm_struct *mm, struct vm_area_struct *vma, | |||
| 1411 | 1441 | ||
| 1412 | kenter(""); | 1442 | kenter(""); |
| 1413 | 1443 | ||
| 1414 | /* we're only permitted to split anonymous regions that have a single | 1444 | /* we're only permitted to split anonymous regions (these should have |
| 1415 | * owner */ | 1445 | * only a single usage on the region) */ |
| 1416 | if (vma->vm_file || | 1446 | if (vma->vm_file) |
| 1417 | atomic_read(&vma->vm_region->vm_usage) != 1) | ||
| 1418 | return -ENOMEM; | 1447 | return -ENOMEM; |
| 1419 | 1448 | ||
| 1420 | if (mm->map_count >= sysctl_max_map_count) | 1449 | if (mm->map_count >= sysctl_max_map_count) |
| @@ -1488,7 +1517,7 @@ static int shrink_vma(struct mm_struct *mm, | |||
| 1488 | 1517 | ||
| 1489 | /* cut the backing region down to size */ | 1518 | /* cut the backing region down to size */ |
| 1490 | region = vma->vm_region; | 1519 | region = vma->vm_region; |
| 1491 | BUG_ON(atomic_read(®ion->vm_usage) != 1); | 1520 | BUG_ON(region->vm_usage != 1); |
| 1492 | 1521 | ||
| 1493 | down_write(&nommu_region_sem); | 1522 | down_write(&nommu_region_sem); |
| 1494 | delete_nommu_region(region); | 1523 | delete_nommu_region(region); |
| @@ -1732,27 +1761,6 @@ void unmap_mapping_range(struct address_space *mapping, | |||
| 1732 | EXPORT_SYMBOL(unmap_mapping_range); | 1761 | EXPORT_SYMBOL(unmap_mapping_range); |
| 1733 | 1762 | ||
| 1734 | /* | 1763 | /* |
| 1735 | * ask for an unmapped area at which to create a mapping on a file | ||
| 1736 | */ | ||
| 1737 | unsigned long get_unmapped_area(struct file *file, unsigned long addr, | ||
| 1738 | unsigned long len, unsigned long pgoff, | ||
| 1739 | unsigned long flags) | ||
| 1740 | { | ||
| 1741 | unsigned long (*get_area)(struct file *, unsigned long, unsigned long, | ||
| 1742 | unsigned long, unsigned long); | ||
| 1743 | |||
| 1744 | get_area = current->mm->get_unmapped_area; | ||
| 1745 | if (file && file->f_op && file->f_op->get_unmapped_area) | ||
| 1746 | get_area = file->f_op->get_unmapped_area; | ||
| 1747 | |||
| 1748 | if (!get_area) | ||
| 1749 | return -ENOSYS; | ||
| 1750 | |||
| 1751 | return get_area(file, addr, len, pgoff, flags); | ||
| 1752 | } | ||
| 1753 | EXPORT_SYMBOL(get_unmapped_area); | ||
| 1754 | |||
| 1755 | /* | ||
| 1756 | * Check that a process has enough memory to allocate a new virtual | 1764 | * Check that a process has enough memory to allocate a new virtual |
| 1757 | * mapping. 0 means there is enough memory for the allocation to | 1765 | * mapping. 0 means there is enough memory for the allocation to |
| 1758 | * succeed and -ENOMEM implies there is not. | 1766 | * succeed and -ENOMEM implies there is not. |
| @@ -1891,9 +1899,11 @@ int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, in | |||
| 1891 | 1899 | ||
| 1892 | /* only read or write mappings where it is permitted */ | 1900 | /* only read or write mappings where it is permitted */ |
| 1893 | if (write && vma->vm_flags & VM_MAYWRITE) | 1901 | if (write && vma->vm_flags & VM_MAYWRITE) |
| 1894 | len -= copy_to_user((void *) addr, buf, len); | 1902 | copy_to_user_page(vma, NULL, addr, |
| 1903 | (void *) addr, buf, len); | ||
| 1895 | else if (!write && vma->vm_flags & VM_MAYREAD) | 1904 | else if (!write && vma->vm_flags & VM_MAYREAD) |
| 1896 | len -= copy_from_user(buf, (void *) addr, len); | 1905 | copy_from_user_page(vma, NULL, addr, |
| 1906 | buf, (void *) addr, len); | ||
| 1897 | else | 1907 | else |
| 1898 | len = 0; | 1908 | len = 0; |
| 1899 | } else { | 1909 | } else { |
| @@ -1904,3 +1914,65 @@ int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, in | |||
| 1904 | mmput(mm); | 1914 | mmput(mm); |
| 1905 | return len; | 1915 | return len; |
| 1906 | } | 1916 | } |
| 1917 | |||
| 1918 | /** | ||
| 1919 | * nommu_shrink_inode_mappings - Shrink the shared mappings on an inode | ||
| 1920 | * @inode: The inode to check | ||
| 1921 | * @size: The current filesize of the inode | ||
| 1922 | * @newsize: The proposed filesize of the inode | ||
| 1923 | * | ||
| 1924 | * Check the shared mappings on an inode on behalf of a shrinking truncate to | ||
| 1925 | * make sure that that any outstanding VMAs aren't broken and then shrink the | ||
| 1926 | * vm_regions that extend that beyond so that do_mmap_pgoff() doesn't | ||
| 1927 | * automatically grant mappings that are too large. | ||
| 1928 | */ | ||
| 1929 | int nommu_shrink_inode_mappings(struct inode *inode, size_t size, | ||
| 1930 | size_t newsize) | ||
| 1931 | { | ||
| 1932 | struct vm_area_struct *vma; | ||
| 1933 | struct prio_tree_iter iter; | ||
| 1934 | struct vm_region *region; | ||
| 1935 | pgoff_t low, high; | ||
| 1936 | size_t r_size, r_top; | ||
| 1937 | |||
| 1938 | low = newsize >> PAGE_SHIFT; | ||
| 1939 | high = (size + PAGE_SIZE - 1) >> PAGE_SHIFT; | ||
| 1940 | |||
| 1941 | down_write(&nommu_region_sem); | ||
| 1942 | |||
| 1943 | /* search for VMAs that fall within the dead zone */ | ||
| 1944 | vma_prio_tree_foreach(vma, &iter, &inode->i_mapping->i_mmap, | ||
| 1945 | low, high) { | ||
| 1946 | /* found one - only interested if it's shared out of the page | ||
| 1947 | * cache */ | ||
| 1948 | if (vma->vm_flags & VM_SHARED) { | ||
| 1949 | up_write(&nommu_region_sem); | ||
| 1950 | return -ETXTBSY; /* not quite true, but near enough */ | ||
| 1951 | } | ||
| 1952 | } | ||
| 1953 | |||
| 1954 | /* reduce any regions that overlap the dead zone - if in existence, | ||
| 1955 | * these will be pointed to by VMAs that don't overlap the dead zone | ||
| 1956 | * | ||
| 1957 | * we don't check for any regions that start beyond the EOF as there | ||
| 1958 | * shouldn't be any | ||
| 1959 | */ | ||
| 1960 | vma_prio_tree_foreach(vma, &iter, &inode->i_mapping->i_mmap, | ||
| 1961 | 0, ULONG_MAX) { | ||
| 1962 | if (!(vma->vm_flags & VM_SHARED)) | ||
| 1963 | continue; | ||
| 1964 | |||
| 1965 | region = vma->vm_region; | ||
| 1966 | r_size = region->vm_top - region->vm_start; | ||
| 1967 | r_top = (region->vm_pgoff << PAGE_SHIFT) + r_size; | ||
| 1968 | |||
| 1969 | if (r_top > newsize) { | ||
| 1970 | region->vm_top -= r_top - newsize; | ||
| 1971 | if (region->vm_end > region->vm_top) | ||
| 1972 | region->vm_end = region->vm_top; | ||
| 1973 | } | ||
| 1974 | } | ||
| 1975 | |||
| 1976 | up_write(&nommu_region_sem); | ||
| 1977 | return 0; | ||
| 1978 | } | ||
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index d79b92580561..d2a8889b4c58 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
| @@ -1222,10 +1222,10 @@ again: | |||
| 1222 | } | 1222 | } |
| 1223 | spin_lock_irqsave(&zone->lock, flags); | 1223 | spin_lock_irqsave(&zone->lock, flags); |
| 1224 | page = __rmqueue(zone, order, migratetype); | 1224 | page = __rmqueue(zone, order, migratetype); |
| 1225 | __mod_zone_page_state(zone, NR_FREE_PAGES, -(1 << order)); | ||
| 1226 | spin_unlock(&zone->lock); | 1225 | spin_unlock(&zone->lock); |
| 1227 | if (!page) | 1226 | if (!page) |
| 1228 | goto failed; | 1227 | goto failed; |
| 1228 | __mod_zone_page_state(zone, NR_FREE_PAGES, -(1 << order)); | ||
| 1229 | } | 1229 | } |
| 1230 | 1230 | ||
| 1231 | __count_zone_vm_events(PGALLOC, zone, 1 << order); | 1231 | __count_zone_vm_events(PGALLOC, zone, 1 << order); |
| @@ -2402,13 +2402,14 @@ int numa_zonelist_order_handler(ctl_table *table, int write, | |||
| 2402 | { | 2402 | { |
| 2403 | char saved_string[NUMA_ZONELIST_ORDER_LEN]; | 2403 | char saved_string[NUMA_ZONELIST_ORDER_LEN]; |
| 2404 | int ret; | 2404 | int ret; |
| 2405 | static DEFINE_MUTEX(zl_order_mutex); | ||
| 2405 | 2406 | ||
| 2407 | mutex_lock(&zl_order_mutex); | ||
| 2406 | if (write) | 2408 | if (write) |
| 2407 | strncpy(saved_string, (char*)table->data, | 2409 | strcpy(saved_string, (char*)table->data); |
| 2408 | NUMA_ZONELIST_ORDER_LEN); | ||
| 2409 | ret = proc_dostring(table, write, buffer, length, ppos); | 2410 | ret = proc_dostring(table, write, buffer, length, ppos); |
| 2410 | if (ret) | 2411 | if (ret) |
| 2411 | return ret; | 2412 | goto out; |
| 2412 | if (write) { | 2413 | if (write) { |
| 2413 | int oldval = user_zonelist_order; | 2414 | int oldval = user_zonelist_order; |
| 2414 | if (__parse_numa_zonelist_order((char*)table->data)) { | 2415 | if (__parse_numa_zonelist_order((char*)table->data)) { |
| @@ -2421,7 +2422,9 @@ int numa_zonelist_order_handler(ctl_table *table, int write, | |||
| 2421 | } else if (oldval != user_zonelist_order) | 2422 | } else if (oldval != user_zonelist_order) |
| 2422 | build_all_zonelists(); | 2423 | build_all_zonelists(); |
| 2423 | } | 2424 | } |
| 2424 | return 0; | 2425 | out: |
| 2426 | mutex_unlock(&zl_order_mutex); | ||
| 2427 | return ret; | ||
| 2425 | } | 2428 | } |
| 2426 | 2429 | ||
| 2427 | 2430 | ||
| @@ -3995,7 +3998,7 @@ void __init add_active_range(unsigned int nid, unsigned long start_pfn, | |||
| 3995 | } | 3998 | } |
| 3996 | 3999 | ||
| 3997 | /* Merge backward if suitable */ | 4000 | /* Merge backward if suitable */ |
| 3998 | if (start_pfn < early_node_map[i].end_pfn && | 4001 | if (start_pfn < early_node_map[i].start_pfn && |
| 3999 | end_pfn >= early_node_map[i].start_pfn) { | 4002 | end_pfn >= early_node_map[i].start_pfn) { |
| 4000 | early_node_map[i].start_pfn = start_pfn; | 4003 | early_node_map[i].start_pfn = start_pfn; |
| 4001 | return; | 4004 | return; |
diff --git a/mm/percpu.c b/mm/percpu.c index 442010cc91c6..083e7c91e5f6 100644 --- a/mm/percpu.c +++ b/mm/percpu.c | |||
| @@ -1271,7 +1271,7 @@ static void pcpu_reclaim(struct work_struct *work) | |||
| 1271 | */ | 1271 | */ |
| 1272 | void free_percpu(void *ptr) | 1272 | void free_percpu(void *ptr) |
| 1273 | { | 1273 | { |
| 1274 | void *addr = __pcpu_ptr_to_addr(ptr); | 1274 | void *addr; |
| 1275 | struct pcpu_chunk *chunk; | 1275 | struct pcpu_chunk *chunk; |
| 1276 | unsigned long flags; | 1276 | unsigned long flags; |
| 1277 | int off; | 1277 | int off; |
| @@ -1279,6 +1279,8 @@ void free_percpu(void *ptr) | |||
| 1279 | if (!ptr) | 1279 | if (!ptr) |
| 1280 | return; | 1280 | return; |
| 1281 | 1281 | ||
| 1282 | addr = __pcpu_ptr_to_addr(ptr); | ||
| 1283 | |||
| 1282 | spin_lock_irqsave(&pcpu_lock, flags); | 1284 | spin_lock_irqsave(&pcpu_lock, flags); |
| 1283 | 1285 | ||
| 1284 | chunk = pcpu_chunk_addr_search(addr); | 1286 | chunk = pcpu_chunk_addr_search(addr); |
| @@ -654,7 +654,7 @@ static void init_node_lock_keys(int q) | |||
| 654 | 654 | ||
| 655 | l3 = s->cs_cachep->nodelists[q]; | 655 | l3 = s->cs_cachep->nodelists[q]; |
| 656 | if (!l3 || OFF_SLAB(s->cs_cachep)) | 656 | if (!l3 || OFF_SLAB(s->cs_cachep)) |
| 657 | return; | 657 | continue; |
| 658 | lockdep_set_class(&l3->list_lock, &on_slab_l3_key); | 658 | lockdep_set_class(&l3->list_lock, &on_slab_l3_key); |
| 659 | alc = l3->alien; | 659 | alc = l3->alien; |
| 660 | /* | 660 | /* |
| @@ -665,7 +665,7 @@ static void init_node_lock_keys(int q) | |||
| 665 | * for alloc_alien_cache, | 665 | * for alloc_alien_cache, |
| 666 | */ | 666 | */ |
| 667 | if (!alc || (unsigned long)alc == BAD_ALIEN_MAGIC) | 667 | if (!alc || (unsigned long)alc == BAD_ALIEN_MAGIC) |
| 668 | return; | 668 | continue; |
| 669 | for_each_node(r) { | 669 | for_each_node(r) { |
| 670 | if (alc[r]) | 670 | if (alc[r]) |
| 671 | lockdep_set_class(&alc[r]->lock, | 671 | lockdep_set_class(&alc[r]->lock, |
diff --git a/mm/truncate.c b/mm/truncate.c index 342deee22684..e87e37244829 100644 --- a/mm/truncate.c +++ b/mm/truncate.c | |||
| @@ -522,22 +522,20 @@ EXPORT_SYMBOL_GPL(invalidate_inode_pages2); | |||
| 522 | */ | 522 | */ |
| 523 | void truncate_pagecache(struct inode *inode, loff_t old, loff_t new) | 523 | void truncate_pagecache(struct inode *inode, loff_t old, loff_t new) |
| 524 | { | 524 | { |
| 525 | if (new < old) { | 525 | struct address_space *mapping = inode->i_mapping; |
| 526 | struct address_space *mapping = inode->i_mapping; | 526 | |
| 527 | 527 | /* | |
| 528 | /* | 528 | * unmap_mapping_range is called twice, first simply for |
| 529 | * unmap_mapping_range is called twice, first simply for | 529 | * efficiency so that truncate_inode_pages does fewer |
| 530 | * efficiency so that truncate_inode_pages does fewer | 530 | * single-page unmaps. However after this first call, and |
| 531 | * single-page unmaps. However after this first call, and | 531 | * before truncate_inode_pages finishes, it is possible for |
| 532 | * before truncate_inode_pages finishes, it is possible for | 532 | * private pages to be COWed, which remain after |
| 533 | * private pages to be COWed, which remain after | 533 | * truncate_inode_pages finishes, hence the second |
| 534 | * truncate_inode_pages finishes, hence the second | 534 | * unmap_mapping_range call must be made for correctness. |
| 535 | * unmap_mapping_range call must be made for correctness. | 535 | */ |
| 536 | */ | 536 | unmap_mapping_range(mapping, new + PAGE_SIZE - 1, 0, 1); |
| 537 | unmap_mapping_range(mapping, new + PAGE_SIZE - 1, 0, 1); | 537 | truncate_inode_pages(mapping, new); |
| 538 | truncate_inode_pages(mapping, new); | 538 | unmap_mapping_range(mapping, new + PAGE_SIZE - 1, 0, 1); |
| 539 | unmap_mapping_range(mapping, new + PAGE_SIZE - 1, 0, 1); | ||
| 540 | } | ||
| 541 | } | 539 | } |
| 542 | EXPORT_SYMBOL(truncate_pagecache); | 540 | EXPORT_SYMBOL(truncate_pagecache); |
| 543 | 541 | ||
| @@ -4,10 +4,6 @@ | |||
| 4 | #include <linux/module.h> | 4 | #include <linux/module.h> |
| 5 | #include <linux/err.h> | 5 | #include <linux/err.h> |
| 6 | #include <linux/sched.h> | 6 | #include <linux/sched.h> |
| 7 | #include <linux/hugetlb.h> | ||
| 8 | #include <linux/syscalls.h> | ||
| 9 | #include <linux/mman.h> | ||
| 10 | #include <linux/file.h> | ||
| 11 | #include <asm/uaccess.h> | 7 | #include <asm/uaccess.h> |
| 12 | 8 | ||
| 13 | #define CREATE_TRACE_POINTS | 9 | #define CREATE_TRACE_POINTS |
| @@ -224,7 +220,7 @@ char *strndup_user(const char __user *s, long n) | |||
| 224 | } | 220 | } |
| 225 | EXPORT_SYMBOL(strndup_user); | 221 | EXPORT_SYMBOL(strndup_user); |
| 226 | 222 | ||
| 227 | #ifndef HAVE_ARCH_PICK_MMAP_LAYOUT | 223 | #if defined(CONFIG_MMU) && !defined(HAVE_ARCH_PICK_MMAP_LAYOUT) |
| 228 | void arch_pick_mmap_layout(struct mm_struct *mm) | 224 | void arch_pick_mmap_layout(struct mm_struct *mm) |
| 229 | { | 225 | { |
| 230 | mm->mmap_base = TASK_UNMAPPED_BASE; | 226 | mm->mmap_base = TASK_UNMAPPED_BASE; |
| @@ -272,46 +268,6 @@ int __attribute__((weak)) get_user_pages_fast(unsigned long start, | |||
| 272 | } | 268 | } |
| 273 | EXPORT_SYMBOL_GPL(get_user_pages_fast); | 269 | EXPORT_SYMBOL_GPL(get_user_pages_fast); |
| 274 | 270 | ||
| 275 | SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len, | ||
| 276 | unsigned long, prot, unsigned long, flags, | ||
| 277 | unsigned long, fd, unsigned long, pgoff) | ||
| 278 | { | ||
| 279 | struct file * file = NULL; | ||
| 280 | unsigned long retval = -EBADF; | ||
| 281 | |||
| 282 | if (!(flags & MAP_ANONYMOUS)) { | ||
| 283 | if (unlikely(flags & MAP_HUGETLB)) | ||
| 284 | return -EINVAL; | ||
| 285 | file = fget(fd); | ||
| 286 | if (!file) | ||
| 287 | goto out; | ||
| 288 | } else if (flags & MAP_HUGETLB) { | ||
| 289 | struct user_struct *user = NULL; | ||
| 290 | /* | ||
| 291 | * VM_NORESERVE is used because the reservations will be | ||
| 292 | * taken when vm_ops->mmap() is called | ||
| 293 | * A dummy user value is used because we are not locking | ||
| 294 | * memory so no accounting is necessary | ||
| 295 | */ | ||
| 296 | len = ALIGN(len, huge_page_size(&default_hstate)); | ||
| 297 | file = hugetlb_file_setup(HUGETLB_ANON_FILE, len, VM_NORESERVE, | ||
| 298 | &user, HUGETLB_ANONHUGE_INODE); | ||
| 299 | if (IS_ERR(file)) | ||
| 300 | return PTR_ERR(file); | ||
| 301 | } | ||
| 302 | |||
| 303 | flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); | ||
| 304 | |||
| 305 | down_write(¤t->mm->mmap_sem); | ||
| 306 | retval = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); | ||
| 307 | up_write(¤t->mm->mmap_sem); | ||
| 308 | |||
| 309 | if (file) | ||
| 310 | fput(file); | ||
| 311 | out: | ||
| 312 | return retval; | ||
| 313 | } | ||
| 314 | |||
| 315 | /* Tracepoints definitions. */ | 271 | /* Tracepoints definitions. */ |
| 316 | EXPORT_TRACEPOINT_SYMBOL(kmalloc); | 272 | EXPORT_TRACEPOINT_SYMBOL(kmalloc); |
| 317 | EXPORT_TRACEPOINT_SYMBOL(kmem_cache_alloc); | 273 | EXPORT_TRACEPOINT_SYMBOL(kmem_cache_alloc); |
diff --git a/mm/vmscan.c b/mm/vmscan.c index 885207a6b6b7..c26986c85ce0 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c | |||
| @@ -1922,6 +1922,9 @@ static int sleeping_prematurely(pg_data_t *pgdat, int order, long remaining) | |||
| 1922 | if (!populated_zone(zone)) | 1922 | if (!populated_zone(zone)) |
| 1923 | continue; | 1923 | continue; |
| 1924 | 1924 | ||
| 1925 | if (zone_is_all_unreclaimable(zone)) | ||
| 1926 | continue; | ||
| 1927 | |||
| 1925 | if (!zone_watermark_ok(zone, order, high_wmark_pages(zone), | 1928 | if (!zone_watermark_ok(zone, order, high_wmark_pages(zone), |
| 1926 | 0, 0)) | 1929 | 0, 0)) |
| 1927 | return 1; | 1930 | return 1; |
