lkml.org 
[lkml]   [1997]   [Jun]   [26]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
SubjectPage cache and swapping
Hi all!
I have seen many times postings about page cache behavior under linux 2.0.x.
Some weeks ago I tried to run linux+Xfree86-2.11+netscape 2.0 on 8 MB machine.
It was almost unusable. Over 4 MB of memory was frozen in page cache, the
machine swapped like a hell and after moving the mouse I had to wait for the
moving of the cursor. I created this small patch, which modifies the memory
freeing policy. It is against 2.0.30, but should work with pre-2.0.31 too.
After applying it the performance was much better, but the page cache became
very small (40-200 KB) while running programs mentioned above.
WARNING: It is not to be blindly applied! I'm not sure, if it does not
introduce deadlocks in other parts of the kernel, so please share your
wisdom with me.
Looking at shrink_mmap in mm/filemap.c I found, that shared pages (page->count
> 1) are inviolable. Additionally, the referenced bit is set, so next time
the page is not freed again, even if it was _not_ used. In other parts of the
kernel I found that page->count is increased on purpose to lock the page
in memory. On the other hand, page->count is for page cache pages (with no buffers
attached to it) the number of processes "seeing" the page. So, I supposed that
removing a shared, but unused page from page cache should not be disasterous.
The patch allows removing shared pages from page cache and removes setting
of the referenced bit for all shared pages.
Krzysztof Strasburger

--- linux-orig/mm/filemap.c Wed Sep 11 14:57:19 1996
+++ linux/mm/filemap.c Tue Jun 24 09:25:16 1997
@@ -160,38 +160,41 @@
} while (tmp != bh);
}

+ /* If it has been referenced recently, don't free it */
+ if (clear_bit(PG_referenced, &page->flags))
+ goto next;
+
+ /* Original note: */
/* We can't throw away shared pages, but we do mark
them as referenced. This relies on the fact that
no page is currently in both the page cache and the
buffer cache; we'd have to modify the following
test to allow for that case. */

- switch (page->count) {
- case 1:
- /* If it has been referenced recently, don't free it */
- if (clear_bit(PG_referenced, &page->flags))
- break;
-
- /* is it a page cache page? */
- if (page->inode) {
- remove_page_from_hash_queue(page);
- remove_page_from_inode_queue(page);
- __free_page(page);
- return 1;
- }
+ /* Why shared pages can't be freed? This modification
+ (sorry for the programming style) allows freeing shared
+ page cache pages. Shared buffers are treated as previously,
+ but they are not marked as referenced. Ah, try_to_free_buffer
+ is called with priority passed to current function, not 6
+ in any case.
+ KS */

- /* is it a buffer cache page? */
- if (bh && try_to_free_buffer(bh, &bh, 6))
+ /* is it a buffer cache page? */
+ if (bh) {
+ if (page->count == 1) {
+ if (try_to_free_buffer(bh, &bh, priority))
return 1;
- break;
-
- default:
- /* more than one users: we can't throw it away */
- set_bit(PG_referenced, &page->flags);
- /* fall through */
- case 0:
- /* nothing */
+ }
+ goto next;
+ }
+ /* is it a page cache page? */
+ if (page->inode) {
+ remove_page_from_hash_queue(page);
+ remove_page_from_inode_queue(page);
+ __free_page(page);
+ return 1;
}
+
next:
page++;
clock++;
\
 
 \ /
  Last update: 2005-03-22 13:39    [W:0.040 / U:0.232 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site