[patch] vmfixes-2.4.0-test9-B2

Ingo Molnar
2000-09-24T19:34:43Z

[-- Attachment #1: Type: TEXT/PLAIN, Size: 1616 bytes --]

the attached vmfixes-B2 patch adds the following fixes/cleanups:

vmscan.c:

- check for __GFP_WAIT not __GFP_IO when yielding the CPU. This fixes
GFP_BUFFER deadlocks. In fact since no caller to do_try_to_free_pages()
can expect that function to not block, we dont test for __GFP_WAIT
either. [GFP_KSWAPD is the only caller without __GFP_WAIT set.]

- do shrink_[d|i]cache_memory() even if !__GFP_IO. This improves balance.

- push the __GFP_IO test into shm_swap().

- after shm_swap() do not test for !count but for <= 0, because count
could be negative if in the future the shrink_ functions return bigger
than 1, and we could then get into an infinite loop. Same after
swap_out() and refill_inactive_scan(). No performance penalty, test
for zero is exchanged with test for sign.

- kmem_cache_reap() is done within refill_inactive(), so it's
unnecessery to call it at the beginning of do_try_to_free_pages().
Moved to the else branch. (i saw kmem_cache_reap() show up in profiles)

- (small codestyle cleanup.)

page_alloc.c:

- in __alloc_pages(), the infinite allocation loop yields the CPU if
necessery. This prevents a potential lockup on UP, and even on SMP it
can prevent livelocks. (i saw this happen.)

mm.h:

- made the GFP_ flag definitions easier to parse for humans :-)

- remove shrink_mmap() prototype, it doesnt exist anymore.

shm.c:

- the trivial test for __GFP_IO.

swap_state.c, filemap.c:

