diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2014-02-21 15:36:40 -0500 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2014-02-21 15:37:09 -0500 |
commit | d97a860c4f3de98ba5040a22f305b7159fe17cff (patch) | |
tree | 90c2155ec5a1f3115a9eb7a86f25d1a4610227c6 /mm | |
parent | 3f67d962c64d9b6de9dab81bdbe6d5c94c80d9b9 (diff) | |
parent | d158fc7f36a25e19791d25a55da5623399a2644f (diff) |
Merge branch 'linus' into sched/core
Reason: Bring bakc upstream modification to resolve conflicts
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'mm')
-rw-r--r-- | mm/filemap.c | 4 | ||||
-rw-r--r-- | mm/huge_memory.c | 9 | ||||
-rw-r--r-- | mm/memory-failure.c | 6 | ||||
-rw-r--r-- | mm/mprotect.c | 25 | ||||
-rw-r--r-- | mm/page-writeback.c | 5 | ||||
-rw-r--r-- | mm/slab.c | 2 | ||||
-rw-r--r-- | mm/slub.c | 74 | ||||
-rw-r--r-- | mm/swap_state.c | 63 | ||||
-rw-r--r-- | mm/swapfile.c | 11 | ||||
-rw-r--r-- | mm/vmpressure.c | 1 | ||||
-rw-r--r-- | mm/vmstat.c | 4 |
11 files changed, 140 insertions, 64 deletions
diff --git a/mm/filemap.c b/mm/filemap.c index d56d3c145b9f..7a13f6ac5421 100644 --- a/mm/filemap.c +++ b/mm/filemap.c | |||
@@ -2553,8 +2553,8 @@ ssize_t generic_file_aio_write(struct kiocb *iocb, const struct iovec *iov, | |||
2553 | if (ret > 0) { | 2553 | if (ret > 0) { |
2554 | ssize_t err; | 2554 | ssize_t err; |
2555 | 2555 | ||
2556 | err = generic_write_sync(file, pos, ret); | 2556 | err = generic_write_sync(file, iocb->ki_pos - ret, ret); |
2557 | if (err < 0 && ret > 0) | 2557 | if (err < 0) |
2558 | ret = err; | 2558 | ret = err; |
2559 | } | 2559 | } |
2560 | return ret; | 2560 | return ret; |
diff --git a/mm/huge_memory.c b/mm/huge_memory.c index 82166bf974e1..da23eb96779f 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c | |||
@@ -1545,6 +1545,7 @@ int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd, | |||
1545 | entry = pmd_mknonnuma(entry); | 1545 | entry = pmd_mknonnuma(entry); |
1546 | entry = pmd_modify(entry, newprot); | 1546 | entry = pmd_modify(entry, newprot); |
1547 | ret = HPAGE_PMD_NR; | 1547 | ret = HPAGE_PMD_NR; |
1548 | set_pmd_at(mm, addr, pmd, entry); | ||
1548 | BUG_ON(pmd_write(entry)); | 1549 | BUG_ON(pmd_write(entry)); |
1549 | } else { | 1550 | } else { |
1550 | struct page *page = pmd_page(*pmd); | 1551 | struct page *page = pmd_page(*pmd); |
@@ -1557,16 +1558,10 @@ int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd, | |||
1557 | */ | 1558 | */ |
1558 | if (!is_huge_zero_page(page) && | 1559 | if (!is_huge_zero_page(page) && |
1559 | !pmd_numa(*pmd)) { | 1560 | !pmd_numa(*pmd)) { |
1560 | entry = *pmd; | 1561 | pmdp_set_numa(mm, addr, pmd); |
1561 | entry = pmd_mknuma(entry); | ||
1562 | ret = HPAGE_PMD_NR; | 1562 | ret = HPAGE_PMD_NR; |
1563 | } | 1563 | } |
1564 | } | 1564 | } |
1565 | |||
1566 | /* Set PMD if cleared earlier */ | ||
1567 | if (ret == HPAGE_PMD_NR) | ||
1568 | set_pmd_at(mm, addr, pmd, entry); | ||
1569 | |||
1570 | spin_unlock(ptl); | 1565 | spin_unlock(ptl); |
1571 | } | 1566 | } |
1572 | 1567 | ||
diff --git a/mm/memory-failure.c b/mm/memory-failure.c index 4f08a2d61487..2f2f34a4e77d 100644 --- a/mm/memory-failure.c +++ b/mm/memory-failure.c | |||
@@ -945,8 +945,10 @@ static int hwpoison_user_mappings(struct page *p, unsigned long pfn, | |||
945 | * to it. Similarly, page lock is shifted. | 945 | * to it. Similarly, page lock is shifted. |
946 | */ | 946 | */ |
947 | if (hpage != p) { | 947 | if (hpage != p) { |
948 | put_page(hpage); | 948 | if (!(flags & MF_COUNT_INCREASED)) { |
949 | get_page(p); | 949 | put_page(hpage); |
950 | get_page(p); | ||
951 | } | ||
950 | lock_page(p); | 952 | lock_page(p); |
951 | unlock_page(hpage); | 953 | unlock_page(hpage); |
952 | *hpagep = p; | 954 | *hpagep = p; |
diff --git a/mm/mprotect.c b/mm/mprotect.c index 7332c1785744..769a67a15803 100644 --- a/mm/mprotect.c +++ b/mm/mprotect.c | |||
@@ -58,36 +58,27 @@ static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd, | |||
58 | if (pte_numa(ptent)) | 58 | if (pte_numa(ptent)) |
59 | ptent = pte_mknonnuma(ptent); | 59 | ptent = pte_mknonnuma(ptent); |
60 | ptent = pte_modify(ptent, newprot); | 60 | ptent = pte_modify(ptent, newprot); |
61 | /* | ||
62 | * Avoid taking write faults for pages we | ||
63 | * know to be dirty. | ||
64 | */ | ||
65 | if (dirty_accountable && pte_dirty(ptent)) | ||
66 | ptent = pte_mkwrite(ptent); | ||
67 | ptep_modify_prot_commit(mm, addr, pte, ptent); | ||
61 | updated = true; | 68 | updated = true; |
62 | } else { | 69 | } else { |
63 | struct page *page; | 70 | struct page *page; |
64 | 71 | ||
65 | ptent = *pte; | ||
66 | page = vm_normal_page(vma, addr, oldpte); | 72 | page = vm_normal_page(vma, addr, oldpte); |
67 | if (page && !PageKsm(page)) { | 73 | if (page && !PageKsm(page)) { |
68 | if (!pte_numa(oldpte)) { | 74 | if (!pte_numa(oldpte)) { |
69 | ptent = pte_mknuma(ptent); | 75 | ptep_set_numa(mm, addr, pte); |
70 | set_pte_at(mm, addr, pte, ptent); | ||
71 | updated = true; | 76 | updated = true; |
72 | } | 77 | } |
73 | } | 78 | } |
74 | } | 79 | } |
75 | |||
76 | /* | ||
77 | * Avoid taking write faults for pages we know to be | ||
78 | * dirty. | ||
79 | */ | ||
80 | if (dirty_accountable && pte_dirty(ptent)) { | ||
81 | ptent = pte_mkwrite(ptent); | ||
82 | updated = true; | ||
83 | } | ||
84 | |||
85 | if (updated) | 80 | if (updated) |
86 | pages++; | 81 | pages++; |
87 | |||
88 | /* Only !prot_numa always clears the pte */ | ||
89 | if (!prot_numa) | ||
90 | ptep_modify_prot_commit(mm, addr, pte, ptent); | ||
91 | } else if (IS_ENABLED(CONFIG_MIGRATION) && !pte_file(oldpte)) { | 82 | } else if (IS_ENABLED(CONFIG_MIGRATION) && !pte_file(oldpte)) { |
92 | swp_entry_t entry = pte_to_swp_entry(oldpte); | 83 | swp_entry_t entry = pte_to_swp_entry(oldpte); |
93 | 84 | ||
diff --git a/mm/page-writeback.c b/mm/page-writeback.c index 2d30e2cfe804..7106cb1aca8e 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c | |||
@@ -2173,11 +2173,12 @@ int __set_page_dirty_nobuffers(struct page *page) | |||
2173 | if (!TestSetPageDirty(page)) { | 2173 | if (!TestSetPageDirty(page)) { |
2174 | struct address_space *mapping = page_mapping(page); | 2174 | struct address_space *mapping = page_mapping(page); |
2175 | struct address_space *mapping2; | 2175 | struct address_space *mapping2; |
2176 | unsigned long flags; | ||
2176 | 2177 | ||
2177 | if (!mapping) | 2178 | if (!mapping) |
2178 | return 1; | 2179 | return 1; |
2179 | 2180 | ||
2180 | spin_lock_irq(&mapping->tree_lock); | 2181 | spin_lock_irqsave(&mapping->tree_lock, flags); |
2181 | mapping2 = page_mapping(page); | 2182 | mapping2 = page_mapping(page); |
2182 | if (mapping2) { /* Race with truncate? */ | 2183 | if (mapping2) { /* Race with truncate? */ |
2183 | BUG_ON(mapping2 != mapping); | 2184 | BUG_ON(mapping2 != mapping); |
@@ -2186,7 +2187,7 @@ int __set_page_dirty_nobuffers(struct page *page) | |||
2186 | radix_tree_tag_set(&mapping->page_tree, | 2187 | radix_tree_tag_set(&mapping->page_tree, |
2187 | page_index(page), PAGECACHE_TAG_DIRTY); | 2188 | page_index(page), PAGECACHE_TAG_DIRTY); |
2188 | } | 2189 | } |
2189 | spin_unlock_irq(&mapping->tree_lock); | 2190 | spin_unlock_irqrestore(&mapping->tree_lock, flags); |
2190 | if (mapping->host) { | 2191 | if (mapping->host) { |
2191 | /* !PageAnon && !swapper_space */ | 2192 | /* !PageAnon && !swapper_space */ |
2192 | __mark_inode_dirty(mapping->host, I_DIRTY_PAGES); | 2193 | __mark_inode_dirty(mapping->host, I_DIRTY_PAGES); |
@@ -1946,7 +1946,7 @@ static void slab_destroy_debugcheck(struct kmem_cache *cachep, | |||
1946 | /** | 1946 | /** |
1947 | * slab_destroy - destroy and release all objects in a slab | 1947 | * slab_destroy - destroy and release all objects in a slab |
1948 | * @cachep: cache pointer being destroyed | 1948 | * @cachep: cache pointer being destroyed |
1949 | * @slabp: slab pointer being destroyed | 1949 | * @page: page pointer being destroyed |
1950 | * | 1950 | * |
1951 | * Destroy all the objs in a slab, and release the mem back to the system. | 1951 | * Destroy all the objs in a slab, and release the mem back to the system. |
1952 | * Before calling the slab must have been unlinked from the cache. The | 1952 | * Before calling the slab must have been unlinked from the cache. The |
@@ -1000,8 +1000,6 @@ static inline void slab_free_hook(struct kmem_cache *s, void *x) | |||
1000 | 1000 | ||
1001 | /* | 1001 | /* |
1002 | * Tracking of fully allocated slabs for debugging purposes. | 1002 | * Tracking of fully allocated slabs for debugging purposes. |
1003 | * | ||
1004 | * list_lock must be held. | ||
1005 | */ | 1003 | */ |
1006 | static void add_full(struct kmem_cache *s, | 1004 | static void add_full(struct kmem_cache *s, |
1007 | struct kmem_cache_node *n, struct page *page) | 1005 | struct kmem_cache_node *n, struct page *page) |
@@ -1009,17 +1007,16 @@ static void add_full(struct kmem_cache *s, | |||
1009 | if (!(s->flags & SLAB_STORE_USER)) | 1007 | if (!(s->flags & SLAB_STORE_USER)) |
1010 | return; | 1008 | return; |
1011 | 1009 | ||
1010 | lockdep_assert_held(&n->list_lock); | ||
1012 | list_add(&page->lru, &n->full); | 1011 | list_add(&page->lru, &n->full); |
1013 | } | 1012 | } |
1014 | 1013 | ||
1015 | /* | 1014 | static void remove_full(struct kmem_cache *s, struct kmem_cache_node *n, struct page *page) |
1016 | * list_lock must be held. | ||
1017 | */ | ||
1018 | static void remove_full(struct kmem_cache *s, struct page *page) | ||
1019 | { | 1015 | { |
1020 | if (!(s->flags & SLAB_STORE_USER)) | 1016 | if (!(s->flags & SLAB_STORE_USER)) |
1021 | return; | 1017 | return; |
1022 | 1018 | ||
1019 | lockdep_assert_held(&n->list_lock); | ||
1023 | list_del(&page->lru); | 1020 | list_del(&page->lru); |
1024 | } | 1021 | } |
1025 | 1022 | ||
@@ -1265,7 +1262,8 @@ static inline int check_object(struct kmem_cache *s, struct page *page, | |||
1265 | void *object, u8 val) { return 1; } | 1262 | void *object, u8 val) { return 1; } |
1266 | static inline void add_full(struct kmem_cache *s, struct kmem_cache_node *n, | 1263 | static inline void add_full(struct kmem_cache *s, struct kmem_cache_node *n, |
1267 | struct page *page) {} | 1264 | struct page *page) {} |
1268 | static inline void remove_full(struct kmem_cache *s, struct page *page) {} | 1265 | static inline void remove_full(struct kmem_cache *s, struct kmem_cache_node *n, |
1266 | struct page *page) {} | ||
1269 | static inline unsigned long kmem_cache_flags(unsigned long object_size, | 1267 | static inline unsigned long kmem_cache_flags(unsigned long object_size, |
1270 | unsigned long flags, const char *name, | 1268 | unsigned long flags, const char *name, |
1271 | void (*ctor)(void *)) | 1269 | void (*ctor)(void *)) |
@@ -1519,11 +1517,9 @@ static void discard_slab(struct kmem_cache *s, struct page *page) | |||
1519 | 1517 | ||
1520 | /* | 1518 | /* |
1521 | * Management of partially allocated slabs. | 1519 | * Management of partially allocated slabs. |
1522 | * | ||
1523 | * list_lock must be held. | ||
1524 | */ | 1520 | */ |
1525 | static inline void add_partial(struct kmem_cache_node *n, | 1521 | static inline void |
1526 | struct page *page, int tail) | 1522 | __add_partial(struct kmem_cache_node *n, struct page *page, int tail) |
1527 | { | 1523 | { |
1528 | n->nr_partial++; | 1524 | n->nr_partial++; |
1529 | if (tail == DEACTIVATE_TO_TAIL) | 1525 | if (tail == DEACTIVATE_TO_TAIL) |
@@ -1532,23 +1528,32 @@ static inline void add_partial(struct kmem_cache_node *n, | |||
1532 | list_add(&page->lru, &n->partial); | 1528 | list_add(&page->lru, &n->partial); |
1533 | } | 1529 | } |
1534 | 1530 | ||
1535 | /* | 1531 | static inline void add_partial(struct kmem_cache_node *n, |
1536 | * list_lock must be held. | 1532 | struct page *page, int tail) |
1537 | */ | 1533 | { |
1538 | static inline void remove_partial(struct kmem_cache_node *n, | 1534 | lockdep_assert_held(&n->list_lock); |
1539 | struct page *page) | 1535 | __add_partial(n, page, tail); |
1536 | } | ||
1537 | |||
1538 | static inline void | ||
1539 | __remove_partial(struct kmem_cache_node *n, struct page *page) | ||
1540 | { | 1540 | { |
1541 | list_del(&page->lru); | 1541 | list_del(&page->lru); |
1542 | n->nr_partial--; | 1542 | n->nr_partial--; |
1543 | } | 1543 | } |
1544 | 1544 | ||
1545 | static inline void remove_partial(struct kmem_cache_node *n, | ||
1546 | struct page *page) | ||
1547 | { | ||
1548 | lockdep_assert_held(&n->list_lock); | ||
1549 | __remove_partial(n, page); | ||
1550 | } | ||
1551 | |||
1545 | /* | 1552 | /* |
1546 | * Remove slab from the partial list, freeze it and | 1553 | * Remove slab from the partial list, freeze it and |
1547 | * return the pointer to the freelist. | 1554 | * return the pointer to the freelist. |
1548 | * | 1555 | * |
1549 | * Returns a list of objects or NULL if it fails. | 1556 | * Returns a list of objects or NULL if it fails. |
1550 | * | ||
1551 | * Must hold list_lock since we modify the partial list. | ||
1552 | */ | 1557 | */ |
1553 | static inline void *acquire_slab(struct kmem_cache *s, | 1558 | static inline void *acquire_slab(struct kmem_cache *s, |
1554 | struct kmem_cache_node *n, struct page *page, | 1559 | struct kmem_cache_node *n, struct page *page, |
@@ -1558,6 +1563,8 @@ static inline void *acquire_slab(struct kmem_cache *s, | |||
1558 | unsigned long counters; | 1563 | unsigned long counters; |
1559 | struct page new; | 1564 | struct page new; |
1560 | 1565 | ||
1566 | lockdep_assert_held(&n->list_lock); | ||
1567 | |||
1561 | /* | 1568 | /* |
1562 | * Zap the freelist and set the frozen bit. | 1569 | * Zap the freelist and set the frozen bit. |
1563 | * The old freelist is the list of objects for the | 1570 | * The old freelist is the list of objects for the |
@@ -1902,7 +1909,7 @@ redo: | |||
1902 | 1909 | ||
1903 | else if (l == M_FULL) | 1910 | else if (l == M_FULL) |
1904 | 1911 | ||
1905 | remove_full(s, page); | 1912 | remove_full(s, n, page); |
1906 | 1913 | ||
1907 | if (m == M_PARTIAL) { | 1914 | if (m == M_PARTIAL) { |
1908 | 1915 | ||
@@ -2556,7 +2563,7 @@ static void __slab_free(struct kmem_cache *s, struct page *page, | |||
2556 | new.inuse--; | 2563 | new.inuse--; |
2557 | if ((!new.inuse || !prior) && !was_frozen) { | 2564 | if ((!new.inuse || !prior) && !was_frozen) { |
2558 | 2565 | ||
2559 | if (kmem_cache_has_cpu_partial(s) && !prior) | 2566 | if (kmem_cache_has_cpu_partial(s) && !prior) { |
2560 | 2567 | ||
2561 | /* | 2568 | /* |
2562 | * Slab was on no list before and will be | 2569 | * Slab was on no list before and will be |
@@ -2566,7 +2573,7 @@ static void __slab_free(struct kmem_cache *s, struct page *page, | |||
2566 | */ | 2573 | */ |
2567 | new.frozen = 1; | 2574 | new.frozen = 1; |
2568 | 2575 | ||
2569 | else { /* Needs to be taken off a list */ | 2576 | } else { /* Needs to be taken off a list */ |
2570 | 2577 | ||
2571 | n = get_node(s, page_to_nid(page)); | 2578 | n = get_node(s, page_to_nid(page)); |
2572 | /* | 2579 | /* |
@@ -2615,7 +2622,7 @@ static void __slab_free(struct kmem_cache *s, struct page *page, | |||
2615 | */ | 2622 | */ |
2616 | if (!kmem_cache_has_cpu_partial(s) && unlikely(!prior)) { | 2623 | if (!kmem_cache_has_cpu_partial(s) && unlikely(!prior)) { |
2617 | if (kmem_cache_debug(s)) | 2624 | if (kmem_cache_debug(s)) |
2618 | remove_full(s, page); | 2625 | remove_full(s, n, page); |
2619 | add_partial(n, page, DEACTIVATE_TO_TAIL); | 2626 | add_partial(n, page, DEACTIVATE_TO_TAIL); |
2620 | stat(s, FREE_ADD_PARTIAL); | 2627 | stat(s, FREE_ADD_PARTIAL); |
2621 | } | 2628 | } |
@@ -2629,9 +2636,10 @@ slab_empty: | |||
2629 | */ | 2636 | */ |
2630 | remove_partial(n, page); | 2637 | remove_partial(n, page); |
2631 | stat(s, FREE_REMOVE_PARTIAL); | 2638 | stat(s, FREE_REMOVE_PARTIAL); |
2632 | } else | 2639 | } else { |
2633 | /* Slab must be on the full list */ | 2640 | /* Slab must be on the full list */ |
2634 | remove_full(s, page); | 2641 | remove_full(s, n, page); |
2642 | } | ||
2635 | 2643 | ||
2636 | spin_unlock_irqrestore(&n->list_lock, flags); | 2644 | spin_unlock_irqrestore(&n->list_lock, flags); |
2637 | stat(s, FREE_SLAB); | 2645 | stat(s, FREE_SLAB); |
@@ -2905,7 +2913,11 @@ static void early_kmem_cache_node_alloc(int node) | |||
2905 | init_kmem_cache_node(n); | 2913 | init_kmem_cache_node(n); |
2906 | inc_slabs_node(kmem_cache_node, node, page->objects); | 2914 | inc_slabs_node(kmem_cache_node, node, page->objects); |
2907 | 2915 | ||
2908 | add_partial(n, page, DEACTIVATE_TO_HEAD); | 2916 | /* |
2917 | * No locks need to be taken here as it has just been | ||
2918 | * initialized and there is no concurrent access. | ||
2919 | */ | ||
2920 | __add_partial(n, page, DEACTIVATE_TO_HEAD); | ||
2909 | } | 2921 | } |
2910 | 2922 | ||
2911 | static void free_kmem_cache_nodes(struct kmem_cache *s) | 2923 | static void free_kmem_cache_nodes(struct kmem_cache *s) |
@@ -3191,7 +3203,7 @@ static void free_partial(struct kmem_cache *s, struct kmem_cache_node *n) | |||
3191 | 3203 | ||
3192 | list_for_each_entry_safe(page, h, &n->partial, lru) { | 3204 | list_for_each_entry_safe(page, h, &n->partial, lru) { |
3193 | if (!page->inuse) { | 3205 | if (!page->inuse) { |
3194 | remove_partial(n, page); | 3206 | __remove_partial(n, page); |
3195 | discard_slab(s, page); | 3207 | discard_slab(s, page); |
3196 | } else { | 3208 | } else { |
3197 | list_slab_objects(s, page, | 3209 | list_slab_objects(s, page, |
@@ -4314,7 +4326,13 @@ static ssize_t show_slab_objects(struct kmem_cache *s, | |||
4314 | 4326 | ||
4315 | page = ACCESS_ONCE(c->partial); | 4327 | page = ACCESS_ONCE(c->partial); |
4316 | if (page) { | 4328 | if (page) { |
4317 | x = page->pobjects; | 4329 | node = page_to_nid(page); |
4330 | if (flags & SO_TOTAL) | ||
4331 | WARN_ON_ONCE(1); | ||
4332 | else if (flags & SO_OBJECTS) | ||
4333 | WARN_ON_ONCE(1); | ||
4334 | else | ||
4335 | x = page->pages; | ||
4318 | total += x; | 4336 | total += x; |
4319 | nodes[node] += x; | 4337 | nodes[node] += x; |
4320 | } | 4338 | } |
@@ -5178,7 +5196,7 @@ static int sysfs_slab_add(struct kmem_cache *s) | |||
5178 | } | 5196 | } |
5179 | 5197 | ||
5180 | s->kobj.kset = slab_kset; | 5198 | s->kobj.kset = slab_kset; |
5181 | err = kobject_init_and_add(&s->kobj, &slab_ktype, NULL, name); | 5199 | err = kobject_init_and_add(&s->kobj, &slab_ktype, NULL, "%s", name); |
5182 | if (err) { | 5200 | if (err) { |
5183 | kobject_put(&s->kobj); | 5201 | kobject_put(&s->kobj); |
5184 | return err; | 5202 | return err; |
diff --git a/mm/swap_state.c b/mm/swap_state.c index 98e85e9c2b2d..e76ace30d436 100644 --- a/mm/swap_state.c +++ b/mm/swap_state.c | |||
@@ -63,6 +63,8 @@ unsigned long total_swapcache_pages(void) | |||
63 | return ret; | 63 | return ret; |
64 | } | 64 | } |
65 | 65 | ||
66 | static atomic_t swapin_readahead_hits = ATOMIC_INIT(4); | ||
67 | |||
66 | void show_swap_cache_info(void) | 68 | void show_swap_cache_info(void) |
67 | { | 69 | { |
68 | printk("%lu pages in swap cache\n", total_swapcache_pages()); | 70 | printk("%lu pages in swap cache\n", total_swapcache_pages()); |
@@ -286,8 +288,11 @@ struct page * lookup_swap_cache(swp_entry_t entry) | |||
286 | 288 | ||
287 | page = find_get_page(swap_address_space(entry), entry.val); | 289 | page = find_get_page(swap_address_space(entry), entry.val); |
288 | 290 | ||
289 | if (page) | 291 | if (page) { |
290 | INC_CACHE_INFO(find_success); | 292 | INC_CACHE_INFO(find_success); |
293 | if (TestClearPageReadahead(page)) | ||
294 | atomic_inc(&swapin_readahead_hits); | ||
295 | } | ||
291 | 296 | ||
292 | INC_CACHE_INFO(find_total); | 297 | INC_CACHE_INFO(find_total); |
293 | return page; | 298 | return page; |
@@ -389,6 +394,50 @@ struct page *read_swap_cache_async(swp_entry_t entry, gfp_t gfp_mask, | |||
389 | return found_page; | 394 | return found_page; |
390 | } | 395 | } |
391 | 396 | ||
397 | static unsigned long swapin_nr_pages(unsigned long offset) | ||
398 | { | ||
399 | static unsigned long prev_offset; | ||
400 | unsigned int pages, max_pages, last_ra; | ||
401 | static atomic_t last_readahead_pages; | ||
402 | |||
403 | max_pages = 1 << ACCESS_ONCE(page_cluster); | ||
404 | if (max_pages <= 1) | ||
405 | return 1; | ||
406 | |||
407 | /* | ||
408 | * This heuristic has been found to work well on both sequential and | ||
409 | * random loads, swapping to hard disk or to SSD: please don't ask | ||
410 | * what the "+ 2" means, it just happens to work well, that's all. | ||
411 | */ | ||
412 | pages = atomic_xchg(&swapin_readahead_hits, 0) + 2; | ||
413 | if (pages == 2) { | ||
414 | /* | ||
415 | * We can have no readahead hits to judge by: but must not get | ||
416 | * stuck here forever, so check for an adjacent offset instead | ||
417 | * (and don't even bother to check whether swap type is same). | ||
418 | */ | ||
419 | if (offset != prev_offset + 1 && offset != prev_offset - 1) | ||
420 | pages = 1; | ||
421 | prev_offset = offset; | ||
422 | } else { | ||
423 | unsigned int roundup = 4; | ||
424 | while (roundup < pages) | ||
425 | roundup <<= 1; | ||
426 | pages = roundup; | ||
427 | } | ||
428 | |||
429 | if (pages > max_pages) | ||
430 | pages = max_pages; | ||
431 | |||
432 | /* Don't shrink readahead too fast */ | ||
433 | last_ra = atomic_read(&last_readahead_pages) / 2; | ||
434 | if (pages < last_ra) | ||
435 | pages = last_ra; | ||
436 | atomic_set(&last_readahead_pages, pages); | ||
437 | |||
438 | return pages; | ||
439 | } | ||
440 | |||
392 | /** | 441 | /** |
393 | * swapin_readahead - swap in pages in hope we need them soon | 442 | * swapin_readahead - swap in pages in hope we need them soon |
394 | * @entry: swap entry of this memory | 443 | * @entry: swap entry of this memory |
@@ -412,11 +461,16 @@ struct page *swapin_readahead(swp_entry_t entry, gfp_t gfp_mask, | |||
412 | struct vm_area_struct *vma, unsigned long addr) | 461 | struct vm_area_struct *vma, unsigned long addr) |
413 | { | 462 | { |
414 | struct page *page; | 463 | struct page *page; |
415 | unsigned long offset = swp_offset(entry); | 464 | unsigned long entry_offset = swp_offset(entry); |
465 | unsigned long offset = entry_offset; | ||
416 | unsigned long start_offset, end_offset; | 466 | unsigned long start_offset, end_offset; |
417 | unsigned long mask = (1UL << page_cluster) - 1; | 467 | unsigned long mask; |
418 | struct blk_plug plug; | 468 | struct blk_plug plug; |
419 | 469 | ||
470 | mask = swapin_nr_pages(offset) - 1; | ||
471 | if (!mask) | ||
472 | goto skip; | ||
473 | |||
420 | /* Read a page_cluster sized and aligned cluster around offset. */ | 474 | /* Read a page_cluster sized and aligned cluster around offset. */ |
421 | start_offset = offset & ~mask; | 475 | start_offset = offset & ~mask; |
422 | end_offset = offset | mask; | 476 | end_offset = offset | mask; |
@@ -430,10 +484,13 @@ struct page *swapin_readahead(swp_entry_t entry, gfp_t gfp_mask, | |||
430 | gfp_mask, vma, addr); | 484 | gfp_mask, vma, addr); |
431 | if (!page) | 485 | if (!page) |
432 | continue; | 486 | continue; |
487 | if (offset != entry_offset) | ||
488 | SetPageReadahead(page); | ||
433 | page_cache_release(page); | 489 | page_cache_release(page); |
434 | } | 490 | } |
435 | blk_finish_plug(&plug); | 491 | blk_finish_plug(&plug); |
436 | 492 | ||
437 | lru_add_drain(); /* Push any new pages onto the LRU now */ | 493 | lru_add_drain(); /* Push any new pages onto the LRU now */ |
494 | skip: | ||
438 | return read_swap_cache_async(entry, gfp_mask, vma, addr); | 495 | return read_swap_cache_async(entry, gfp_mask, vma, addr); |
439 | } | 496 | } |
diff --git a/mm/swapfile.c b/mm/swapfile.c index c6c13b050a58..4a7f7e6992b6 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c | |||
@@ -1923,7 +1923,6 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile) | |||
1923 | p->swap_map = NULL; | 1923 | p->swap_map = NULL; |
1924 | cluster_info = p->cluster_info; | 1924 | cluster_info = p->cluster_info; |
1925 | p->cluster_info = NULL; | 1925 | p->cluster_info = NULL; |
1926 | p->flags = 0; | ||
1927 | frontswap_map = frontswap_map_get(p); | 1926 | frontswap_map = frontswap_map_get(p); |
1928 | spin_unlock(&p->lock); | 1927 | spin_unlock(&p->lock); |
1929 | spin_unlock(&swap_lock); | 1928 | spin_unlock(&swap_lock); |
@@ -1949,6 +1948,16 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile) | |||
1949 | mutex_unlock(&inode->i_mutex); | 1948 | mutex_unlock(&inode->i_mutex); |
1950 | } | 1949 | } |
1951 | filp_close(swap_file, NULL); | 1950 | filp_close(swap_file, NULL); |
1951 | |||
1952 | /* | ||
1953 | * Clear the SWP_USED flag after all resources are freed so that swapon | ||
1954 | * can reuse this swap_info in alloc_swap_info() safely. It is ok to | ||
1955 | * not hold p->lock after we cleared its SWP_WRITEOK. | ||
1956 | */ | ||
1957 | spin_lock(&swap_lock); | ||
1958 | p->flags = 0; | ||
1959 | spin_unlock(&swap_lock); | ||
1960 | |||
1952 | err = 0; | 1961 | err = 0; |
1953 | atomic_inc(&proc_poll_event); | 1962 | atomic_inc(&proc_poll_event); |
1954 | wake_up_interruptible(&proc_poll_wait); | 1963 | wake_up_interruptible(&proc_poll_wait); |
diff --git a/mm/vmpressure.c b/mm/vmpressure.c index 196970a4541f..d4042e75f7c7 100644 --- a/mm/vmpressure.c +++ b/mm/vmpressure.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/mm.h> | 19 | #include <linux/mm.h> |
20 | #include <linux/vmstat.h> | 20 | #include <linux/vmstat.h> |
21 | #include <linux/eventfd.h> | 21 | #include <linux/eventfd.h> |
22 | #include <linux/slab.h> | ||
22 | #include <linux/swap.h> | 23 | #include <linux/swap.h> |
23 | #include <linux/printk.h> | 24 | #include <linux/printk.h> |
24 | #include <linux/vmpressure.h> | 25 | #include <linux/vmpressure.h> |
diff --git a/mm/vmstat.c b/mm/vmstat.c index 72496140ac08..def5dd2fbe61 100644 --- a/mm/vmstat.c +++ b/mm/vmstat.c | |||
@@ -851,12 +851,14 @@ const char * const vmstat_text[] = { | |||
851 | "thp_zero_page_alloc", | 851 | "thp_zero_page_alloc", |
852 | "thp_zero_page_alloc_failed", | 852 | "thp_zero_page_alloc_failed", |
853 | #endif | 853 | #endif |
854 | #ifdef CONFIG_DEBUG_TLBFLUSH | ||
854 | #ifdef CONFIG_SMP | 855 | #ifdef CONFIG_SMP |
855 | "nr_tlb_remote_flush", | 856 | "nr_tlb_remote_flush", |
856 | "nr_tlb_remote_flush_received", | 857 | "nr_tlb_remote_flush_received", |
857 | #endif | 858 | #endif /* CONFIG_SMP */ |
858 | "nr_tlb_local_flush_all", | 859 | "nr_tlb_local_flush_all", |
859 | "nr_tlb_local_flush_one", | 860 | "nr_tlb_local_flush_one", |
861 | #endif /* CONFIG_DEBUG_TLBFLUSH */ | ||
860 | 862 | ||
861 | #endif /* CONFIG_VM_EVENTS_COUNTERS */ | 863 | #endif /* CONFIG_VM_EVENTS_COUNTERS */ |
862 | }; | 864 | }; |