Re: memory handling in pre5/pre6

From: Rik van Riel (riel@conectiva.com.br)
Date: Tue Apr 18 2000 - 14:25:06 EST


On Tue, 18 Apr 2000, Andrea Arcangeli wrote:

        [truncate_inode_pages fix]

> You'll lockup. Also you aren't fixing anything. There is no race
> to fix in truncate_inode_pages.

Think about eg. multiple truncates on the same inode...

> This will make your machine sloowww and you also won't be able
> to shrink the cache at a certain point and you'll swapout even
> more at that point. Just try this:
>
> find / -type f -exec cp {} /dev/null \; >/dev/null

I'm running it now (with my latest version of the patch,
which is attached below) and performance of the rest of the
machine is not impacted by the continuous copy...

It puts pages with a "too high" count in the middle of the
LRU queue, referenced pages are put at the end of the queue
and other pages that weren't referenced are either freed or
put at the beginning of the queue, so we'll have a chance of
freeing them next time.

This brings shrink_mmap() much closer to LRU order and seems
to fix quite a few performance problems here. Maybe there's
still a balancing mistake somewhere, but the system performance
is fine under all types of loads I managed to generate here...

I'm interested in real-world cases where anybody manages to
break this patch... (it's important that we get this exactly
right for 2.4, if you want performance, please test this patch)

regards,

Rik

--
The Internet is not a network of computers. It is a network
of people. That is its real strength.

Wanna talk about the kernel? irc.openprojects.net / #kernelnewbies http://www.conectiva.com/ http://www.surriel.com/

--- linux-2.3.99-pre6-3/mm/filemap.c.orig Mon Apr 17 12:21:46 2000 +++ linux-2.3.99-pre6-3/mm/filemap.c Tue Apr 18 15:08:08 2000 @@ -149,11 +149,16 @@ /* page wholly truncated - free it */ if (offset >= start) { + if (TryLockPage(page)) { + spin_unlock(&pagecache_lock); + get_page(page); + wait_on_page(page); + put_page(page); + goto repeat; + } get_page(page); spin_unlock(&pagecache_lock); - lock_page(page); - if (!page->buffers || block_flushpage(page, 0)) lru_cache_del(page); @@ -191,11 +196,13 @@ continue; /* partial truncate, clear end of page */ + if (TryLockPage(page)) { + spin_unlock(&pagecache_lock); + goto repeat; + } get_page(page); spin_unlock(&pagecache_lock); - lock_page(page); - memclear_highpage_flush(page, partial, PAGE_CACHE_SIZE-partial); if (page->buffers) block_flushpage(page, partial); @@ -208,6 +215,9 @@ */ UnlockPage(page); page_cache_release(page); + get_page(page); + wait_on_page(page); + put_page(page); goto repeat; } spin_unlock(&pagecache_lock); @@ -233,7 +243,18 @@ page = list_entry(page_lru, struct page, lru); list_del(page_lru); + /* What?! A page is in the LRU queue of another zone?! */ + if (!memclass(page->zone, zone)) + BUG(); + + count--; + dispose = &zone->lru_cache; + /* the page is in use, we can't free it now */ + if (!page->buffers && page_count(page) > 1) + goto dispose_continue; + + dispose = &old; if (test_and_clear_bit(PG_referenced, &page->flags)) /* Roll the page at the top of the lru list, * we could also be more aggressive putting @@ -242,18 +263,7 @@ */ goto dispose_continue; - dispose = &old; - /* don't account passes over not DMA pages */ - if (zone && (!memclass(page->zone, zone))) - goto dispose_continue; - - count--; - dispose = &young; - - /* avoid unscalable SMP locking */ - if (!page->buffers && page_count(page) > 1) - goto dispose_continue; if (TryLockPage(page)) goto dispose_continue;

- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Sun Apr 23 2000 - 21:00:14 EST