Re: broken VM in 2.4.10-pre9

From: Linus Torvalds (torvalds@transmeta.com)
Date: Mon Sep 17 2001 - 12:33:51 EST


On Mon, 17 Sep 2001, Rik van Riel wrote:
>
> > - truly anonymous pages (ie before they've been added to the swap cache)
> > are not necessarily going to behave as nicely as other pages. They
> > magically appear after VM scanning as a "1st reference", and I have a
> > reasonably good argument that says that they'll have been aged up and
> > down roughly the same number of times, which makes this more-or-less
> > correct. But it's still a theoretical argument, nothing more.
>
> This nicely points out the problem with page aging which Linux
> has always had. Pages which are referenced all the time by the
> processes using them STILL get aged down all the time.
>
> I suspect that the biggest impact the reverse mapping patch
> has right now seems to be caused by fixing this behaviour and
> just aging up a page when it is referenced and down when it is
> not.

Well, here's a 10-line patch to make the anonymous pages get on the LRU
queues, and thus get aged along with all the others.

NOTE NOTE NOTE! This is _literally_ a 15-minute hack, and I expect that
there are paths where I forget to remove the page from the LRU queue
(which should result in a nice big oops in __free_pages_ok()).

Also, I didn't look into shm handling - it _looks_ like shm will remove
the page from the LRU list and re-insert it, which will lose all list
information, of course.

But the point being that keeping anonymous pages on the LRU list shouldn't
be all that hard. Even if I missed something on this first try.

                Linus

------
diff -u --recursive --new-file penguin/linux/mm/filemap.c linux/mm/filemap.c
--- penguin/linux/mm/filemap.c Mon Sep 17 09:22:57 2001
+++ linux/mm/filemap.c Mon Sep 17 09:15:45 2001
@@ -489,7 +489,6 @@
         page->index = index;
         add_page_to_inode_queue(mapping, page);
         add_page_to_hash_queue(page, page_hash(mapping, index));
- lru_cache_add(page);
         spin_unlock(&pagecache_lock);
 }

diff -u --recursive --new-file penguin/linux/mm/memory.c linux/mm/memory.c
--- penguin/linux/mm/memory.c Mon Sep 17 09:23:55 2001
+++ linux/mm/memory.c Mon Sep 17 10:15:57 2001
@@ -958,6 +958,7 @@
                 if (pte_young(pte))
                         mark_page_accessed(old_page);
                 break_cow(vma, new_page, address, page_table);
+ lru_cache_add(new_page);

                 /* Free the old page.. */
                 new_page = old_page;
@@ -1198,6 +1199,7 @@
                 mm->rss++;
                 flush_page_to_ram(page);
                 entry = pte_mkwrite(pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
+ lru_cache_add(page);
         }

         set_pte(page_table, entry);
diff -u --recursive --new-file penguin/linux/mm/shmem.c linux/mm/shmem.c
--- penguin/linux/mm/shmem.c Mon Sep 17 09:22:57 2001
+++ linux/mm/shmem.c Mon Sep 17 09:17:12 2001
@@ -356,6 +356,7 @@
                 flags = page->flags & ~((1 << PG_uptodate) | (1 << PG_error) | (1 << PG_referenced) | (1 << PG_arch_1));
                 page->flags = flags | (1 << PG_dirty);
                 add_to_page_cache_locked(page, mapping, idx);
+ lru_cache_add(page);
                 info->swapped--;
                 spin_unlock (&info->lock);
         } else {
diff -u --recursive --new-file penguin/linux/mm/swap.c linux/mm/swap.c
--- penguin/linux/mm/swap.c Wed Aug 8 15:17:26 2001
+++ linux/mm/swap.c Mon Sep 17 09:50:33 2001
@@ -153,8 +153,6 @@
 void lru_cache_add(struct page * page)
 {
         spin_lock(&pagemap_lru_lock);
- if (!PageLocked(page))
- BUG();
         add_page_to_inactive_dirty_list(page);
         page->age = 0;
         spin_unlock(&pagemap_lru_lock);
@@ -176,7 +174,7 @@
         } else if (PageInactiveClean(page)) {
                 del_page_from_inactive_clean_list(page);
         } else {
- printk("VM: __lru_cache_del, found unknown page ?!\n");
+// printk("VM: __lru_cache_del, found unknown page ?!\n");
         }
         DEBUG_ADD_PAGE
 }
@@ -187,8 +185,6 @@
  */
 void lru_cache_del(struct page * page)
 {
- if (!PageLocked(page))
- BUG();
         spin_lock(&pagemap_lru_lock);
         __lru_cache_del(page);
         spin_unlock(&pagemap_lru_lock);
diff -u --recursive --new-file penguin/linux/mm/swap_state.c linux/mm/swap_state.c
--- penguin/linux/mm/swap_state.c Mon Sep 17 09:22:57 2001
+++ linux/mm/swap_state.c Mon Sep 17 09:42:20 2001
@@ -147,6 +147,10 @@
  */
 void free_page_and_swap_cache(struct page *page)
 {
+ if (page_count(page) == 1 && !page->mapping) {
+ lru_cache_del(page);
+ }
+
         /*
          * If we are the only user, then try to free up the swap cache.
          *

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



This archive was generated by hypermail 2b29 : Sun Sep 23 2001 - 21:00:20 EST