X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=mm%2Fswap.c;h=b524ea90bddb93554b7ace67af24af59fc657d17;hb=987b0145d94eecf292d8b301228356f44611ab7c;hp=88895c249bc901f576760a633f993c75bfcd5cf7;hpb=f7ed79d23a47594e7834d66a8f14449796d4f3e6;p=linux-2.6.git diff --git a/mm/swap.c b/mm/swap.c index 88895c249..b524ea90b 100644 --- a/mm/swap.c +++ b/mm/swap.c @@ -209,18 +209,19 @@ int lru_add_drain_all(void) */ void fastcall __page_cache_release(struct page *page) { - if (PageLRU(page)) { - unsigned long flags; - struct zone *zone = page_zone(page); + unsigned long flags; + struct zone *zone = page_zone(page); - spin_lock_irqsave(&zone->lru_lock, flags); - BUG_ON(!PageLRU(page)); - __ClearPageLRU(page); + spin_lock_irqsave(&zone->lru_lock, flags); + if (TestClearPageLRU(page)) del_page_from_lru(zone, page); - spin_unlock_irqrestore(&zone->lru_lock, flags); - } - free_hot_page(page); + if (page_count(page) != 0) + page = NULL; + spin_unlock_irqrestore(&zone->lru_lock, flags); + if (page) + free_hot_page(page); } + EXPORT_SYMBOL(__page_cache_release); /* @@ -244,6 +245,7 @@ void release_pages(struct page **pages, int nr, int cold) pagevec_init(&pages_to_free, cold); for (i = 0; i < nr; i++) { struct page *page = pages[i]; + struct zone *pagezone; if (unlikely(PageCompound(page))) { if (zone) { @@ -257,27 +259,23 @@ void release_pages(struct page **pages, int nr, int cold) if (!put_page_testzero(page)) continue; - if (PageLRU(page)) { - struct zone *pagezone = page_zone(page); - if (pagezone != zone) { - if (zone) - spin_unlock_irq(&zone->lru_lock); - zone = pagezone; - spin_lock_irq(&zone->lru_lock); - } - BUG_ON(!PageLRU(page)); - __ClearPageLRU(page); - del_page_from_lru(zone, page); + pagezone = page_zone(page); + if (pagezone != zone) { + if (zone) + spin_unlock_irq(&zone->lru_lock); + zone = pagezone; + spin_lock_irq(&zone->lru_lock); } - - if (!pagevec_add(&pages_to_free, page)) { - if (zone) { + if (TestClearPageLRU(page)) + del_page_from_lru(zone, page); + if (page_count(page) == 0) { + if (!pagevec_add(&pages_to_free, page)) { spin_unlock_irq(&zone->lru_lock); - zone = NULL; + __pagevec_free(&pages_to_free); + pagevec_reinit(&pages_to_free); + zone = NULL; /* No lock is held */ } - __pagevec_free(&pages_to_free); - pagevec_reinit(&pages_to_free); - } + } } if (zone) spin_unlock_irq(&zone->lru_lock); @@ -345,8 +343,8 @@ void __pagevec_lru_add(struct pagevec *pvec) zone = pagezone; spin_lock_irq(&zone->lru_lock); } - BUG_ON(PageLRU(page)); - SetPageLRU(page); + if (TestSetPageLRU(page)) + BUG(); add_page_to_inactive_list(zone, page); } if (zone) @@ -372,10 +370,10 @@ void __pagevec_lru_add_active(struct pagevec *pvec) zone = pagezone; spin_lock_irq(&zone->lru_lock); } - BUG_ON(PageLRU(page)); - SetPageLRU(page); - BUG_ON(PageActive(page)); - SetPageActive(page); + if (TestSetPageLRU(page)) + BUG(); + if (TestSetPageActive(page)) + BUG(); add_page_to_active_list(zone, page); } if (zone) @@ -512,7 +510,7 @@ long percpu_counter_sum(struct percpu_counter *fbc) spin_lock(&fbc->lock); ret = fbc->count; - for_each_possible_cpu(cpu) { + for_each_cpu(cpu) { long *pcount = per_cpu_ptr(fbc->counters, cpu); ret += *pcount; }