diff options
author | John Dykstra <jdykstra@cray.com> | 2012-05-25 17:12:46 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2012-05-30 04:57:11 -0400 |
commit | fa83523f45fbb403eba4ebc5704bf98aa4da0163 (patch) | |
tree | 35466e5e2e9e5ed8171ef596d63690ed42621fca /arch/x86/mm | |
parent | 1b38a3a10f2ad96a3c0130f63b7f3610bab7090d (diff) |
x86/mm/pat: Improve scaling of pat_pagerange_is_ram()
Function pat_pagerange_is_ram() scales poorly to large address
ranges, because it probes the resource tree for each page.
On a 2.6 GHz Opteron, this function consumes 34 ms for a 1 GB range.
It is called twice during untrack_pfn_vma(), slowing process
cleanup and handicapping the OOM killer.
This replacement consumes less than 1ms, under the same conditions.
Signed-off-by: John Dykstra <jdykstra@cray.com> on behalf of Cray Inc.
Acked-by: Suresh Siddha <suresh.b.siddha@intel.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1337980366.1979.6.camel@redwood
[ Small stylistic cleanups and renames ]
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'arch/x86/mm')
-rw-r--r-- | arch/x86/mm/pat.c | 56 |
1 files changed, 36 insertions, 20 deletions
diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c index f6ff57b7efa5..bea6e573e02b 100644 --- a/arch/x86/mm/pat.c +++ b/arch/x86/mm/pat.c | |||
@@ -158,31 +158,47 @@ static unsigned long pat_x_mtrr_type(u64 start, u64 end, unsigned long req_type) | |||
158 | return req_type; | 158 | return req_type; |
159 | } | 159 | } |
160 | 160 | ||
161 | struct pagerange_state { | ||
162 | unsigned long cur_pfn; | ||
163 | int ram; | ||
164 | int not_ram; | ||
165 | }; | ||
166 | |||
167 | static int | ||
168 | pagerange_is_ram_callback(unsigned long initial_pfn, unsigned long total_nr_pages, void *arg) | ||
169 | { | ||
170 | struct pagerange_state *state = arg; | ||
171 | |||
172 | state->not_ram |= initial_pfn > state->cur_pfn; | ||
173 | state->ram |= total_nr_pages > 0; | ||
174 | state->cur_pfn = initial_pfn + total_nr_pages; | ||
175 | |||
176 | return state->ram && state->not_ram; | ||
177 | } | ||
178 | |||
161 | static int pat_pagerange_is_ram(resource_size_t start, resource_size_t end) | 179 | static int pat_pagerange_is_ram(resource_size_t start, resource_size_t end) |
162 | { | 180 | { |
163 | int ram_page = 0, not_rampage = 0; | 181 | int ret = 0; |
164 | unsigned long page_nr; | 182 | unsigned long start_pfn = start >> PAGE_SHIFT; |
183 | unsigned long end_pfn = (end + PAGE_SIZE - 1) >> PAGE_SHIFT; | ||
184 | struct pagerange_state state = {start_pfn, 0, 0}; | ||
165 | 185 | ||
166 | for (page_nr = (start >> PAGE_SHIFT); page_nr < (end >> PAGE_SHIFT); | 186 | /* |
167 | ++page_nr) { | 187 | * For legacy reasons, physical address range in the legacy ISA |
168 | /* | 188 | * region is tracked as non-RAM. This will allow users of |
169 | * For legacy reasons, physical address range in the legacy ISA | 189 | * /dev/mem to map portions of legacy ISA region, even when |
170 | * region is tracked as non-RAM. This will allow users of | 190 | * some of those portions are listed(or not even listed) with |
171 | * /dev/mem to map portions of legacy ISA region, even when | 191 | * different e820 types(RAM/reserved/..) |
172 | * some of those portions are listed(or not even listed) with | 192 | */ |
173 | * different e820 types(RAM/reserved/..) | 193 | if (start_pfn < ISA_END_ADDRESS >> PAGE_SHIFT) |
174 | */ | 194 | start_pfn = ISA_END_ADDRESS >> PAGE_SHIFT; |
175 | if (page_nr >= (ISA_END_ADDRESS >> PAGE_SHIFT) && | 195 | |
176 | page_is_ram(page_nr)) | 196 | if (start_pfn < end_pfn) { |
177 | ram_page = 1; | 197 | ret = walk_system_ram_range(start_pfn, end_pfn - start_pfn, |
178 | else | 198 | &state, pagerange_is_ram_callback); |
179 | not_rampage = 1; | ||
180 | |||
181 | if (ram_page == not_rampage) | ||
182 | return -1; | ||
183 | } | 199 | } |
184 | 200 | ||
185 | return ram_page; | 201 | return (ret > 0) ? -1 : (state.ram ? 1 : 0); |
186 | } | 202 | } |
187 | 203 | ||
188 | /* | 204 | /* |