diff options
| -rw-r--r-- | mm/swap.c | 101 |
1 files changed, 47 insertions, 54 deletions
| @@ -178,13 +178,15 @@ void put_pages_list(struct list_head *pages) | |||
| 178 | } | 178 | } |
| 179 | EXPORT_SYMBOL(put_pages_list); | 179 | EXPORT_SYMBOL(put_pages_list); |
| 180 | 180 | ||
| 181 | static void pagevec_lru_move_fn(struct pagevec *pvec, | 181 | /* |
| 182 | void (*move_fn)(struct page *page, void *arg), | 182 | * pagevec_move_tail() must be called with IRQ disabled. |
| 183 | void *arg) | 183 | * Otherwise this may cause nasty races. |
| 184 | */ | ||
| 185 | static void pagevec_move_tail(struct pagevec *pvec) | ||
| 184 | { | 186 | { |
| 185 | int i; | 187 | int i; |
| 188 | int pgmoved = 0; | ||
| 186 | struct zone *zone = NULL; | 189 | struct zone *zone = NULL; |
| 187 | unsigned long flags = 0; | ||
| 188 | 190 | ||
| 189 | for (i = 0; i < pagevec_count(pvec); i++) { | 191 | for (i = 0; i < pagevec_count(pvec); i++) { |
| 190 | struct page *page = pvec->pages[i]; | 192 | struct page *page = pvec->pages[i]; |
| @@ -192,41 +194,21 @@ static void pagevec_lru_move_fn(struct pagevec *pvec, | |||
| 192 | 194 | ||
| 193 | if (pagezone != zone) { | 195 | if (pagezone != zone) { |
| 194 | if (zone) | 196 | if (zone) |
| 195 | spin_unlock_irqrestore(&zone->lru_lock, flags); | 197 | spin_unlock(&zone->lru_lock); |
| 196 | zone = pagezone; | 198 | zone = pagezone; |
| 197 | spin_lock_irqsave(&zone->lru_lock, flags); | 199 | spin_lock(&zone->lru_lock); |
| 200 | } | ||
| 201 | if (PageLRU(page) && !PageActive(page) && !PageUnevictable(page)) { | ||
| 202 | int lru = page_lru_base_type(page); | ||
| 203 | list_move_tail(&page->lru, &zone->lru[lru].list); | ||
| 204 | pgmoved++; | ||
| 198 | } | 205 | } |
| 199 | |||
| 200 | (*move_fn)(page, arg); | ||
| 201 | } | 206 | } |
| 202 | if (zone) | 207 | if (zone) |
| 203 | spin_unlock_irqrestore(&zone->lru_lock, flags); | 208 | spin_unlock(&zone->lru_lock); |
| 204 | release_pages(pvec->pages, pagevec_count(pvec), pvec->cold); | ||
| 205 | pagevec_reinit(pvec); | ||
| 206 | } | ||
| 207 | |||
| 208 | static void pagevec_move_tail_fn(struct page *page, void *arg) | ||
| 209 | { | ||
| 210 | int *pgmoved = arg; | ||
| 211 | struct zone *zone = page_zone(page); | ||
| 212 | |||
| 213 | if (PageLRU(page) && !PageActive(page) && !PageUnevictable(page)) { | ||
| 214 | int lru = page_lru_base_type(page); | ||
| 215 | list_move_tail(&page->lru, &zone->lru[lru].list); | ||
| 216 | (*pgmoved)++; | ||
| 217 | } | ||
| 218 | } | ||
| 219 | |||
| 220 | /* | ||
| 221 | * pagevec_move_tail() must be called with IRQ disabled. | ||
| 222 | * Otherwise this may cause nasty races. | ||
| 223 | */ | ||
| 224 | static void pagevec_move_tail(struct pagevec *pvec) | ||
| 225 | { | ||
| 226 | int pgmoved = 0; | ||
| 227 | |||
| 228 | pagevec_lru_move_fn(pvec, pagevec_move_tail_fn, &pgmoved); | ||
| 229 | __count_vm_events(PGROTATED, pgmoved); | 209 | __count_vm_events(PGROTATED, pgmoved); |
| 210 | release_pages(pvec->pages, pvec->nr, pvec->cold); | ||
| 211 | pagevec_reinit(pvec); | ||
| 230 | } | 212 | } |
| 231 | 213 | ||
| 232 | /* | 214 | /* |
| @@ -234,7 +216,7 @@ static void pagevec_move_tail(struct pagevec *pvec) | |||
| 234 | * reclaim. If it still appears to be reclaimable, move it to the tail of the | 216 | * reclaim. If it still appears to be reclaimable, move it to the tail of the |
| 235 | * inactive list. | 217 | * inactive list. |
| 236 | */ | 218 | */ |
| 237 | void rotate_reclaimable_page(struct page *page) | 219 | void rotate_reclaimable_page(struct page *page) |
| 238 | { | 220 | { |
| 239 | if (!PageLocked(page) && !PageDirty(page) && !PageActive(page) && | 221 | if (!PageLocked(page) && !PageDirty(page) && !PageActive(page) && |
| 240 | !PageUnevictable(page) && PageLRU(page)) { | 222 | !PageUnevictable(page) && PageLRU(page)) { |
| @@ -534,33 +516,44 @@ void lru_add_page_tail(struct zone* zone, | |||
| 534 | } | 516 | } |
| 535 | } | 517 | } |
| 536 | 518 | ||
| 537 | static void ____pagevec_lru_add_fn(struct page *page, void *arg) | ||
| 538 | { | ||
| 539 | enum lru_list lru = (enum lru_list)arg; | ||
| 540 | struct zone *zone = page_zone(page); | ||
| 541 | int file = is_file_lru(lru); | ||
| 542 | int active = is_active_lru(lru); | ||
| 543 | |||
| 544 | VM_BUG_ON(PageActive(page)); | ||
| 545 | VM_BUG_ON(PageUnevictable(page)); | ||
| 546 | VM_BUG_ON(PageLRU(page)); | ||
| 547 | |||
| 548 | SetPageLRU(page); | ||
| 549 | if (active) | ||
| 550 | SetPageActive(page); | ||
| 551 | update_page_reclaim_stat(zone, page, file, active); | ||
| 552 | add_page_to_lru_list(zone, page, lru); | ||
| 553 | } | ||
| 554 | |||
| 555 | /* | 519 | /* |
| 556 | * Add the passed pages to the LRU, then drop the caller's refcount | 520 | * Add the passed pages to the LRU, then drop the caller's refcount |
| 557 | * on them. Reinitialises the caller's pagevec. | 521 | * on them. Reinitialises the caller's pagevec. |
| 558 | */ | 522 | */ |
| 559 | void ____pagevec_lru_add(struct pagevec *pvec, enum lru_list lru) | 523 | void ____pagevec_lru_add(struct pagevec *pvec, enum lru_list lru) |
| 560 | { | 524 | { |
| 525 | int i; | ||
| 526 | struct zone *zone = NULL; | ||
| 527 | |||
| 561 | VM_BUG_ON(is_unevictable_lru(lru)); | 528 | VM_BUG_ON(is_unevictable_lru(lru)); |
| 562 | 529 | ||
| 563 | pagevec_lru_move_fn(pvec, ____pagevec_lru_add_fn, (void *)lru); | 530 | for (i = 0; i < pagevec_count(pvec); i++) { |
| 531 | struct page *page = pvec->pages[i]; | ||
| 532 | struct zone *pagezone = page_zone(page); | ||
| 533 | int file; | ||
| 534 | int active; | ||
| 535 | |||
| 536 | if (pagezone != zone) { | ||
| 537 | if (zone) | ||
| 538 | spin_unlock_irq(&zone->lru_lock); | ||
| 539 | zone = pagezone; | ||
| 540 | spin_lock_irq(&zone->lru_lock); | ||
| 541 | } | ||
| 542 | VM_BUG_ON(PageActive(page)); | ||
| 543 | VM_BUG_ON(PageUnevictable(page)); | ||
| 544 | VM_BUG_ON(PageLRU(page)); | ||
| 545 | SetPageLRU(page); | ||
| 546 | active = is_active_lru(lru); | ||
| 547 | file = is_file_lru(lru); | ||
| 548 | if (active) | ||
| 549 | SetPageActive(page); | ||
| 550 | update_page_reclaim_stat(zone, page, file, active); | ||
| 551 | add_page_to_lru_list(zone, page, lru); | ||
| 552 | } | ||
| 553 | if (zone) | ||
| 554 | spin_unlock_irq(&zone->lru_lock); | ||
| 555 | release_pages(pvec->pages, pvec->nr, pvec->cold); | ||
| 556 | pagevec_reinit(pvec); | ||
| 564 | } | 557 | } |
| 565 | 558 | ||
| 566 | EXPORT_SYMBOL(____pagevec_lru_add); | 559 | EXPORT_SYMBOL(____pagevec_lru_add); |
