diff options
author | Ingo Molnar <mingo@elte.hu> | 2010-07-21 15:43:03 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2010-07-21 15:43:06 -0400 |
commit | 9dcdbf7a33d9018ac5d45debcf261be648bdd56a (patch) | |
tree | bbcc1a018f11ff76cd7ce174ef3ffe2c02da07ee /mm | |
parent | cc5edb0eb9ce892b530e34a5d110382483587942 (diff) | |
parent | cd5b8f8755a89a57fc8c408d284b8b613f090345 (diff) |
Merge branch 'linus' into perf/core
Merge reason: Pick up the latest perf fixes.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'mm')
-rw-r--r-- | mm/Kconfig | 3 | ||||
-rw-r--r-- | mm/Makefile | 2 | ||||
-rw-r--r-- | mm/backing-dev.c | 17 | ||||
-rw-r--r-- | mm/bootmem.c | 24 | ||||
-rw-r--r-- | mm/memblock.c | 541 | ||||
-rw-r--r-- | mm/page-writeback.c | 3 | ||||
-rw-r--r-- | mm/page_alloc.c | 8 | ||||
-rw-r--r-- | mm/page_cgroup.c | 7 | ||||
-rw-r--r-- | mm/vmscan.c | 10 |
9 files changed, 592 insertions, 23 deletions
diff --git a/mm/Kconfig b/mm/Kconfig index 527136b22384..f4e516e9c37c 100644 --- a/mm/Kconfig +++ b/mm/Kconfig | |||
@@ -128,6 +128,9 @@ config SPARSEMEM_VMEMMAP | |||
128 | pfn_to_page and page_to_pfn operations. This is the most | 128 | pfn_to_page and page_to_pfn operations. This is the most |
129 | efficient option when sufficient kernel resources are available. | 129 | efficient option when sufficient kernel resources are available. |
130 | 130 | ||
131 | config HAVE_MEMBLOCK | ||
132 | boolean | ||
133 | |||
131 | # eventually, we can have this option just 'select SPARSEMEM' | 134 | # eventually, we can have this option just 'select SPARSEMEM' |
132 | config MEMORY_HOTPLUG | 135 | config MEMORY_HOTPLUG |
133 | bool "Allow for memory hot-add" | 136 | bool "Allow for memory hot-add" |
diff --git a/mm/Makefile b/mm/Makefile index 8982504bd03b..34b2546a9e37 100644 --- a/mm/Makefile +++ b/mm/Makefile | |||
@@ -15,6 +15,8 @@ obj-y := bootmem.o filemap.o mempool.o oom_kill.o fadvise.o \ | |||
15 | $(mmu-y) | 15 | $(mmu-y) |
16 | obj-y += init-mm.o | 16 | obj-y += init-mm.o |
17 | 17 | ||
18 | obj-$(CONFIG_HAVE_MEMBLOCK) += memblock.o | ||
19 | |||
18 | obj-$(CONFIG_BOUNCE) += bounce.o | 20 | obj-$(CONFIG_BOUNCE) += bounce.o |
19 | obj-$(CONFIG_SWAP) += page_io.o swap_state.o swapfile.o thrash.o | 21 | obj-$(CONFIG_SWAP) += page_io.o swap_state.o swapfile.o thrash.o |
20 | obj-$(CONFIG_HAS_DMA) += dmapool.o | 22 | obj-$(CONFIG_HAS_DMA) += dmapool.o |
diff --git a/mm/backing-dev.c b/mm/backing-dev.c index 660a87a22511..123bcef13e51 100644 --- a/mm/backing-dev.c +++ b/mm/backing-dev.c | |||
@@ -104,15 +104,13 @@ static int bdi_debug_stats_show(struct seq_file *m, void *v) | |||
104 | "b_more_io: %8lu\n" | 104 | "b_more_io: %8lu\n" |
105 | "bdi_list: %8u\n" | 105 | "bdi_list: %8u\n" |
106 | "state: %8lx\n" | 106 | "state: %8lx\n" |
107 | "wb_mask: %8lx\n" | 107 | "wb_list: %8u\n", |
108 | "wb_list: %8u\n" | ||
109 | "wb_cnt: %8u\n", | ||
110 | (unsigned long) K(bdi_stat(bdi, BDI_WRITEBACK)), | 108 | (unsigned long) K(bdi_stat(bdi, BDI_WRITEBACK)), |
111 | (unsigned long) K(bdi_stat(bdi, BDI_RECLAIMABLE)), | 109 | (unsigned long) K(bdi_stat(bdi, BDI_RECLAIMABLE)), |
112 | K(bdi_thresh), K(dirty_thresh), | 110 | K(bdi_thresh), K(dirty_thresh), |
113 | K(background_thresh), nr_wb, nr_dirty, nr_io, nr_more_io, | 111 | K(background_thresh), nr_wb, nr_dirty, nr_io, nr_more_io, |
114 | !list_empty(&bdi->bdi_list), bdi->state, bdi->wb_mask, | 112 | !list_empty(&bdi->bdi_list), bdi->state, |
115 | !list_empty(&bdi->wb_list), bdi->wb_cnt); | 113 | !list_empty(&bdi->wb_list)); |
116 | #undef K | 114 | #undef K |
117 | 115 | ||
118 | return 0; | 116 | return 0; |
@@ -340,14 +338,13 @@ int bdi_has_dirty_io(struct backing_dev_info *bdi) | |||
340 | static void bdi_flush_io(struct backing_dev_info *bdi) | 338 | static void bdi_flush_io(struct backing_dev_info *bdi) |
341 | { | 339 | { |
342 | struct writeback_control wbc = { | 340 | struct writeback_control wbc = { |
343 | .bdi = bdi, | ||
344 | .sync_mode = WB_SYNC_NONE, | 341 | .sync_mode = WB_SYNC_NONE, |
345 | .older_than_this = NULL, | 342 | .older_than_this = NULL, |
346 | .range_cyclic = 1, | 343 | .range_cyclic = 1, |
347 | .nr_to_write = 1024, | 344 | .nr_to_write = 1024, |
348 | }; | 345 | }; |
349 | 346 | ||
350 | writeback_inodes_wbc(&wbc); | 347 | writeback_inodes_wb(&bdi->wb, &wbc); |
351 | } | 348 | } |
352 | 349 | ||
353 | /* | 350 | /* |
@@ -675,12 +672,6 @@ int bdi_init(struct backing_dev_info *bdi) | |||
675 | 672 | ||
676 | bdi_wb_init(&bdi->wb, bdi); | 673 | bdi_wb_init(&bdi->wb, bdi); |
677 | 674 | ||
678 | /* | ||
679 | * Just one thread support for now, hard code mask and count | ||
680 | */ | ||
681 | bdi->wb_mask = 1; | ||
682 | bdi->wb_cnt = 1; | ||
683 | |||
684 | for (i = 0; i < NR_BDI_STAT_ITEMS; i++) { | 675 | for (i = 0; i < NR_BDI_STAT_ITEMS; i++) { |
685 | err = percpu_counter_init(&bdi->bdi_stat[i], 0); | 676 | err = percpu_counter_init(&bdi->bdi_stat[i], 0); |
686 | if (err) | 677 | if (err) |
diff --git a/mm/bootmem.c b/mm/bootmem.c index 58c66cc5056a..142c84a54993 100644 --- a/mm/bootmem.c +++ b/mm/bootmem.c | |||
@@ -833,15 +833,24 @@ static void * __init ___alloc_bootmem_node(bootmem_data_t *bdata, | |||
833 | void * __init __alloc_bootmem_node(pg_data_t *pgdat, unsigned long size, | 833 | void * __init __alloc_bootmem_node(pg_data_t *pgdat, unsigned long size, |
834 | unsigned long align, unsigned long goal) | 834 | unsigned long align, unsigned long goal) |
835 | { | 835 | { |
836 | void *ptr; | ||
837 | |||
836 | if (WARN_ON_ONCE(slab_is_available())) | 838 | if (WARN_ON_ONCE(slab_is_available())) |
837 | return kzalloc_node(size, GFP_NOWAIT, pgdat->node_id); | 839 | return kzalloc_node(size, GFP_NOWAIT, pgdat->node_id); |
838 | 840 | ||
839 | #ifdef CONFIG_NO_BOOTMEM | 841 | #ifdef CONFIG_NO_BOOTMEM |
840 | return __alloc_memory_core_early(pgdat->node_id, size, align, | 842 | ptr = __alloc_memory_core_early(pgdat->node_id, size, align, |
843 | goal, -1ULL); | ||
844 | if (ptr) | ||
845 | return ptr; | ||
846 | |||
847 | ptr = __alloc_memory_core_early(MAX_NUMNODES, size, align, | ||
841 | goal, -1ULL); | 848 | goal, -1ULL); |
842 | #else | 849 | #else |
843 | return ___alloc_bootmem_node(pgdat->bdata, size, align, goal, 0); | 850 | ptr = ___alloc_bootmem_node(pgdat->bdata, size, align, goal, 0); |
844 | #endif | 851 | #endif |
852 | |||
853 | return ptr; | ||
845 | } | 854 | } |
846 | 855 | ||
847 | void * __init __alloc_bootmem_node_high(pg_data_t *pgdat, unsigned long size, | 856 | void * __init __alloc_bootmem_node_high(pg_data_t *pgdat, unsigned long size, |
@@ -977,14 +986,21 @@ void * __init __alloc_bootmem_low(unsigned long size, unsigned long align, | |||
977 | void * __init __alloc_bootmem_low_node(pg_data_t *pgdat, unsigned long size, | 986 | void * __init __alloc_bootmem_low_node(pg_data_t *pgdat, unsigned long size, |
978 | unsigned long align, unsigned long goal) | 987 | unsigned long align, unsigned long goal) |
979 | { | 988 | { |
989 | void *ptr; | ||
990 | |||
980 | if (WARN_ON_ONCE(slab_is_available())) | 991 | if (WARN_ON_ONCE(slab_is_available())) |
981 | return kzalloc_node(size, GFP_NOWAIT, pgdat->node_id); | 992 | return kzalloc_node(size, GFP_NOWAIT, pgdat->node_id); |
982 | 993 | ||
983 | #ifdef CONFIG_NO_BOOTMEM | 994 | #ifdef CONFIG_NO_BOOTMEM |
984 | return __alloc_memory_core_early(pgdat->node_id, size, align, | 995 | ptr = __alloc_memory_core_early(pgdat->node_id, size, align, |
996 | goal, ARCH_LOW_ADDRESS_LIMIT); | ||
997 | if (ptr) | ||
998 | return ptr; | ||
999 | ptr = __alloc_memory_core_early(MAX_NUMNODES, size, align, | ||
985 | goal, ARCH_LOW_ADDRESS_LIMIT); | 1000 | goal, ARCH_LOW_ADDRESS_LIMIT); |
986 | #else | 1001 | #else |
987 | return ___alloc_bootmem_node(pgdat->bdata, size, align, | 1002 | ptr = ___alloc_bootmem_node(pgdat->bdata, size, align, |
988 | goal, ARCH_LOW_ADDRESS_LIMIT); | 1003 | goal, ARCH_LOW_ADDRESS_LIMIT); |
989 | #endif | 1004 | #endif |
1005 | return ptr; | ||
990 | } | 1006 | } |
diff --git a/mm/memblock.c b/mm/memblock.c new file mode 100644 index 000000000000..3024eb30fc27 --- /dev/null +++ b/mm/memblock.c | |||
@@ -0,0 +1,541 @@ | |||
1 | /* | ||
2 | * Procedures for maintaining information about logical memory blocks. | ||
3 | * | ||
4 | * Peter Bergner, IBM Corp. June 2001. | ||
5 | * Copyright (C) 2001 Peter Bergner. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * as published by the Free Software Foundation; either version | ||
10 | * 2 of the License, or (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/bitops.h> | ||
16 | #include <linux/memblock.h> | ||
17 | |||
18 | #define MEMBLOCK_ALLOC_ANYWHERE 0 | ||
19 | |||
20 | struct memblock memblock; | ||
21 | |||
22 | static int memblock_debug; | ||
23 | |||
24 | static int __init early_memblock(char *p) | ||
25 | { | ||
26 | if (p && strstr(p, "debug")) | ||
27 | memblock_debug = 1; | ||
28 | return 0; | ||
29 | } | ||
30 | early_param("memblock", early_memblock); | ||
31 | |||
32 | static void memblock_dump(struct memblock_region *region, char *name) | ||
33 | { | ||
34 | unsigned long long base, size; | ||
35 | int i; | ||
36 | |||
37 | pr_info(" %s.cnt = 0x%lx\n", name, region->cnt); | ||
38 | |||
39 | for (i = 0; i < region->cnt; i++) { | ||
40 | base = region->region[i].base; | ||
41 | size = region->region[i].size; | ||
42 | |||
43 | pr_info(" %s[0x%x]\t0x%016llx - 0x%016llx, 0x%llx bytes\n", | ||
44 | name, i, base, base + size - 1, size); | ||
45 | } | ||
46 | } | ||
47 | |||
48 | void memblock_dump_all(void) | ||
49 | { | ||
50 | if (!memblock_debug) | ||
51 | return; | ||
52 | |||
53 | pr_info("MEMBLOCK configuration:\n"); | ||
54 | pr_info(" rmo_size = 0x%llx\n", (unsigned long long)memblock.rmo_size); | ||
55 | pr_info(" memory.size = 0x%llx\n", (unsigned long long)memblock.memory.size); | ||
56 | |||
57 | memblock_dump(&memblock.memory, "memory"); | ||
58 | memblock_dump(&memblock.reserved, "reserved"); | ||
59 | } | ||
60 | |||
61 | static unsigned long memblock_addrs_overlap(u64 base1, u64 size1, u64 base2, | ||
62 | u64 size2) | ||
63 | { | ||
64 | return ((base1 < (base2 + size2)) && (base2 < (base1 + size1))); | ||
65 | } | ||
66 | |||
67 | static long memblock_addrs_adjacent(u64 base1, u64 size1, u64 base2, u64 size2) | ||
68 | { | ||
69 | if (base2 == base1 + size1) | ||
70 | return 1; | ||
71 | else if (base1 == base2 + size2) | ||
72 | return -1; | ||
73 | |||
74 | return 0; | ||
75 | } | ||
76 | |||
77 | static long memblock_regions_adjacent(struct memblock_region *rgn, | ||
78 | unsigned long r1, unsigned long r2) | ||
79 | { | ||
80 | u64 base1 = rgn->region[r1].base; | ||
81 | u64 size1 = rgn->region[r1].size; | ||
82 | u64 base2 = rgn->region[r2].base; | ||
83 | u64 size2 = rgn->region[r2].size; | ||
84 | |||
85 | return memblock_addrs_adjacent(base1, size1, base2, size2); | ||
86 | } | ||
87 | |||
88 | static void memblock_remove_region(struct memblock_region *rgn, unsigned long r) | ||
89 | { | ||
90 | unsigned long i; | ||
91 | |||
92 | for (i = r; i < rgn->cnt - 1; i++) { | ||
93 | rgn->region[i].base = rgn->region[i + 1].base; | ||
94 | rgn->region[i].size = rgn->region[i + 1].size; | ||
95 | } | ||
96 | rgn->cnt--; | ||
97 | } | ||
98 | |||
99 | /* Assumption: base addr of region 1 < base addr of region 2 */ | ||
100 | static void memblock_coalesce_regions(struct memblock_region *rgn, | ||
101 | unsigned long r1, unsigned long r2) | ||
102 | { | ||
103 | rgn->region[r1].size += rgn->region[r2].size; | ||
104 | memblock_remove_region(rgn, r2); | ||
105 | } | ||
106 | |||
107 | void __init memblock_init(void) | ||
108 | { | ||
109 | /* Create a dummy zero size MEMBLOCK which will get coalesced away later. | ||
110 | * This simplifies the memblock_add() code below... | ||
111 | */ | ||
112 | memblock.memory.region[0].base = 0; | ||
113 | memblock.memory.region[0].size = 0; | ||
114 | memblock.memory.cnt = 1; | ||
115 | |||
116 | /* Ditto. */ | ||
117 | memblock.reserved.region[0].base = 0; | ||
118 | memblock.reserved.region[0].size = 0; | ||
119 | memblock.reserved.cnt = 1; | ||
120 | } | ||
121 | |||
122 | void __init memblock_analyze(void) | ||
123 | { | ||
124 | int i; | ||
125 | |||
126 | memblock.memory.size = 0; | ||
127 | |||
128 | for (i = 0; i < memblock.memory.cnt; i++) | ||
129 | memblock.memory.size += memblock.memory.region[i].size; | ||
130 | } | ||
131 | |||
132 | static long memblock_add_region(struct memblock_region *rgn, u64 base, u64 size) | ||
133 | { | ||
134 | unsigned long coalesced = 0; | ||
135 | long adjacent, i; | ||
136 | |||
137 | if ((rgn->cnt == 1) && (rgn->region[0].size == 0)) { | ||
138 | rgn->region[0].base = base; | ||
139 | rgn->region[0].size = size; | ||
140 | return 0; | ||
141 | } | ||
142 | |||
143 | /* First try and coalesce this MEMBLOCK with another. */ | ||
144 | for (i = 0; i < rgn->cnt; i++) { | ||
145 | u64 rgnbase = rgn->region[i].base; | ||
146 | u64 rgnsize = rgn->region[i].size; | ||
147 | |||
148 | if ((rgnbase == base) && (rgnsize == size)) | ||
149 | /* Already have this region, so we're done */ | ||
150 | return 0; | ||
151 | |||
152 | adjacent = memblock_addrs_adjacent(base, size, rgnbase, rgnsize); | ||
153 | if (adjacent > 0) { | ||
154 | rgn->region[i].base -= size; | ||
155 | rgn->region[i].size += size; | ||
156 | coalesced++; | ||
157 | break; | ||
158 | } else if (adjacent < 0) { | ||
159 | rgn->region[i].size += size; | ||
160 | coalesced++; | ||
161 | break; | ||
162 | } | ||
163 | } | ||
164 | |||
165 | if ((i < rgn->cnt - 1) && memblock_regions_adjacent(rgn, i, i+1)) { | ||
166 | memblock_coalesce_regions(rgn, i, i+1); | ||
167 | coalesced++; | ||
168 | } | ||
169 | |||
170 | if (coalesced) | ||
171 | return coalesced; | ||
172 | if (rgn->cnt >= MAX_MEMBLOCK_REGIONS) | ||
173 | return -1; | ||
174 | |||
175 | /* Couldn't coalesce the MEMBLOCK, so add it to the sorted table. */ | ||
176 | for (i = rgn->cnt - 1; i >= 0; i--) { | ||
177 | if (base < rgn->region[i].base) { | ||
178 | rgn->region[i+1].base = rgn->region[i].base; | ||
179 | rgn->region[i+1].size = rgn->region[i].size; | ||
180 | } else { | ||
181 | rgn->region[i+1].base = base; | ||
182 | rgn->region[i+1].size = size; | ||
183 | break; | ||
184 | } | ||
185 | } | ||
186 | |||
187 | if (base < rgn->region[0].base) { | ||
188 | rgn->region[0].base = base; | ||
189 | rgn->region[0].size = size; | ||
190 | } | ||
191 | rgn->cnt++; | ||
192 | |||
193 | return 0; | ||
194 | } | ||
195 | |||
196 | long memblock_add(u64 base, u64 size) | ||
197 | { | ||
198 | struct memblock_region *_rgn = &memblock.memory; | ||
199 | |||
200 | /* On pSeries LPAR systems, the first MEMBLOCK is our RMO region. */ | ||
201 | if (base == 0) | ||
202 | memblock.rmo_size = size; | ||
203 | |||
204 | return memblock_add_region(_rgn, base, size); | ||
205 | |||
206 | } | ||
207 | |||
208 | static long __memblock_remove(struct memblock_region *rgn, u64 base, u64 size) | ||
209 | { | ||
210 | u64 rgnbegin, rgnend; | ||
211 | u64 end = base + size; | ||
212 | int i; | ||
213 | |||
214 | rgnbegin = rgnend = 0; /* supress gcc warnings */ | ||
215 | |||
216 | /* Find the region where (base, size) belongs to */ | ||
217 | for (i=0; i < rgn->cnt; i++) { | ||
218 | rgnbegin = rgn->region[i].base; | ||
219 | rgnend = rgnbegin + rgn->region[i].size; | ||
220 | |||
221 | if ((rgnbegin <= base) && (end <= rgnend)) | ||
222 | break; | ||
223 | } | ||
224 | |||
225 | /* Didn't find the region */ | ||
226 | if (i == rgn->cnt) | ||
227 | return -1; | ||
228 | |||
229 | /* Check to see if we are removing entire region */ | ||
230 | if ((rgnbegin == base) && (rgnend == end)) { | ||
231 | memblock_remove_region(rgn, i); | ||
232 | return 0; | ||
233 | } | ||
234 | |||
235 | /* Check to see if region is matching at the front */ | ||
236 | if (rgnbegin == base) { | ||
237 | rgn->region[i].base = end; | ||
238 | rgn->region[i].size -= size; | ||
239 | return 0; | ||
240 | } | ||
241 | |||
242 | /* Check to see if the region is matching at the end */ | ||
243 | if (rgnend == end) { | ||
244 | rgn->region[i].size -= size; | ||
245 | return 0; | ||
246 | } | ||
247 | |||
248 | /* | ||
249 | * We need to split the entry - adjust the current one to the | ||
250 | * beginging of the hole and add the region after hole. | ||
251 | */ | ||
252 | rgn->region[i].size = base - rgn->region[i].base; | ||
253 | return memblock_add_region(rgn, end, rgnend - end); | ||
254 | } | ||
255 | |||
256 | long memblock_remove(u64 base, u64 size) | ||
257 | { | ||
258 | return __memblock_remove(&memblock.memory, base, size); | ||
259 | } | ||
260 | |||
261 | long __init memblock_free(u64 base, u64 size) | ||
262 | { | ||
263 | return __memblock_remove(&memblock.reserved, base, size); | ||
264 | } | ||
265 | |||
266 | long __init memblock_reserve(u64 base, u64 size) | ||
267 | { | ||
268 | struct memblock_region *_rgn = &memblock.reserved; | ||
269 | |||
270 | BUG_ON(0 == size); | ||
271 | |||
272 | return memblock_add_region(_rgn, base, size); | ||
273 | } | ||
274 | |||
275 | long memblock_overlaps_region(struct memblock_region *rgn, u64 base, u64 size) | ||
276 | { | ||
277 | unsigned long i; | ||
278 | |||
279 | for (i = 0; i < rgn->cnt; i++) { | ||
280 | u64 rgnbase = rgn->region[i].base; | ||
281 | u64 rgnsize = rgn->region[i].size; | ||
282 | if (memblock_addrs_overlap(base, size, rgnbase, rgnsize)) | ||
283 | break; | ||
284 | } | ||
285 | |||
286 | return (i < rgn->cnt) ? i : -1; | ||
287 | } | ||
288 | |||
289 | static u64 memblock_align_down(u64 addr, u64 size) | ||
290 | { | ||
291 | return addr & ~(size - 1); | ||
292 | } | ||
293 | |||
294 | static u64 memblock_align_up(u64 addr, u64 size) | ||
295 | { | ||
296 | return (addr + (size - 1)) & ~(size - 1); | ||
297 | } | ||
298 | |||
299 | static u64 __init memblock_alloc_nid_unreserved(u64 start, u64 end, | ||
300 | u64 size, u64 align) | ||
301 | { | ||
302 | u64 base, res_base; | ||
303 | long j; | ||
304 | |||
305 | base = memblock_align_down((end - size), align); | ||
306 | while (start <= base) { | ||
307 | j = memblock_overlaps_region(&memblock.reserved, base, size); | ||
308 | if (j < 0) { | ||
309 | /* this area isn't reserved, take it */ | ||
310 | if (memblock_add_region(&memblock.reserved, base, size) < 0) | ||
311 | base = ~(u64)0; | ||
312 | return base; | ||
313 | } | ||
314 | res_base = memblock.reserved.region[j].base; | ||
315 | if (res_base < size) | ||
316 | break; | ||
317 | base = memblock_align_down(res_base - size, align); | ||
318 | } | ||
319 | |||
320 | return ~(u64)0; | ||
321 | } | ||
322 | |||
323 | static u64 __init memblock_alloc_nid_region(struct memblock_property *mp, | ||
324 | u64 (*nid_range)(u64, u64, int *), | ||
325 | u64 size, u64 align, int nid) | ||
326 | { | ||
327 | u64 start, end; | ||
328 | |||
329 | start = mp->base; | ||
330 | end = start + mp->size; | ||
331 | |||
332 | start = memblock_align_up(start, align); | ||
333 | while (start < end) { | ||
334 | u64 this_end; | ||
335 | int this_nid; | ||
336 | |||
337 | this_end = nid_range(start, end, &this_nid); | ||
338 | if (this_nid == nid) { | ||
339 | u64 ret = memblock_alloc_nid_unreserved(start, this_end, | ||
340 | size, align); | ||
341 | if (ret != ~(u64)0) | ||
342 | return ret; | ||
343 | } | ||
344 | start = this_end; | ||
345 | } | ||
346 | |||
347 | return ~(u64)0; | ||
348 | } | ||
349 | |||
350 | u64 __init memblock_alloc_nid(u64 size, u64 align, int nid, | ||
351 | u64 (*nid_range)(u64 start, u64 end, int *nid)) | ||
352 | { | ||
353 | struct memblock_region *mem = &memblock.memory; | ||
354 | int i; | ||
355 | |||
356 | BUG_ON(0 == size); | ||
357 | |||
358 | size = memblock_align_up(size, align); | ||
359 | |||
360 | for (i = 0; i < mem->cnt; i++) { | ||
361 | u64 ret = memblock_alloc_nid_region(&mem->region[i], | ||
362 | nid_range, | ||
363 | size, align, nid); | ||
364 | if (ret != ~(u64)0) | ||
365 | return ret; | ||
366 | } | ||
367 | |||
368 | return memblock_alloc(size, align); | ||
369 | } | ||
370 | |||
371 | u64 __init memblock_alloc(u64 size, u64 align) | ||
372 | { | ||
373 | return memblock_alloc_base(size, align, MEMBLOCK_ALLOC_ANYWHERE); | ||
374 | } | ||
375 | |||
376 | u64 __init memblock_alloc_base(u64 size, u64 align, u64 max_addr) | ||
377 | { | ||
378 | u64 alloc; | ||
379 | |||
380 | alloc = __memblock_alloc_base(size, align, max_addr); | ||
381 | |||
382 | if (alloc == 0) | ||
383 | panic("ERROR: Failed to allocate 0x%llx bytes below 0x%llx.\n", | ||
384 | (unsigned long long) size, (unsigned long long) max_addr); | ||
385 | |||
386 | return alloc; | ||
387 | } | ||
388 | |||
389 | u64 __init __memblock_alloc_base(u64 size, u64 align, u64 max_addr) | ||
390 | { | ||
391 | long i, j; | ||
392 | u64 base = 0; | ||
393 | u64 res_base; | ||
394 | |||
395 | BUG_ON(0 == size); | ||
396 | |||
397 | size = memblock_align_up(size, align); | ||
398 | |||
399 | /* On some platforms, make sure we allocate lowmem */ | ||
400 | /* Note that MEMBLOCK_REAL_LIMIT may be MEMBLOCK_ALLOC_ANYWHERE */ | ||
401 | if (max_addr == MEMBLOCK_ALLOC_ANYWHERE) | ||
402 | max_addr = MEMBLOCK_REAL_LIMIT; | ||
403 | |||
404 | for (i = memblock.memory.cnt - 1; i >= 0; i--) { | ||
405 | u64 memblockbase = memblock.memory.region[i].base; | ||
406 | u64 memblocksize = memblock.memory.region[i].size; | ||
407 | |||
408 | if (memblocksize < size) | ||
409 | continue; | ||
410 | if (max_addr == MEMBLOCK_ALLOC_ANYWHERE) | ||
411 | base = memblock_align_down(memblockbase + memblocksize - size, align); | ||
412 | else if (memblockbase < max_addr) { | ||
413 | base = min(memblockbase + memblocksize, max_addr); | ||
414 | base = memblock_align_down(base - size, align); | ||
415 | } else | ||
416 | continue; | ||
417 | |||
418 | while (base && memblockbase <= base) { | ||
419 | j = memblock_overlaps_region(&memblock.reserved, base, size); | ||
420 | if (j < 0) { | ||
421 | /* this area isn't reserved, take it */ | ||
422 | if (memblock_add_region(&memblock.reserved, base, size) < 0) | ||
423 | return 0; | ||
424 | return base; | ||
425 | } | ||
426 | res_base = memblock.reserved.region[j].base; | ||
427 | if (res_base < size) | ||
428 | break; | ||
429 | base = memblock_align_down(res_base - size, align); | ||
430 | } | ||
431 | } | ||
432 | return 0; | ||
433 | } | ||
434 | |||
435 | /* You must call memblock_analyze() before this. */ | ||
436 | u64 __init memblock_phys_mem_size(void) | ||
437 | { | ||
438 | return memblock.memory.size; | ||
439 | } | ||
440 | |||
441 | u64 memblock_end_of_DRAM(void) | ||
442 | { | ||
443 | int idx = memblock.memory.cnt - 1; | ||
444 | |||
445 | return (memblock.memory.region[idx].base + memblock.memory.region[idx].size); | ||
446 | } | ||
447 | |||
448 | /* You must call memblock_analyze() after this. */ | ||
449 | void __init memblock_enforce_memory_limit(u64 memory_limit) | ||
450 | { | ||
451 | unsigned long i; | ||
452 | u64 limit; | ||
453 | struct memblock_property *p; | ||
454 | |||
455 | if (!memory_limit) | ||
456 | return; | ||
457 | |||
458 | /* Truncate the memblock regions to satisfy the memory limit. */ | ||
459 | limit = memory_limit; | ||
460 | for (i = 0; i < memblock.memory.cnt; i++) { | ||
461 | if (limit > memblock.memory.region[i].size) { | ||
462 | limit -= memblock.memory.region[i].size; | ||
463 | continue; | ||
464 | } | ||
465 | |||
466 | memblock.memory.region[i].size = limit; | ||
467 | memblock.memory.cnt = i + 1; | ||
468 | break; | ||
469 | } | ||
470 | |||
471 | if (memblock.memory.region[0].size < memblock.rmo_size) | ||
472 | memblock.rmo_size = memblock.memory.region[0].size; | ||
473 | |||
474 | memory_limit = memblock_end_of_DRAM(); | ||
475 | |||
476 | /* And truncate any reserves above the limit also. */ | ||
477 | for (i = 0; i < memblock.reserved.cnt; i++) { | ||
478 | p = &memblock.reserved.region[i]; | ||
479 | |||
480 | if (p->base > memory_limit) | ||
481 | p->size = 0; | ||
482 | else if ((p->base + p->size) > memory_limit) | ||
483 | p->size = memory_limit - p->base; | ||
484 | |||
485 | if (p->size == 0) { | ||
486 | memblock_remove_region(&memblock.reserved, i); | ||
487 | i--; | ||
488 | } | ||
489 | } | ||
490 | } | ||
491 | |||
492 | int __init memblock_is_reserved(u64 addr) | ||
493 | { | ||
494 | int i; | ||
495 | |||
496 | for (i = 0; i < memblock.reserved.cnt; i++) { | ||
497 | u64 upper = memblock.reserved.region[i].base + | ||
498 | memblock.reserved.region[i].size - 1; | ||
499 | if ((addr >= memblock.reserved.region[i].base) && (addr <= upper)) | ||
500 | return 1; | ||
501 | } | ||
502 | return 0; | ||
503 | } | ||
504 | |||
505 | int memblock_is_region_reserved(u64 base, u64 size) | ||
506 | { | ||
507 | return memblock_overlaps_region(&memblock.reserved, base, size); | ||
508 | } | ||
509 | |||
510 | /* | ||
511 | * Given a <base, len>, find which memory regions belong to this range. | ||
512 | * Adjust the request and return a contiguous chunk. | ||
513 | */ | ||
514 | int memblock_find(struct memblock_property *res) | ||
515 | { | ||
516 | int i; | ||
517 | u64 rstart, rend; | ||
518 | |||
519 | rstart = res->base; | ||
520 | rend = rstart + res->size - 1; | ||
521 | |||
522 | for (i = 0; i < memblock.memory.cnt; i++) { | ||
523 | u64 start = memblock.memory.region[i].base; | ||
524 | u64 end = start + memblock.memory.region[i].size - 1; | ||
525 | |||
526 | if (start > rend) | ||
527 | return -1; | ||
528 | |||
529 | if ((end >= rstart) && (start < rend)) { | ||
530 | /* adjust the request */ | ||
531 | if (rstart < start) | ||
532 | rstart = start; | ||
533 | if (rend > end) | ||
534 | rend = end; | ||
535 | res->base = rstart; | ||
536 | res->size = rend - rstart + 1; | ||
537 | return 0; | ||
538 | } | ||
539 | } | ||
540 | return -1; | ||
541 | } | ||
diff --git a/mm/page-writeback.c b/mm/page-writeback.c index 54f28bd493d3..37498ef61548 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c | |||
@@ -495,7 +495,6 @@ static void balance_dirty_pages(struct address_space *mapping, | |||
495 | 495 | ||
496 | for (;;) { | 496 | for (;;) { |
497 | struct writeback_control wbc = { | 497 | struct writeback_control wbc = { |
498 | .bdi = bdi, | ||
499 | .sync_mode = WB_SYNC_NONE, | 498 | .sync_mode = WB_SYNC_NONE, |
500 | .older_than_this = NULL, | 499 | .older_than_this = NULL, |
501 | .nr_to_write = write_chunk, | 500 | .nr_to_write = write_chunk, |
@@ -537,7 +536,7 @@ static void balance_dirty_pages(struct address_space *mapping, | |||
537 | * up. | 536 | * up. |
538 | */ | 537 | */ |
539 | if (bdi_nr_reclaimable > bdi_thresh) { | 538 | if (bdi_nr_reclaimable > bdi_thresh) { |
540 | writeback_inodes_wbc(&wbc); | 539 | writeback_inodes_wb(&bdi->wb, &wbc); |
541 | pages_written += write_chunk - wbc.nr_to_write; | 540 | pages_written += write_chunk - wbc.nr_to_write; |
542 | get_dirty_limits(&background_thresh, &dirty_thresh, | 541 | get_dirty_limits(&background_thresh, &dirty_thresh, |
543 | &bdi_thresh, bdi); | 542 | &bdi_thresh, bdi); |
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 431214b941ac..9bd339eb04c6 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
@@ -3634,6 +3634,9 @@ void * __init __alloc_memory_core_early(int nid, u64 size, u64 align, | |||
3634 | int i; | 3634 | int i; |
3635 | void *ptr; | 3635 | void *ptr; |
3636 | 3636 | ||
3637 | if (limit > get_max_mapped()) | ||
3638 | limit = get_max_mapped(); | ||
3639 | |||
3637 | /* need to go over early_node_map to find out good range for node */ | 3640 | /* need to go over early_node_map to find out good range for node */ |
3638 | for_each_active_range_index_in_nid(i, nid) { | 3641 | for_each_active_range_index_in_nid(i, nid) { |
3639 | u64 addr; | 3642 | u64 addr; |
@@ -3659,6 +3662,11 @@ void * __init __alloc_memory_core_early(int nid, u64 size, u64 align, | |||
3659 | ptr = phys_to_virt(addr); | 3662 | ptr = phys_to_virt(addr); |
3660 | memset(ptr, 0, size); | 3663 | memset(ptr, 0, size); |
3661 | reserve_early_without_check(addr, addr + size, "BOOTMEM"); | 3664 | reserve_early_without_check(addr, addr + size, "BOOTMEM"); |
3665 | /* | ||
3666 | * The min_count is set to 0 so that bootmem allocated blocks | ||
3667 | * are never reported as leaks. | ||
3668 | */ | ||
3669 | kmemleak_alloc(ptr, size, 0, 0); | ||
3662 | return ptr; | 3670 | return ptr; |
3663 | } | 3671 | } |
3664 | 3672 | ||
diff --git a/mm/page_cgroup.c b/mm/page_cgroup.c index 6c0081441a32..5bffada7cde1 100644 --- a/mm/page_cgroup.c +++ b/mm/page_cgroup.c | |||
@@ -9,6 +9,7 @@ | |||
9 | #include <linux/vmalloc.h> | 9 | #include <linux/vmalloc.h> |
10 | #include <linux/cgroup.h> | 10 | #include <linux/cgroup.h> |
11 | #include <linux/swapops.h> | 11 | #include <linux/swapops.h> |
12 | #include <linux/kmemleak.h> | ||
12 | 13 | ||
13 | static void __meminit | 14 | static void __meminit |
14 | __init_page_cgroup(struct page_cgroup *pc, unsigned long pfn) | 15 | __init_page_cgroup(struct page_cgroup *pc, unsigned long pfn) |
@@ -126,6 +127,12 @@ static int __init_refok init_section_page_cgroup(unsigned long pfn) | |||
126 | if (!base) | 127 | if (!base) |
127 | base = vmalloc(table_size); | 128 | base = vmalloc(table_size); |
128 | } | 129 | } |
130 | /* | ||
131 | * The value stored in section->page_cgroup is (base - pfn) | ||
132 | * and it does not point to the memory block allocated above, | ||
133 | * causing kmemleak false positives. | ||
134 | */ | ||
135 | kmemleak_not_leak(base); | ||
129 | } else { | 136 | } else { |
130 | /* | 137 | /* |
131 | * We don't have to allocate page_cgroup again, but | 138 | * We don't have to allocate page_cgroup again, but |
diff --git a/mm/vmscan.c b/mm/vmscan.c index 9c7e57cc63a3..b94fe1b3da43 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c | |||
@@ -213,8 +213,9 @@ unsigned long shrink_slab(unsigned long scanned, gfp_t gfp_mask, | |||
213 | list_for_each_entry(shrinker, &shrinker_list, list) { | 213 | list_for_each_entry(shrinker, &shrinker_list, list) { |
214 | unsigned long long delta; | 214 | unsigned long long delta; |
215 | unsigned long total_scan; | 215 | unsigned long total_scan; |
216 | unsigned long max_pass = (*shrinker->shrink)(0, gfp_mask); | 216 | unsigned long max_pass; |
217 | 217 | ||
218 | max_pass = (*shrinker->shrink)(shrinker, 0, gfp_mask); | ||
218 | delta = (4 * scanned) / shrinker->seeks; | 219 | delta = (4 * scanned) / shrinker->seeks; |
219 | delta *= max_pass; | 220 | delta *= max_pass; |
220 | do_div(delta, lru_pages + 1); | 221 | do_div(delta, lru_pages + 1); |
@@ -242,8 +243,9 @@ unsigned long shrink_slab(unsigned long scanned, gfp_t gfp_mask, | |||
242 | int shrink_ret; | 243 | int shrink_ret; |
243 | int nr_before; | 244 | int nr_before; |
244 | 245 | ||
245 | nr_before = (*shrinker->shrink)(0, gfp_mask); | 246 | nr_before = (*shrinker->shrink)(shrinker, 0, gfp_mask); |
246 | shrink_ret = (*shrinker->shrink)(this_scan, gfp_mask); | 247 | shrink_ret = (*shrinker->shrink)(shrinker, this_scan, |
248 | gfp_mask); | ||
247 | if (shrink_ret == -1) | 249 | if (shrink_ret == -1) |
248 | break; | 250 | break; |
249 | if (shrink_ret < nr_before) | 251 | if (shrink_ret < nr_before) |
@@ -296,7 +298,7 @@ static int may_write_to_queue(struct backing_dev_info *bdi) | |||
296 | static void handle_write_error(struct address_space *mapping, | 298 | static void handle_write_error(struct address_space *mapping, |
297 | struct page *page, int error) | 299 | struct page *page, int error) |
298 | { | 300 | { |
299 | lock_page(page); | 301 | lock_page_nosync(page); |
300 | if (page_mapping(page) == mapping) | 302 | if (page_mapping(page) == mapping) |
301 | mapping_set_error(mapping, error); | 303 | mapping_set_error(mapping, error); |
302 | unlock_page(page); | 304 | unlock_page(page); |