]> rtime.felk.cvut.cz Git - hercules2020/nv-tegra/linux-4.4.git/blob - rt-patches/0046-mm-workingset-Do-not-protect-workingset_shadow_nodes.patch
rt_patches: required rebase due to printk change
[hercules2020/nv-tegra/linux-4.4.git] / rt-patches / 0046-mm-workingset-Do-not-protect-workingset_shadow_nodes.patch
1 From 8bd00bc3ee3c0d2703954a1f09c1d96031d5a1a8 Mon Sep 17 00:00:00 2001
2 From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
3 Date: Thu, 29 Jan 2015 17:19:44 +0100
4 Subject: [PATCH 046/366] mm/workingset: Do not protect workingset_shadow_nodes
5  with irq off
6
7 workingset_shadow_nodes is protected by local_irq_disable(). Some users
8 use spin_lock_irq().
9 Replace the irq/on with a local_lock(). Rename workingset_shadow_nodes
10 so I catch users of it which will be introduced later.
11
12 Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
13 ---
14  include/linux/swap.h |  4 +++-
15  mm/filemap.c         | 11 ++++++++---
16  mm/truncate.c        |  7 +++++--
17  mm/workingset.c      | 23 ++++++++++++-----------
18  4 files changed, 28 insertions(+), 17 deletions(-)
19
20 diff --git a/include/linux/swap.h b/include/linux/swap.h
21 index d8ca2ea..973b384 100644
22 --- a/include/linux/swap.h
23 +++ b/include/linux/swap.h
24 @@ -11,6 +11,7 @@
25  #include <linux/fs.h>
26  #include <linux/atomic.h>
27  #include <linux/page-flags.h>
28 +#include <linux/locallock.h>
29  #include <asm/page.h>
30  
31  struct notifier_block;
32 @@ -252,7 +253,8 @@ struct swap_info_struct {
33  void *workingset_eviction(struct address_space *mapping, struct page *page);
34  bool workingset_refault(void *shadow);
35  void workingset_activation(struct page *page);
36 -extern struct list_lru workingset_shadow_nodes;
37 +extern struct list_lru __workingset_shadow_nodes;
38 +DECLARE_LOCAL_IRQ_LOCK(workingset_shadow_lock);
39  
40  static inline unsigned int workingset_node_pages(struct radix_tree_node *node)
41  {
42 diff --git a/mm/filemap.c b/mm/filemap.c
43 index fad46b1..7fb06d4 100644
44 --- a/mm/filemap.c
45 +++ b/mm/filemap.c
46 @@ -144,9 +144,12 @@ static int page_cache_tree_insert(struct address_space *mapping,
47                  * node->private_list is protected by
48                  * mapping->tree_lock.
49                  */
50 -               if (!list_empty(&node->private_list))
51 -                       list_lru_del(&workingset_shadow_nodes,
52 +               if (!list_empty(&node->private_list)) {
53 +                       local_lock(workingset_shadow_lock);
54 +                       list_lru_del(&__workingset_shadow_nodes,
55                                      &node->private_list);
56 +                       local_unlock(workingset_shadow_lock);
57 +               }
58         }
59         return 0;
60  }
61 @@ -218,7 +221,9 @@ static void page_cache_tree_delete(struct address_space *mapping,
62         if (!workingset_node_pages(node) &&
63             list_empty(&node->private_list)) {
64                 node->private_data = mapping;
65 -               list_lru_add(&workingset_shadow_nodes, &node->private_list);
66 +               local_lock(workingset_shadow_lock);
67 +               list_lru_add(&__workingset_shadow_nodes, &node->private_list);
68 +               local_unlock(workingset_shadow_lock);
69         }
70  }
71  
72 diff --git a/mm/truncate.c b/mm/truncate.c
73 index 76e35ad..5f19642 100644
74 --- a/mm/truncate.c
75 +++ b/mm/truncate.c
76 @@ -56,8 +56,11 @@ static void clear_exceptional_entry(struct address_space *mapping,
77          * protected by mapping->tree_lock.
78          */
79         if (!workingset_node_shadows(node) &&
80 -           !list_empty(&node->private_list))
81 -               list_lru_del(&workingset_shadow_nodes, &node->private_list);
82 +           !list_empty(&node->private_list)) {
83 +               local_lock(workingset_shadow_lock);
84 +               list_lru_del(&__workingset_shadow_nodes, &node->private_list);
85 +               local_unlock(workingset_shadow_lock);
86 +       }
87         __radix_tree_delete_node(&mapping->page_tree, node);
88  unlock:
89         spin_unlock_irq(&mapping->tree_lock);
90 diff --git a/mm/workingset.c b/mm/workingset.c
91 index df66f42..6db7b24 100644
92 --- a/mm/workingset.c
93 +++ b/mm/workingset.c
94 @@ -264,7 +264,8 @@ void workingset_activation(struct page *page)
95   * point where they would still be useful.
96   */
97  
98 -struct list_lru workingset_shadow_nodes;
99 +struct list_lru __workingset_shadow_nodes;
100 +DEFINE_LOCAL_IRQ_LOCK(workingset_shadow_lock);
101  
102  static unsigned long count_shadow_nodes(struct shrinker *shrinker,
103                                         struct shrink_control *sc)
104 @@ -274,9 +275,9 @@ static unsigned long count_shadow_nodes(struct shrinker *shrinker,
105         unsigned long pages;
106  
107         /* list_lru lock nests inside IRQ-safe mapping->tree_lock */
108 -       local_irq_disable();
109 -       shadow_nodes = list_lru_shrink_count(&workingset_shadow_nodes, sc);
110 -       local_irq_enable();
111 +       local_lock_irq(workingset_shadow_lock);
112 +       shadow_nodes = list_lru_shrink_count(&__workingset_shadow_nodes, sc);
113 +       local_unlock_irq(workingset_shadow_lock);
114  
115         pages = node_present_pages(sc->nid);
116         /*
117 @@ -361,9 +362,9 @@ static enum lru_status shadow_lru_isolate(struct list_head *item,
118         spin_unlock(&mapping->tree_lock);
119         ret = LRU_REMOVED_RETRY;
120  out:
121 -       local_irq_enable();
122 +       local_unlock_irq(workingset_shadow_lock);
123         cond_resched();
124 -       local_irq_disable();
125 +       local_lock_irq(workingset_shadow_lock);
126         spin_lock(lru_lock);
127         return ret;
128  }
129 @@ -374,10 +375,10 @@ static unsigned long scan_shadow_nodes(struct shrinker *shrinker,
130         unsigned long ret;
131  
132         /* list_lru lock nests inside IRQ-safe mapping->tree_lock */
133 -       local_irq_disable();
134 -       ret =  list_lru_shrink_walk(&workingset_shadow_nodes, sc,
135 +       local_lock_irq(workingset_shadow_lock);
136 +       ret =  list_lru_shrink_walk(&__workingset_shadow_nodes, sc,
137                                     shadow_lru_isolate, NULL);
138 -       local_irq_enable();
139 +       local_unlock_irq(workingset_shadow_lock);
140         return ret;
141  }
142  
143 @@ -398,7 +399,7 @@ static int __init workingset_init(void)
144  {
145         int ret;
146  
147 -       ret = list_lru_init_key(&workingset_shadow_nodes, &shadow_nodes_key);
148 +       ret = list_lru_init_key(&__workingset_shadow_nodes, &shadow_nodes_key);
149         if (ret)
150                 goto err;
151         ret = register_shrinker(&workingset_shadow_shrinker);
152 @@ -406,7 +407,7 @@ static int __init workingset_init(void)
153                 goto err_list_lru;
154         return 0;
155  err_list_lru:
156 -       list_lru_destroy(&workingset_shadow_nodes);
157 +       list_lru_destroy(&__workingset_shadow_nodes);
158  err:
159         return ret;
160  }
161 -- 
162 1.9.1
163