diff options
Diffstat (limited to 'mm')
-rw-r--r-- | mm/fremap.c | 3 | ||||
-rw-r--r-- | mm/madvise.c | 11 | ||||
-rw-r--r-- | mm/vmscan.c | 13 |
3 files changed, 16 insertions, 11 deletions
diff --git a/mm/fremap.c b/mm/fremap.c index 3235fb77c133..ab23a0673c35 100644 --- a/mm/fremap.c +++ b/mm/fremap.c | |||
@@ -89,6 +89,9 @@ int install_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
89 | size = (i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; | 89 | size = (i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; |
90 | if (!page->mapping || page->index >= size) | 90 | if (!page->mapping || page->index >= size) |
91 | goto err_unlock; | 91 | goto err_unlock; |
92 | err = -ENOMEM; | ||
93 | if (page_mapcount(page) > INT_MAX/2) | ||
94 | goto err_unlock; | ||
92 | 95 | ||
93 | zap_pte(mm, vma, addr, pte); | 96 | zap_pte(mm, vma, addr, pte); |
94 | 97 | ||
diff --git a/mm/madvise.c b/mm/madvise.c index 4454936f87d1..20e075d1c64c 100644 --- a/mm/madvise.c +++ b/mm/madvise.c | |||
@@ -83,6 +83,9 @@ static long madvise_willneed(struct vm_area_struct * vma, | |||
83 | { | 83 | { |
84 | struct file *file = vma->vm_file; | 84 | struct file *file = vma->vm_file; |
85 | 85 | ||
86 | if (!file) | ||
87 | return -EBADF; | ||
88 | |||
86 | if (file->f_mapping->a_ops->get_xip_page) { | 89 | if (file->f_mapping->a_ops->get_xip_page) { |
87 | /* no bad return value, but ignore advice */ | 90 | /* no bad return value, but ignore advice */ |
88 | return 0; | 91 | return 0; |
@@ -141,11 +144,7 @@ static long | |||
141 | madvise_vma(struct vm_area_struct *vma, struct vm_area_struct **prev, | 144 | madvise_vma(struct vm_area_struct *vma, struct vm_area_struct **prev, |
142 | unsigned long start, unsigned long end, int behavior) | 145 | unsigned long start, unsigned long end, int behavior) |
143 | { | 146 | { |
144 | struct file *filp = vma->vm_file; | 147 | long error; |
145 | long error = -EBADF; | ||
146 | |||
147 | if (!filp) | ||
148 | goto out; | ||
149 | 148 | ||
150 | switch (behavior) { | 149 | switch (behavior) { |
151 | case MADV_NORMAL: | 150 | case MADV_NORMAL: |
@@ -166,8 +165,6 @@ madvise_vma(struct vm_area_struct *vma, struct vm_area_struct **prev, | |||
166 | error = -EINVAL; | 165 | error = -EINVAL; |
167 | break; | 166 | break; |
168 | } | 167 | } |
169 | |||
170 | out: | ||
171 | return error; | 168 | return error; |
172 | } | 169 | } |
173 | 170 | ||
diff --git a/mm/vmscan.c b/mm/vmscan.c index 0ea71e887bb6..64f9570cff56 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c | |||
@@ -511,10 +511,11 @@ static int shrink_list(struct list_head *page_list, struct scan_control *sc) | |||
511 | * PageDirty _after_ making sure that the page is freeable and | 511 | * PageDirty _after_ making sure that the page is freeable and |
512 | * not in use by anybody. (pagecache + us == 2) | 512 | * not in use by anybody. (pagecache + us == 2) |
513 | */ | 513 | */ |
514 | if (page_count(page) != 2 || PageDirty(page)) { | 514 | if (unlikely(page_count(page) != 2)) |
515 | write_unlock_irq(&mapping->tree_lock); | 515 | goto cannot_free; |
516 | goto keep_locked; | 516 | smp_rmb(); |
517 | } | 517 | if (unlikely(PageDirty(page))) |
518 | goto cannot_free; | ||
518 | 519 | ||
519 | #ifdef CONFIG_SWAP | 520 | #ifdef CONFIG_SWAP |
520 | if (PageSwapCache(page)) { | 521 | if (PageSwapCache(page)) { |
@@ -538,6 +539,10 @@ free_it: | |||
538 | __pagevec_release_nonlru(&freed_pvec); | 539 | __pagevec_release_nonlru(&freed_pvec); |
539 | continue; | 540 | continue; |
540 | 541 | ||
542 | cannot_free: | ||
543 | write_unlock_irq(&mapping->tree_lock); | ||
544 | goto keep_locked; | ||
545 | |||
541 | activate_locked: | 546 | activate_locked: |
542 | SetPageActive(page); | 547 | SetPageActive(page); |
543 | pgactivate++; | 548 | pgactivate++; |