lkml.org 
[lkml]   [2000]   [Jul]   [17]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
Subject[PATCH] test5-pre1 vmfix (rev 8)
Hi,

Since I am responsible for messing up some aspects of vm
(when fixing others)
here is a patch that tries to solve the introduced problems.

* no more periodic wake up of kswapd - not needed anymore
* no more freeing all zones to (free_pages > pages_high)
* always wakes kswapd up after try_to_free_pages
* kswapd starts when all zones gets zone_wake_kswapd
(runs once for each zone that hits zone_wake_kswapd)
* removed test for more than pages_high in alloc_pages,
zones will mostly be in the range [pages_high...pages_low]
* I get 10% better throughput than 2.4.0-test4, YMMV

Note: logic of function keep_kswapd_awake has changed.

/RogerL


--
Home page:
http://www.norran.net/nra02596/--- linux/mm/vmscan.c.orig Sat Jul 15 23:44:34 2000
+++ linux/mm/vmscan.c Tue Jul 18 02:08:48 2000
@@ -440,7 +440,7 @@ static inline int memory_pressure(void)
}

/*
- * Check if there recently has been memory pressure (zone_wake_kswapd)
+ * Check if all zones have recently had memory_pressure (zone_wake_kswapd)
*/
static inline int keep_kswapd_awake(void)
{
@@ -451,13 +451,13 @@ static inline int keep_kswapd_awake(void
for(i = 0; i < MAX_NR_ZONES; i++) {
zone_t *zone = pgdat->node_zones+ i;
if (zone->size &&
- zone->zone_wake_kswapd)
- return 1;
+ !zone->zone_wake_kswapd)
+ return 0;
}
pgdat = pgdat->node_next;
} while (pgdat);

- return 0;
+ return 1;
}

/*
@@ -496,9 +496,7 @@ static int do_try_to_free_pages(unsigned
goto done;
}

- /* not (been) low on memory - it is
- * pointless to try to swap out.
- */
+ /* check if mission completed */
if (!keep_kswapd_awake())
goto done;

@@ -596,10 +594,7 @@ int kswapd(void *unused)

for (;;) {
if (!keep_kswapd_awake()) {
- /* wake up regulary to do an early attempt too free
- * pages - pages will not actually be freed.
- */
- interruptible_sleep_on_timeout(&kswapd_wait, HZ);
+ interruptible_sleep_on(&kswapd_wait);
}

do_try_to_free_pages(GFP_KSWAPD);
@@ -631,18 +626,18 @@ int try_to_free_pages(unsigned int gfp_m
retval = do_try_to_free_pages(gfp_mask);
current->flags &= ~PF_MEMALLOC;
}
- else {
- /* make sure kswapd runs */
- if (waitqueue_active(&kswapd_wait))
- wake_up_interruptible(&kswapd_wait);
- }
+
+ /* someone needed memory that kswapd had not provided
+ * make sure kswapd runs, should not happen often */
+ if (waitqueue_active(&kswapd_wait))
+ wake_up_interruptible(&kswapd_wait);

return retval;
}

static int __init kswapd_init(void)
{
- printk("Starting kswapd v1.6\n");
+ printk("Starting kswapd v1.7\n");
swap_setup();
kernel_thread(kswapd, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
return 0;
--- linux/mm/page_alloc.c.orig Sat Jul 15 23:44:46 2000
+++ linux/mm/page_alloc.c Tue Jul 18 02:19:30 2000
@@ -217,7 +217,7 @@ static struct page * rmqueue(zone_t *zon
*/
struct page * __alloc_pages(zonelist_t *zonelist, unsigned long order)
{
- zone_t **zone = zonelist->zones;
+ zone_t **zone;
extern wait_queue_head_t kswapd_wait;

/*
@@ -228,21 +228,6 @@ struct page * __alloc_pages(zonelist_t *
* in a higher zone fails.
*/

- for (;;) {
- zone_t *z = *(zone++);
- if (!z)
- break;
- if (!z->size)
- BUG();
-
- /* If there are zones with a lot of free memory allocate from them */
- if (z->free_pages > z->pages_high) {
- struct page *page = rmqueue(z, order);
- if (page)
- return page;
- }
- }
-
zone = zonelist->zones;
for (;;) {
zone_t *z = *(zone++);
@@ -263,6 +248,21 @@ struct page * __alloc_pages(zonelist_t *
return page;
}
}
+
+ /* Three possibilities to get here
+ * - Previous alloc_pages resulted in last zone set to have
+ * zone_wake_kswapd and start it. kswapd has not been able
+ * to release enough pages so that one zone does not have
+ * zone_wake_kswapd set.
+ * - Different sets of zones (zonelist)
+ * previous did not have all zones with zone_wake_kswapd but
+ * this one has... should kswapd be woken up? it will run once.
+ * - SMP race, kswapd went to sleep slightly after it as running
+ * in 'if (waitqueue_active(...))' above.
+ * + anyway the test is very cheap to do...
+ */
+ if (waitqueue_active(&kswapd_wait))
+ wake_up_interruptible(&kswapd_wait);

/*
* Ok, we don't have any zones that don't need some
\
 
 \ /
  Last update: 2005-03-22 13:57    [W:0.044 / U:0.096 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site