diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-01-02 17:40:38 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-01-02 17:40:38 -0500 |
commit | 06f055f394da2364b944d41b9609589763ae762a (patch) | |
tree | 3f8c0a081e2a9aa5d0742d8f164c87b30dba3d2d | |
parent | 152b734a9e38aa2e9668fa072cf66625383ca865 (diff) | |
parent | 4ff36ee94d93ddb4b7846177f1118d9aa33408e2 (diff) |
Merge branch 'akpm' (incoming from Andrew)
Merge patches from Andrew Morton:
"Ten fixes"
* emailed patches from Andrew Morton <akpm@linux-foundation.org>:
epoll: do not take the nested ep->mtx on EPOLL_CTL_DEL
sh: add EXPORT_SYMBOL(min_low_pfn) and EXPORT_SYMBOL(max_low_pfn) to sh_ksyms_32.c
drivers/dma/ioat/dma.c: check DMA mapping error in ioat_dma_self_test()
mm/memory-failure.c: transfer page count from head page to tail page after split thp
MAINTAINERS: set up proper record for Xilinx Zynq
mm: remove bogus warning in copy_huge_pmd()
memcg: fix memcg_size() calculation
mm: fix use-after-free in sys_remap_file_pages
mm: munlock: fix deadlock in __munlock_pagevec()
mm: munlock: fix a bug where THP tail page is encountered
-rw-r--r-- | MAINTAINERS | 3 | ||||
-rw-r--r-- | arch/sh/kernel/sh_ksyms_32.c | 5 | ||||
-rw-r--r-- | drivers/dma/ioat/dma.c | 11 | ||||
-rw-r--r-- | fs/eventpoll.c | 4 | ||||
-rw-r--r-- | mm/fremap.c | 8 | ||||
-rw-r--r-- | mm/huge_memory.c | 3 | ||||
-rw-r--r-- | mm/memcontrol.c | 2 | ||||
-rw-r--r-- | mm/memory-failure.c | 10 | ||||
-rw-r--r-- | mm/mlock.c | 44 |
9 files changed, 66 insertions, 24 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 21c038f216e3..6c2079270791 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -1368,6 +1368,9 @@ T: git git://git.xilinx.com/linux-xlnx.git | |||
1368 | S: Supported | 1368 | S: Supported |
1369 | F: arch/arm/mach-zynq/ | 1369 | F: arch/arm/mach-zynq/ |
1370 | F: drivers/cpuidle/cpuidle-zynq.c | 1370 | F: drivers/cpuidle/cpuidle-zynq.c |
1371 | N: zynq | ||
1372 | N: xilinx | ||
1373 | F: drivers/clocksource/cadence_ttc_timer.c | ||
1371 | 1374 | ||
1372 | ARM SMMU DRIVER | 1375 | ARM SMMU DRIVER |
1373 | M: Will Deacon <will.deacon@arm.com> | 1376 | M: Will Deacon <will.deacon@arm.com> |
diff --git a/arch/sh/kernel/sh_ksyms_32.c b/arch/sh/kernel/sh_ksyms_32.c index 2a0a596ebf67..d77f2f6c7ff0 100644 --- a/arch/sh/kernel/sh_ksyms_32.c +++ b/arch/sh/kernel/sh_ksyms_32.c | |||
@@ -20,6 +20,11 @@ EXPORT_SYMBOL(csum_partial_copy_generic); | |||
20 | EXPORT_SYMBOL(copy_page); | 20 | EXPORT_SYMBOL(copy_page); |
21 | EXPORT_SYMBOL(__clear_user); | 21 | EXPORT_SYMBOL(__clear_user); |
22 | EXPORT_SYMBOL(empty_zero_page); | 22 | EXPORT_SYMBOL(empty_zero_page); |
23 | #ifdef CONFIG_FLATMEM | ||
24 | /* need in pfn_valid macro */ | ||
25 | EXPORT_SYMBOL(min_low_pfn); | ||
26 | EXPORT_SYMBOL(max_low_pfn); | ||
27 | #endif | ||
23 | 28 | ||
24 | #define DECLARE_EXPORT(name) \ | 29 | #define DECLARE_EXPORT(name) \ |
25 | extern void name(void);EXPORT_SYMBOL(name) | 30 | extern void name(void);EXPORT_SYMBOL(name) |
diff --git a/drivers/dma/ioat/dma.c b/drivers/dma/ioat/dma.c index 1a49c777607c..87529181efcc 100644 --- a/drivers/dma/ioat/dma.c +++ b/drivers/dma/ioat/dma.c | |||
@@ -817,7 +817,15 @@ int ioat_dma_self_test(struct ioatdma_device *device) | |||
817 | } | 817 | } |
818 | 818 | ||
819 | dma_src = dma_map_single(dev, src, IOAT_TEST_SIZE, DMA_TO_DEVICE); | 819 | dma_src = dma_map_single(dev, src, IOAT_TEST_SIZE, DMA_TO_DEVICE); |
820 | if (dma_mapping_error(dev, dma_src)) { | ||
821 | dev_err(dev, "mapping src buffer failed\n"); | ||
822 | goto free_resources; | ||
823 | } | ||
820 | dma_dest = dma_map_single(dev, dest, IOAT_TEST_SIZE, DMA_FROM_DEVICE); | 824 | dma_dest = dma_map_single(dev, dest, IOAT_TEST_SIZE, DMA_FROM_DEVICE); |
825 | if (dma_mapping_error(dev, dma_dest)) { | ||
826 | dev_err(dev, "mapping dest buffer failed\n"); | ||
827 | goto unmap_src; | ||
828 | } | ||
821 | flags = DMA_PREP_INTERRUPT; | 829 | flags = DMA_PREP_INTERRUPT; |
822 | tx = device->common.device_prep_dma_memcpy(dma_chan, dma_dest, dma_src, | 830 | tx = device->common.device_prep_dma_memcpy(dma_chan, dma_dest, dma_src, |
823 | IOAT_TEST_SIZE, flags); | 831 | IOAT_TEST_SIZE, flags); |
@@ -855,8 +863,9 @@ int ioat_dma_self_test(struct ioatdma_device *device) | |||
855 | } | 863 | } |
856 | 864 | ||
857 | unmap_dma: | 865 | unmap_dma: |
858 | dma_unmap_single(dev, dma_src, IOAT_TEST_SIZE, DMA_TO_DEVICE); | ||
859 | dma_unmap_single(dev, dma_dest, IOAT_TEST_SIZE, DMA_FROM_DEVICE); | 866 | dma_unmap_single(dev, dma_dest, IOAT_TEST_SIZE, DMA_FROM_DEVICE); |
867 | unmap_src: | ||
868 | dma_unmap_single(dev, dma_src, IOAT_TEST_SIZE, DMA_TO_DEVICE); | ||
860 | free_resources: | 869 | free_resources: |
861 | dma->device_free_chan_resources(dma_chan); | 870 | dma->device_free_chan_resources(dma_chan); |
862 | out: | 871 | out: |
diff --git a/fs/eventpoll.c b/fs/eventpoll.c index 8b5e2584c840..af903128891c 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c | |||
@@ -1907,10 +1907,6 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd, | |||
1907 | } | 1907 | } |
1908 | } | 1908 | } |
1909 | } | 1909 | } |
1910 | if (op == EPOLL_CTL_DEL && is_file_epoll(tf.file)) { | ||
1911 | tep = tf.file->private_data; | ||
1912 | mutex_lock_nested(&tep->mtx, 1); | ||
1913 | } | ||
1914 | 1910 | ||
1915 | /* | 1911 | /* |
1916 | * Try to lookup the file inside our RB tree, Since we grabbed "mtx" | 1912 | * Try to lookup the file inside our RB tree, Since we grabbed "mtx" |
diff --git a/mm/fremap.c b/mm/fremap.c index 5bff08147768..bbc4d660221a 100644 --- a/mm/fremap.c +++ b/mm/fremap.c | |||
@@ -208,9 +208,10 @@ get_write_lock: | |||
208 | if (mapping_cap_account_dirty(mapping)) { | 208 | if (mapping_cap_account_dirty(mapping)) { |
209 | unsigned long addr; | 209 | unsigned long addr; |
210 | struct file *file = get_file(vma->vm_file); | 210 | struct file *file = get_file(vma->vm_file); |
211 | /* mmap_region may free vma; grab the info now */ | ||
212 | vm_flags = vma->vm_flags; | ||
211 | 213 | ||
212 | addr = mmap_region(file, start, size, | 214 | addr = mmap_region(file, start, size, vm_flags, pgoff); |
213 | vma->vm_flags, pgoff); | ||
214 | fput(file); | 215 | fput(file); |
215 | if (IS_ERR_VALUE(addr)) { | 216 | if (IS_ERR_VALUE(addr)) { |
216 | err = addr; | 217 | err = addr; |
@@ -218,7 +219,7 @@ get_write_lock: | |||
218 | BUG_ON(addr != start); | 219 | BUG_ON(addr != start); |
219 | err = 0; | 220 | err = 0; |
220 | } | 221 | } |
221 | goto out; | 222 | goto out_freed; |
222 | } | 223 | } |
223 | mutex_lock(&mapping->i_mmap_mutex); | 224 | mutex_lock(&mapping->i_mmap_mutex); |
224 | flush_dcache_mmap_lock(mapping); | 225 | flush_dcache_mmap_lock(mapping); |
@@ -253,6 +254,7 @@ get_write_lock: | |||
253 | out: | 254 | out: |
254 | if (vma) | 255 | if (vma) |
255 | vm_flags = vma->vm_flags; | 256 | vm_flags = vma->vm_flags; |
257 | out_freed: | ||
256 | if (likely(!has_write_lock)) | 258 | if (likely(!has_write_lock)) |
257 | up_read(&mm->mmap_sem); | 259 | up_read(&mm->mmap_sem); |
258 | else | 260 | else |
diff --git a/mm/huge_memory.c b/mm/huge_memory.c index 7de1bf85f683..9c0b17295ba0 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c | |||
@@ -883,9 +883,6 @@ int copy_huge_pmd(struct mm_struct *dst_mm, struct mm_struct *src_mm, | |||
883 | goto out_unlock; | 883 | goto out_unlock; |
884 | } | 884 | } |
885 | 885 | ||
886 | /* mmap_sem prevents this happening but warn if that changes */ | ||
887 | WARN_ON(pmd_trans_migrating(pmd)); | ||
888 | |||
889 | if (unlikely(pmd_trans_splitting(pmd))) { | 886 | if (unlikely(pmd_trans_splitting(pmd))) { |
890 | /* split huge page running from under us */ | 887 | /* split huge page running from under us */ |
891 | spin_unlock(src_ptl); | 888 | spin_unlock(src_ptl); |
diff --git a/mm/memcontrol.c b/mm/memcontrol.c index bf5e89457149..7f1a356153c0 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c | |||
@@ -338,7 +338,7 @@ struct mem_cgroup { | |||
338 | static size_t memcg_size(void) | 338 | static size_t memcg_size(void) |
339 | { | 339 | { |
340 | return sizeof(struct mem_cgroup) + | 340 | return sizeof(struct mem_cgroup) + |
341 | nr_node_ids * sizeof(struct mem_cgroup_per_node); | 341 | nr_node_ids * sizeof(struct mem_cgroup_per_node *); |
342 | } | 342 | } |
343 | 343 | ||
344 | /* internal only representation about the status of kmem accounting. */ | 344 | /* internal only representation about the status of kmem accounting. */ |
diff --git a/mm/memory-failure.c b/mm/memory-failure.c index db08af92c6fc..fabe55046c1d 100644 --- a/mm/memory-failure.c +++ b/mm/memory-failure.c | |||
@@ -938,6 +938,16 @@ static int hwpoison_user_mappings(struct page *p, unsigned long pfn, | |||
938 | BUG_ON(!PageHWPoison(p)); | 938 | BUG_ON(!PageHWPoison(p)); |
939 | return SWAP_FAIL; | 939 | return SWAP_FAIL; |
940 | } | 940 | } |
941 | /* | ||
942 | * We pinned the head page for hwpoison handling, | ||
943 | * now we split the thp and we are interested in | ||
944 | * the hwpoisoned raw page, so move the refcount | ||
945 | * to it. | ||
946 | */ | ||
947 | if (hpage != p) { | ||
948 | put_page(hpage); | ||
949 | get_page(p); | ||
950 | } | ||
941 | /* THP is split, so ppage should be the real poisoned page. */ | 951 | /* THP is split, so ppage should be the real poisoned page. */ |
942 | ppage = p; | 952 | ppage = p; |
943 | } | 953 | } |
diff --git a/mm/mlock.c b/mm/mlock.c index d480cd6fc475..192e6eebe4f2 100644 --- a/mm/mlock.c +++ b/mm/mlock.c | |||
@@ -133,7 +133,10 @@ static void __munlock_isolation_failed(struct page *page) | |||
133 | 133 | ||
134 | /** | 134 | /** |
135 | * munlock_vma_page - munlock a vma page | 135 | * munlock_vma_page - munlock a vma page |
136 | * @page - page to be unlocked | 136 | * @page - page to be unlocked, either a normal page or THP page head |
137 | * | ||
138 | * returns the size of the page as a page mask (0 for normal page, | ||
139 | * HPAGE_PMD_NR - 1 for THP head page) | ||
137 | * | 140 | * |
138 | * called from munlock()/munmap() path with page supposedly on the LRU. | 141 | * called from munlock()/munmap() path with page supposedly on the LRU. |
139 | * When we munlock a page, because the vma where we found the page is being | 142 | * When we munlock a page, because the vma where we found the page is being |
@@ -148,21 +151,30 @@ static void __munlock_isolation_failed(struct page *page) | |||
148 | */ | 151 | */ |
149 | unsigned int munlock_vma_page(struct page *page) | 152 | unsigned int munlock_vma_page(struct page *page) |
150 | { | 153 | { |
151 | unsigned int page_mask = 0; | 154 | unsigned int nr_pages; |
152 | 155 | ||
153 | BUG_ON(!PageLocked(page)); | 156 | BUG_ON(!PageLocked(page)); |
154 | 157 | ||
155 | if (TestClearPageMlocked(page)) { | 158 | if (TestClearPageMlocked(page)) { |
156 | unsigned int nr_pages = hpage_nr_pages(page); | 159 | nr_pages = hpage_nr_pages(page); |
157 | mod_zone_page_state(page_zone(page), NR_MLOCK, -nr_pages); | 160 | mod_zone_page_state(page_zone(page), NR_MLOCK, -nr_pages); |
158 | page_mask = nr_pages - 1; | ||
159 | if (!isolate_lru_page(page)) | 161 | if (!isolate_lru_page(page)) |
160 | __munlock_isolated_page(page); | 162 | __munlock_isolated_page(page); |
161 | else | 163 | else |
162 | __munlock_isolation_failed(page); | 164 | __munlock_isolation_failed(page); |
165 | } else { | ||
166 | nr_pages = hpage_nr_pages(page); | ||
163 | } | 167 | } |
164 | 168 | ||
165 | return page_mask; | 169 | /* |
170 | * Regardless of the original PageMlocked flag, we determine nr_pages | ||
171 | * after touching the flag. This leaves a possible race with a THP page | ||
172 | * split, such that a whole THP page was munlocked, but nr_pages == 1. | ||
173 | * Returning a smaller mask due to that is OK, the worst that can | ||
174 | * happen is subsequent useless scanning of the former tail pages. | ||
175 | * The NR_MLOCK accounting can however become broken. | ||
176 | */ | ||
177 | return nr_pages - 1; | ||
166 | } | 178 | } |
167 | 179 | ||
168 | /** | 180 | /** |
@@ -286,10 +298,12 @@ static void __munlock_pagevec(struct pagevec *pvec, struct zone *zone) | |||
286 | { | 298 | { |
287 | int i; | 299 | int i; |
288 | int nr = pagevec_count(pvec); | 300 | int nr = pagevec_count(pvec); |
289 | int delta_munlocked = -nr; | 301 | int delta_munlocked; |
290 | struct pagevec pvec_putback; | 302 | struct pagevec pvec_putback; |
291 | int pgrescued = 0; | 303 | int pgrescued = 0; |
292 | 304 | ||
305 | pagevec_init(&pvec_putback, 0); | ||
306 | |||
293 | /* Phase 1: page isolation */ | 307 | /* Phase 1: page isolation */ |
294 | spin_lock_irq(&zone->lru_lock); | 308 | spin_lock_irq(&zone->lru_lock); |
295 | for (i = 0; i < nr; i++) { | 309 | for (i = 0; i < nr; i++) { |
@@ -318,18 +332,21 @@ skip_munlock: | |||
318 | /* | 332 | /* |
319 | * We won't be munlocking this page in the next phase | 333 | * We won't be munlocking this page in the next phase |
320 | * but we still need to release the follow_page_mask() | 334 | * but we still need to release the follow_page_mask() |
321 | * pin. | 335 | * pin. We cannot do it under lru_lock however. If it's |
336 | * the last pin, __page_cache_release would deadlock. | ||
322 | */ | 337 | */ |
338 | pagevec_add(&pvec_putback, pvec->pages[i]); | ||
323 | pvec->pages[i] = NULL; | 339 | pvec->pages[i] = NULL; |
324 | put_page(page); | ||
325 | delta_munlocked++; | ||
326 | } | 340 | } |
327 | } | 341 | } |
342 | delta_munlocked = -nr + pagevec_count(&pvec_putback); | ||
328 | __mod_zone_page_state(zone, NR_MLOCK, delta_munlocked); | 343 | __mod_zone_page_state(zone, NR_MLOCK, delta_munlocked); |
329 | spin_unlock_irq(&zone->lru_lock); | 344 | spin_unlock_irq(&zone->lru_lock); |
330 | 345 | ||
346 | /* Now we can release pins of pages that we are not munlocking */ | ||
347 | pagevec_release(&pvec_putback); | ||
348 | |||
331 | /* Phase 2: page munlock */ | 349 | /* Phase 2: page munlock */ |
332 | pagevec_init(&pvec_putback, 0); | ||
333 | for (i = 0; i < nr; i++) { | 350 | for (i = 0; i < nr; i++) { |
334 | struct page *page = pvec->pages[i]; | 351 | struct page *page = pvec->pages[i]; |
335 | 352 | ||
@@ -440,7 +457,8 @@ void munlock_vma_pages_range(struct vm_area_struct *vma, | |||
440 | 457 | ||
441 | while (start < end) { | 458 | while (start < end) { |
442 | struct page *page = NULL; | 459 | struct page *page = NULL; |
443 | unsigned int page_mask, page_increm; | 460 | unsigned int page_mask; |
461 | unsigned long page_increm; | ||
444 | struct pagevec pvec; | 462 | struct pagevec pvec; |
445 | struct zone *zone; | 463 | struct zone *zone; |
446 | int zoneid; | 464 | int zoneid; |
@@ -490,7 +508,9 @@ void munlock_vma_pages_range(struct vm_area_struct *vma, | |||
490 | goto next; | 508 | goto next; |
491 | } | 509 | } |
492 | } | 510 | } |
493 | page_increm = 1 + (~(start >> PAGE_SHIFT) & page_mask); | 511 | /* It's a bug to munlock in the middle of a THP page */ |
512 | VM_BUG_ON((start >> PAGE_SHIFT) & page_mask); | ||
513 | page_increm = 1 + page_mask; | ||
494 | start += page_increm * PAGE_SIZE; | 514 | start += page_increm * PAGE_SIZE; |
495 | next: | 515 | next: |
496 | cond_resched(); | 516 | cond_resched(); |