- (shrink_mmap doesnt exist anymore, it's refill_inactive.)

(The patch applies and compiles cleanly, and is tested under various VM
loads i use.)

Ingo

[-- Attachment #2: Type: TEXT/PLAIN, Size: 7375 bytes --]

--- linux/mm/vmscan.c.orig Sun Sep 24 11:41:38 2000
+++ linux/mm/vmscan.c Sun Sep 24 12:20:27 2000
@@ -119,7 +119,7 @@
* our scan.
*
* Basically, this just makes it possible for us to do
- * some real work in the future in "shrink_mmap()".
+ * some real work in the future in "refill_inactive()".
*/
if (!pte_dirty(pte)) {
flush_cache_page(vma, address);
@@ -159,7 +159,7 @@
* NOTE NOTE NOTE! This should just set a
* dirty bit in 'page', and just drop the
* pte. All the hard work would be done by
- * shrink_mmap().
+ * refill_inactive().
*
* That would get rid of a lot of problems.
*/
@@ -891,7 +891,7 @@
do {
made_progress = 0;

- if (current->need_resched && (gfp_mask & __GFP_IO)) {
+ if (current->need_resched) {
__set_current_state(TASK_RUNNING);
schedule();
}
@@ -899,34 +899,32 @@
while (refill_inactive_scan(priority, 1) ||
swap_out(priority, gfp_mask, idle_time)) {
made_progress = 1;
- if (!--count)
+ if (--count <= 0)
goto done;
}

- /* Try to get rid of some shared memory pages.. */
- if (gfp_mask & __GFP_IO) {
- /*
- * don't be too light against the d/i cache since
- * shrink_mmap() almost never fail when there's
- * really plenty of memory free.
- */
- count -= shrink_dcache_memory(priority, gfp_mask);
- count -= shrink_icache_memory(priority, gfp_mask);
- /*
- * Not currently working, see fixme in shrink_?cache_memory
- * In the inner funtions there is a comment:
- * "To help debugging, a zero exit status indicates
- * all slabs were released." (-arca?)
- * lets handle it in a primitive but working way...
- * if (count <= 0)
- * goto done;
- */
+ /*
+ * don't be too light against the d/i cache since
+ * refill_inactive() almost never fail when there's
+ * really plenty of memory free.
+ */
+ count -= shrink_dcache_memory(priority, gfp_mask);
+ count -= shrink_icache_memory(priority, gfp_mask);
+ /*
+ * Not currently working, see fixme in shrink_?cache_memory
+ * In the inner funtions there is a comment:
+ * "To help debugging, a zero exit status indicates
+ * all slabs were released." (-arca?)
+ * lets handle it in a primitive but working way...
+ * if (count <= 0)
+ * goto done;
+ */

- while (shm_swap(priority, gfp_mask)) {
- made_progress = 1;
- if (!--count)
- goto done;
- }
+ /* Try to get rid of some shared memory pages.. */
+ while (shm_swap(priority, gfp_mask)) {
+ made_progress = 1;
+ if (--count <= 0)
+ goto done;
}

/*
@@ -934,7 +932,7 @@
*/
while (swap_out(priority, gfp_mask, 0)) {
made_progress = 1;
- if (!--count)
+ if (--count <= 0)
goto done;
}

@@ -955,9 +953,9 @@
priority--;
} while (priority >= 0);

- /* Always end on a shrink_mmap.., may sleep... */
+ /* Always end on a refill_inactive.., may sleep... */
while (refill_inactive_scan(0, 1)) {
- if (!--count)
+ if (--count <= 0)
goto done;
}

@@ -970,11 +968,6 @@
int ret = 0;

/*
- * First, reclaim unused slab cache memory.
- */
- kmem_cache_reap(gfp_mask);
-
- /*
* If we're low on free pages, move pages from the
* inactive_dirty list to the inactive_clean list.
*
@@ -992,13 +985,14 @@
* the inode and dentry cache whenever we do this.
*/
if (free_shortage() || inactive_shortage()) {
- if (gfp_mask & __GFP_IO) {
- ret += shrink_dcache_memory(6, gfp_mask);
- ret += shrink_icache_memory(6, gfp_mask);
- }
-
+ ret += shrink_dcache_memory(6, gfp_mask);
+ ret += shrink_icache_memory(6, gfp_mask);
ret += refill_inactive(gfp_mask, user);
} else {
+ /*
+ * Reclaim unused slab cache memory.
+ */
+ kmem_cache_reap(gfp_mask);
ret = 1;
}

@@ -1153,9 +1147,8 @@
{
int ret = 1;

- if (gfp_mask & __GFP_WAIT) {
+ if (gfp_mask & __GFP_WAIT)
ret = do_try_to_free_pages(gfp_mask, 1);
- }

return ret;
}
--- linux/mm/page_alloc.c.orig Sun Sep 24 11:44:59 2000
+++ linux/mm/page_alloc.c Sun Sep 24 11:52:00 2000
@@ -444,6 +444,13 @@
* processes, etc).
*/
if (gfp_mask & __GFP_WAIT) {
+ /*
+ * Give other processes a chance to run:
+ */
+ if (current->need_resched) {
+ __set_current_state(TASK_RUNNING);
+ schedule();
+ }
try_to_free_pages(gfp_mask);
memory_pressure++;
goto try_again;
--- linux/mm/filemap.c.orig Sun Sep 24 12:20:35 2000
+++ linux/mm/filemap.c Sun Sep 24 12:20:48 2000
@@ -1925,10 +1925,10 @@
* Application no longer needs these pages. If the pages are dirty,
* it's OK to just throw them away. The app will be more careful about
* data it wants to keep. Be sure to free swap resources too. The
- * zap_page_range call sets things up for shrink_mmap to actually free
+ * zap_page_range call sets things up for refill_inactive to actually free
* these pages later if no one else has touched them in the meantime,
* although we could add these pages to a global reuse list for
- * shrink_mmap to pick up before reclaiming other pages.
+ * refill_inactive to pick up before reclaiming other pages.
*
* NB: This interface discards data rather than pushes it out to swap,
* as some implementations do. This has performance implications for
--- linux/mm/swap_state.c.orig Sun Sep 24 12:21:02 2000
+++ linux/mm/swap_state.c Sun Sep 24 12:21:13 2000
@@ -166,7 +166,7 @@
return 0;
/*
* Though the "found" page was in the swap cache an instant
- * earlier, it might have been removed by shrink_mmap etc.
+ * earlier, it might have been removed by refill_inactive etc.
* Re search ... Since find_lock_page grabs a reference on
* the page, it can not be reused for anything else, namely
* it can not be associated with another swaphandle, so it
--- linux/include/linux/mm.h.orig Sun Sep 24 11:46:37 2000
+++ linux/include/linux/mm.h Sun Sep 24 12:21:54 2000
@@ -441,7 +441,6 @@
/* filemap.c */
extern void remove_inode_page(struct page *);
extern unsigned long page_unuse(struct page *);
-extern int shrink_mmap(int, int);
extern void truncate_inode_pages(struct address_space *, loff_t);

/* generic vm_area_ops exported for stackable file systems */
@@ -469,11 +468,11 @@

#define GFP_BUFFER (__GFP_HIGH | __GFP_WAIT)
#define GFP_ATOMIC (__GFP_HIGH)
-#define GFP_USER (__GFP_WAIT | __GFP_IO)
-#define GFP_HIGHUSER (GFP_USER | __GFP_HIGHMEM)
+#define GFP_USER ( __GFP_WAIT | __GFP_IO)
+#define GFP_HIGHUSER ( __GFP_WAIT | __GFP_IO | __GFP_HIGHMEM)
#define GFP_KERNEL (__GFP_HIGH | __GFP_WAIT | __GFP_IO)
#define GFP_NFS (__GFP_HIGH | __GFP_WAIT | __GFP_IO)
-#define GFP_KSWAPD (__GFP_IO)
+#define GFP_KSWAPD ( __GFP_IO)

/* Flag - indicates that the buffer will be suitable for DMA. Ignored on some
platforms, used as appropriate on others */
--- linux/ipc/shm.c.orig Sun Sep 24 11:45:16 2000
+++ linux/ipc/shm.c Sun Sep 24 11:53:59 2000
@@ -1536,6 +1536,12 @@
int counter;
struct page * page_map;

+ /*
+ * Push this inside:
+ */
+ if (!(gfp_mask & __GFP_IO))
+ return 0;
+
zshm_swap(prio, gfp_mask);
counter = shm_rss >> prio;
if (!counter)