diff options
Diffstat (limited to 'mm/swap.c')
-rw-r--r-- | mm/swap.c | 66 |
1 files changed, 34 insertions, 32 deletions
@@ -209,19 +209,18 @@ int lru_add_drain_all(void) | |||
209 | */ | 209 | */ |
210 | void fastcall __page_cache_release(struct page *page) | 210 | void fastcall __page_cache_release(struct page *page) |
211 | { | 211 | { |
212 | unsigned long flags; | 212 | if (PageLRU(page)) { |
213 | struct zone *zone = page_zone(page); | 213 | unsigned long flags; |
214 | struct zone *zone = page_zone(page); | ||
214 | 215 | ||
215 | spin_lock_irqsave(&zone->lru_lock, flags); | 216 | spin_lock_irqsave(&zone->lru_lock, flags); |
216 | if (TestClearPageLRU(page)) | 217 | BUG_ON(!PageLRU(page)); |
218 | __ClearPageLRU(page); | ||
217 | del_page_from_lru(zone, page); | 219 | del_page_from_lru(zone, page); |
218 | if (page_count(page) != 0) | 220 | spin_unlock_irqrestore(&zone->lru_lock, flags); |
219 | page = NULL; | 221 | } |
220 | spin_unlock_irqrestore(&zone->lru_lock, flags); | 222 | free_hot_page(page); |
221 | if (page) | ||
222 | free_hot_page(page); | ||
223 | } | 223 | } |
224 | |||
225 | EXPORT_SYMBOL(__page_cache_release); | 224 | EXPORT_SYMBOL(__page_cache_release); |
226 | 225 | ||
227 | /* | 226 | /* |
@@ -245,7 +244,6 @@ void release_pages(struct page **pages, int nr, int cold) | |||
245 | pagevec_init(&pages_to_free, cold); | 244 | pagevec_init(&pages_to_free, cold); |
246 | for (i = 0; i < nr; i++) { | 245 | for (i = 0; i < nr; i++) { |
247 | struct page *page = pages[i]; | 246 | struct page *page = pages[i]; |
248 | struct zone *pagezone; | ||
249 | 247 | ||
250 | if (unlikely(PageCompound(page))) { | 248 | if (unlikely(PageCompound(page))) { |
251 | if (zone) { | 249 | if (zone) { |
@@ -259,23 +257,27 @@ void release_pages(struct page **pages, int nr, int cold) | |||
259 | if (!put_page_testzero(page)) | 257 | if (!put_page_testzero(page)) |
260 | continue; | 258 | continue; |
261 | 259 | ||
262 | pagezone = page_zone(page); | 260 | if (PageLRU(page)) { |
263 | if (pagezone != zone) { | 261 | struct zone *pagezone = page_zone(page); |
264 | if (zone) | 262 | if (pagezone != zone) { |
265 | spin_unlock_irq(&zone->lru_lock); | 263 | if (zone) |
266 | zone = pagezone; | 264 | spin_unlock_irq(&zone->lru_lock); |
267 | spin_lock_irq(&zone->lru_lock); | 265 | zone = pagezone; |
268 | } | 266 | spin_lock_irq(&zone->lru_lock); |
269 | if (TestClearPageLRU(page)) | 267 | } |
268 | BUG_ON(!PageLRU(page)); | ||
269 | __ClearPageLRU(page); | ||
270 | del_page_from_lru(zone, page); | 270 | del_page_from_lru(zone, page); |
271 | if (page_count(page) == 0) { | 271 | } |
272 | if (!pagevec_add(&pages_to_free, page)) { | 272 | |
273 | if (!pagevec_add(&pages_to_free, page)) { | ||
274 | if (zone) { | ||
273 | spin_unlock_irq(&zone->lru_lock); | 275 | spin_unlock_irq(&zone->lru_lock); |
274 | __pagevec_free(&pages_to_free); | 276 | zone = NULL; |
275 | pagevec_reinit(&pages_to_free); | ||
276 | zone = NULL; /* No lock is held */ | ||
277 | } | 277 | } |
278 | } | 278 | __pagevec_free(&pages_to_free); |
279 | pagevec_reinit(&pages_to_free); | ||
280 | } | ||
279 | } | 281 | } |
280 | if (zone) | 282 | if (zone) |
281 | spin_unlock_irq(&zone->lru_lock); | 283 | spin_unlock_irq(&zone->lru_lock); |
@@ -343,8 +345,8 @@ void __pagevec_lru_add(struct pagevec *pvec) | |||
343 | zone = pagezone; | 345 | zone = pagezone; |
344 | spin_lock_irq(&zone->lru_lock); | 346 | spin_lock_irq(&zone->lru_lock); |
345 | } | 347 | } |
346 | if (TestSetPageLRU(page)) | 348 | BUG_ON(PageLRU(page)); |
347 | BUG(); | 349 | SetPageLRU(page); |
348 | add_page_to_inactive_list(zone, page); | 350 | add_page_to_inactive_list(zone, page); |
349 | } | 351 | } |
350 | if (zone) | 352 | if (zone) |
@@ -370,10 +372,10 @@ void __pagevec_lru_add_active(struct pagevec *pvec) | |||
370 | zone = pagezone; | 372 | zone = pagezone; |
371 | spin_lock_irq(&zone->lru_lock); | 373 | spin_lock_irq(&zone->lru_lock); |
372 | } | 374 | } |
373 | if (TestSetPageLRU(page)) | 375 | BUG_ON(PageLRU(page)); |
374 | BUG(); | 376 | SetPageLRU(page); |
375 | if (TestSetPageActive(page)) | 377 | BUG_ON(PageActive(page)); |
376 | BUG(); | 378 | SetPageActive(page); |
377 | add_page_to_active_list(zone, page); | 379 | add_page_to_active_list(zone, page); |
378 | } | 380 | } |
379 | if (zone) | 381 | if (zone) |
@@ -510,7 +512,7 @@ long percpu_counter_sum(struct percpu_counter *fbc) | |||
510 | 512 | ||
511 | spin_lock(&fbc->lock); | 513 | spin_lock(&fbc->lock); |
512 | ret = fbc->count; | 514 | ret = fbc->count; |
513 | for_each_cpu(cpu) { | 515 | for_each_possible_cpu(cpu) { |
514 | long *pcount = per_cpu_ptr(fbc->counters, cpu); | 516 | long *pcount = per_cpu_ptr(fbc->counters, cpu); |
515 | ret += *pcount; | 517 | ret += *pcount; |
516 | } | 518 | } |