diff options
| -rw-r--r-- | include/linux/mm.h | 2 | ||||
| -rw-r--r-- | mm/swap.c | 32 |
2 files changed, 23 insertions, 11 deletions
diff --git a/include/linux/mm.h b/include/linux/mm.h index 85854b867463..75e9f0724997 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h | |||
| @@ -303,7 +303,7 @@ struct page { | |||
| 303 | */ | 303 | */ |
| 304 | #define put_page_testzero(p) \ | 304 | #define put_page_testzero(p) \ |
| 305 | ({ \ | 305 | ({ \ |
| 306 | BUG_ON(page_count(p) == 0); \ | 306 | BUG_ON(atomic_read(&(p)->_count) == -1);\ |
| 307 | atomic_add_negative(-1, &(p)->_count); \ | 307 | atomic_add_negative(-1, &(p)->_count); \ |
| 308 | }) | 308 | }) |
| 309 | 309 | ||
| @@ -34,19 +34,22 @@ | |||
| 34 | /* How many pages do we try to swap or page in/out together? */ | 34 | /* How many pages do we try to swap or page in/out together? */ |
| 35 | int page_cluster; | 35 | int page_cluster; |
| 36 | 36 | ||
| 37 | void put_page(struct page *page) | 37 | static void put_compound_page(struct page *page) |
| 38 | { | 38 | { |
| 39 | if (unlikely(PageCompound(page))) { | 39 | page = (struct page *)page_private(page); |
| 40 | page = (struct page *)page_private(page); | 40 | if (put_page_testzero(page)) { |
| 41 | if (put_page_testzero(page)) { | 41 | void (*dtor)(struct page *page); |
| 42 | void (*dtor)(struct page *page); | ||
| 43 | 42 | ||
| 44 | dtor = (void (*)(struct page *))page[1].mapping; | 43 | dtor = (void (*)(struct page *))page[1].mapping; |
| 45 | (*dtor)(page); | 44 | (*dtor)(page); |
| 46 | } | ||
| 47 | return; | ||
| 48 | } | 45 | } |
| 49 | if (put_page_testzero(page)) | 46 | } |
| 47 | |||
| 48 | void put_page(struct page *page) | ||
| 49 | { | ||
| 50 | if (unlikely(PageCompound(page))) | ||
| 51 | put_compound_page(page); | ||
| 52 | else if (put_page_testzero(page)) | ||
| 50 | __page_cache_release(page); | 53 | __page_cache_release(page); |
| 51 | } | 54 | } |
| 52 | EXPORT_SYMBOL(put_page); | 55 | EXPORT_SYMBOL(put_page); |
| @@ -244,6 +247,15 @@ void release_pages(struct page **pages, int nr, int cold) | |||
| 244 | struct page *page = pages[i]; | 247 | struct page *page = pages[i]; |
| 245 | struct zone *pagezone; | 248 | struct zone *pagezone; |
| 246 | 249 | ||
| 250 | if (unlikely(PageCompound(page))) { | ||
| 251 | if (zone) { | ||
| 252 | spin_unlock_irq(&zone->lru_lock); | ||
| 253 | zone = NULL; | ||
| 254 | } | ||
| 255 | put_compound_page(page); | ||
| 256 | continue; | ||
| 257 | } | ||
| 258 | |||
| 247 | if (!put_page_testzero(page)) | 259 | if (!put_page_testzero(page)) |
| 248 | continue; | 260 | continue; |
| 249 | 261 | ||
