diff options
Diffstat (limited to 'mm/swap.c')
-rw-r--r-- | mm/swap.c | 52 |
1 files changed, 27 insertions, 25 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 | if (!TestClearPageLRU(page)) |
218 | BUG(); | ||
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 | if (!TestClearPageLRU(page)) | ||
269 | BUG(); | ||
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); |