]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - mm/swap.c
mm: deactivate invalidated pages
[mv-sheeva.git] / mm / swap.c
index c02f93611a849e6c79bdbae2e13ee6e4cff6eb37..4aea806d0d441c7d58d4bc8be83103ff743e5289 100644 (file)
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -39,6 +39,7 @@ int page_cluster;
 
 static DEFINE_PER_CPU(struct pagevec[NR_LRU_LISTS], lru_add_pvecs);
 static DEFINE_PER_CPU(struct pagevec, lru_rotate_pvecs);
+static DEFINE_PER_CPU(struct pagevec, lru_deactivate_pvecs);
 
 /*
  * This path almost never happens for VM activity - pages are normally
@@ -346,6 +347,60 @@ void add_page_to_unevictable_list(struct page *page)
        spin_unlock_irq(&zone->lru_lock);
 }
 
+/*
+ * If the page can not be invalidated, it is moved to the
+ * inactive list to speed up its reclaim.  It is moved to the
+ * head of the list, rather than the tail, to give the flusher
+ * threads some time to write it out, as this is much more
+ * effective than the single-page writeout from reclaim.
+ */
+static void lru_deactivate(struct page *page, struct zone *zone)
+{
+       int lru, file;
+
+       if (!PageLRU(page) || !PageActive(page))
+               return;
+
+       /* Some processes are using the page */
+       if (page_mapped(page))
+               return;
+
+       file = page_is_file_cache(page);
+       lru = page_lru_base_type(page);
+       del_page_from_lru_list(zone, page, lru + LRU_ACTIVE);
+       ClearPageActive(page);
+       ClearPageReferenced(page);
+       add_page_to_lru_list(zone, page, lru);
+       __count_vm_event(PGDEACTIVATE);
+
+       update_page_reclaim_stat(zone, page, file, 0);
+}
+
+static void ____pagevec_lru_deactivate(struct pagevec *pvec)
+{
+       int i;
+       struct zone *zone = NULL;
+
+       for (i = 0; i < pagevec_count(pvec); i++) {
+               struct page *page = pvec->pages[i];
+               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);
+               }
+               lru_deactivate(page, zone);
+       }
+       if (zone)
+               spin_unlock_irq(&zone->lru_lock);
+
+       release_pages(pvec->pages, pvec->nr, pvec->cold);
+       pagevec_reinit(pvec);
+}
+
+
 /*
  * Drain pages out of the cpu's pagevecs.
  * Either "cpu" is the current CPU, and preemption has already been
@@ -372,6 +427,29 @@ static void drain_cpu_pagevecs(int cpu)
                pagevec_move_tail(pvec);
                local_irq_restore(flags);
        }
+
+       pvec = &per_cpu(lru_deactivate_pvecs, cpu);
+       if (pagevec_count(pvec))
+               ____pagevec_lru_deactivate(pvec);
+}
+
+/**
+ * deactivate_page - forcefully deactivate a page
+ * @page: page to deactivate
+ *
+ * This function hints the VM that @page is a good reclaim candidate,
+ * for example if its invalidation fails due to the page being dirty
+ * or under writeback.
+ */
+void deactivate_page(struct page *page)
+{
+       if (likely(get_page_unless_zero(page))) {
+               struct pagevec *pvec = &get_cpu_var(lru_deactivate_pvecs);
+
+               if (!pagevec_add(pvec, page))
+                       ____pagevec_lru_deactivate(pvec);
+               put_cpu_var(lru_deactivate_pvecs);
+       }
 }
 
 void lru_add_drain(void)