]> err.no Git - linux-2.6/commitdiff
[PATCH] VM: rate limit early reclaim
authorMartin Hicks <mort@sgi.com>
Wed, 22 Jun 2005 00:14:43 +0000 (17:14 -0700)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Wed, 22 Jun 2005 01:46:14 +0000 (18:46 -0700)
When early zone reclaim is turned on the LRU is scanned more frequently when a
zone is low on memory.  This limits when the zone reclaim can be called by
skipping the scan if another thread (either via kswapd or sync reclaim) is
already reclaiming from the zone.

Signed-off-by: Martin Hicks <mort@sgi.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
include/linux/mmzone.h
mm/page_alloc.c
mm/vmscan.c

index dfc2452ccb104d23fb409fba5bc923292a96c3b3..18fed8b679437ad66f475adb8d9d841e561c0b29 100644 (file)
@@ -149,6 +149,8 @@ struct zone {
         * as it fails a watermark_ok() in __alloc_pages?
         */
        int                     reclaim_pages;
+       /* A count of how many reclaimers are scanning this zone */
+       atomic_t                reclaim_in_progress;
 
        /*
         * prev_priority holds the scanning priority for this zone.  It is
index a9da20bc2ed09a754fb69046f32e7e38066507ce..2019c1b19254e4b2085064c911b40b3f962a32bb 100644 (file)
@@ -1738,6 +1738,7 @@ static void __init free_area_init_core(struct pglist_data *pgdat,
                zone->nr_scan_inactive = 0;
                zone->nr_active = 0;
                zone->nr_inactive = 0;
+               atomic_set(&zone->reclaim_in_progress, -1);
                if (!size)
                        continue;
 
index 7da846960d8a7b2b4773758adb6ede0c7d2bc712..24da725a30f0dfabe23452e0a11240319c8c64b1 100644 (file)
@@ -900,7 +900,9 @@ shrink_caches(struct zone **zones, struct scan_control *sc)
                if (zone->all_unreclaimable && sc->priority != DEF_PRIORITY)
                        continue;       /* Let kswapd poll it */
 
+               atomic_inc(&zone->reclaim_in_progress);
                shrink_zone(zone, sc);
+               atomic_dec(&zone->reclaim_in_progress);
        }
 }
  
@@ -1111,7 +1113,9 @@ scan:
                        sc.nr_reclaimed = 0;
                        sc.priority = priority;
                        sc.swap_cluster_max = nr_pages? nr_pages : SWAP_CLUSTER_MAX;
+                       atomic_inc(&zone->reclaim_in_progress);
                        shrink_zone(zone, &sc);
+                       atomic_dec(&zone->reclaim_in_progress);
                        reclaim_state->reclaimed_slab = 0;
                        nr_slab = shrink_slab(sc.nr_scanned, GFP_KERNEL,
                                                lru_pages);
@@ -1354,9 +1358,15 @@ int zone_reclaim(struct zone *zone, unsigned int gfp_mask, unsigned int order)
        else
                sc.swap_cluster_max = SWAP_CLUSTER_MAX;
 
+       /* Don't reclaim the zone if there are other reclaimers active */
+       if (!atomic_inc_and_test(&zone->reclaim_in_progress))
+               goto out;
+
        shrink_zone(zone, &sc);
        total_reclaimed = sc.nr_reclaimed;
 
+ out:
+       atomic_dec(&zone->reclaim_in_progress);
        return total_reclaimed;
 }