From: Roger Larsson <roger.larsson@norran.net>
To: "linux-kernel@vger.rutgers.edu" <linux-kernel@vger.rutgers.edu>,
"linux-mm@kvack.org" <linux-mm@kvack.org>
Subject: [PATCH--] test5-pre1 vmfix (rev 2.1) + one rescheduling bugfix?
Date: Wed, 19 Jul 2000 04:12:40 +0200 [thread overview]
Message-ID: <39750E98.54A4FBE9@norran.net> (raw)
[-- Attachment #1: Type: text/plain, Size: 1402 bytes --]
Hi,
[Intermediate release - indicator of problem with previous]
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]
* Up to 10% better throughput than 2.4.0-test4, YMMV
* Tested mostly with streaming tests. On a non HIGHMEM config.
+ New: zone_wake_kswapd == 2 indicates a situation where
free_pages < pages_low another alloc is done.
+ New-BUGFIX: runs kswapd while zone_wake_kswapd == 2 or
low_on_memory (Quintela)
+ New-BUGFIX? checks if __GFP_IO before rescheduling
(will become separate patch if correct, thanks Quintela)
- Kills mmap002, did not in the previously released that
should have this problem (but did not) - why? Will
investigate further...
- Since kswapd does not wake up periodic anymore, the
latencies might be worse... Will investigate it
further when other stuff works.
Note: logic of function keep_kswapd_awake has changed.
/RogerL
--
Home page:
http://www.norran.net/nra02596/
[-- Attachment #2: patch-2.4.0-test5-1-vmfix.21 --]
[-- Type: text/plain, Size: 6401 bytes --]
--- linux/mm/vmscan.c.orig Sat Jul 15 23:44:34 2000
+++ linux/mm/vmscan.c Wed Jul 19 03:44:12 2000
@@ -419,7 +419,7 @@ out:
}
/*
- * Check if there is any memory pressure (free_pages < pages_low)
+ * Check if there is any memory pressure (zone_wake_kswapd == 2)
*/
static inline int memory_pressure(void)
{
@@ -430,7 +430,7 @@ static inline int memory_pressure(void)
for(i = 0; i < MAX_NR_ZONES; i++) {
zone_t *zone = pgdat->node_zones+ i;
if (zone->size &&
- zone->free_pages < zone->pages_low)
+ zone->zone_wake_kswapd == 2)
return 1;
}
pgdat = pgdat->node_next;
@@ -440,24 +440,31 @@ static inline int memory_pressure(void)
}
/*
- * Check if there recently has been memory pressure (zone_wake_kswapd)
+ * Check if any zone have recently been critical (low_on_memory)
+ * any zone with current memory pressure (zone_wake_kswapd == 2)
+ * all zones have recently had memory_pressure (zone_wake_kswapd)
*/
static inline int keep_kswapd_awake(void)
{
+ int all_recent = 1;
pg_data_t *pgdat = pgdat_list;
do {
int i;
for(i = 0; i < MAX_NR_ZONES; i++) {
zone_t *zone = pgdat->node_zones+ i;
- if (zone->size &&
- zone->zone_wake_kswapd)
- return 1;
+ if (!zone->size) {
+ if (zone->zone_wake_kswapd == 2 ||
+ zone->low_on_memory)
+ return 1;
+ if (!zone->zone_wake_kswapd)
+ all_recent = 0;
+ }
}
pgdat = pgdat->node_next;
} while (pgdat);
- return 0;
+ return all_recent;
}
/*
@@ -484,7 +491,7 @@ static int do_try_to_free_pages(unsigned
priority = 64;
do {
- if (current->need_resched) {
+ if ((gfp_mask & __GFP_IO) && current->need_resched) {
schedule();
/* time has passed - pressure too? */
if (!memory_pressure())
@@ -496,9 +503,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 +601,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);
@@ -628,24 +630,30 @@ int try_to_free_pages(unsigned int gfp_m
if (gfp_mask & __GFP_WAIT) {
current->state = TASK_RUNNING;
current->flags |= PF_MEMALLOC;
- retval = do_try_to_free_pages(gfp_mask);
+ do {
+ retval = do_try_to_free_pages(gfp_mask);
+ } while (!retval);
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;
}
module_init(kswapd_init)
+
+
+
+
--- linux/mm/page_alloc.c.orig Sat Jul 15 23:44:46 2000
+++ linux/mm/page_alloc.c Wed Jul 19 03:45:36 2000
@@ -141,9 +141,12 @@ void __free_pages_ok (struct page *page,
spin_unlock_irqrestore(&zone->lock, flags);
- if (zone->free_pages > zone->pages_high) {
- zone->zone_wake_kswapd = 0;
- zone->low_on_memory = 0;
+ if (zone->free_pages > zone->pages_low) {
+ zone->zone_wake_kswapd = 1;
+ if (zone->free_pages > zone->pages_high) {
+ zone->zone_wake_kswapd = 0;
+ zone->low_on_memory = 0;
+ }
}
}
@@ -217,7 +220,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 +231,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++);
@@ -256,6 +244,16 @@ struct page * __alloc_pages(zonelist_t *
struct page *page = rmqueue(z, order);
if (z->free_pages < z->pages_low) {
z->zone_wake_kswapd = 1;
+
+ /* Usually zone_wake_kswapd is set to 2
+ * on second alloc below pages_low
+ * but if this was a big one
+ * - do not let it pass unnoticed
+ */
+ if (z->free_pages < z->pages_low - MAX_ORDER) {
+ z->zone_wake_kswapd = 2;
+ }
+
if (waitqueue_active(&kswapd_wait))
wake_up_interruptible(&kswapd_wait);
}
@@ -264,6 +262,21 @@ struct page * __alloc_pages(zonelist_t *
}
}
+ /* 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
* balancing.. See if we have any that aren't critical..
@@ -275,8 +288,17 @@ struct page * __alloc_pages(zonelist_t *
break;
if (!z->low_on_memory) {
struct page *page = rmqueue(z, order);
- if (z->free_pages < z->pages_min)
- z->low_on_memory = 1;
+ if (z->free_pages < z->pages_low) {
+ z->zone_wake_kswapd = 2; /* future: ++ */
+
+ if (z->free_pages < z->pages_min)
+ z->low_on_memory = 1;
+
+ /* make kswapd notice new condition */
+ if (waitqueue_active(&kswapd_wait))
+ wake_up_interruptible(&kswapd_wait);
+ }
+
if (page)
return page;
}
reply other threads:[~2000-07-19 2:12 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=39750E98.54A4FBE9@norran.net \
--to=roger.larsson@norran.net \
--cc=linux-kernel@vger.rutgers.edu \
--cc=linux-mm@kvack.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox