lkml.org 
[lkml]   [2002]   [Aug]   [11]   [last100]   RSS Feed
Views: [more markup]  [less markup]  [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
DateSun, 11 Aug 2002 00:39:25 -0700
FromAndrew Morton <>
Subject[patch 12/21] wrapup of LRU locking changes

Some fallout from the pagemap_lru_lock changes:

- lru_cache_del() is no longer used.  Kill it.

- page_cache_release() almost never actually frees pages.  So inline
  page_cache_release() and move its rarely-called slow path into (the
  misnamed) mm/swap.c

- update the locking comment in filemap.c.  pagemap_lru_lock used to
  be one of the outermost locks in the VM locking hierarchy.  Now, we
  never take any other locks while holding pagemap_lru_lock.  So it
  doesn't have any relationship with anything.

- put_page() now removes pages from the LRU on the final put.  The
  lock is interrupt save.




 include/linux/mm.h      |    7 ++++++-
 include/linux/pagemap.h |    8 ++++++--
 include/linux/swap.h    |    2 --
 kernel/ksyms.c          |    2 +-
 mm/filemap.c            |    1 -
 mm/page_alloc.c         |   20 +-------------------
 mm/swap.c               |   31 ++++++++++++-------------------
 mm/vmscan.c             |    6 ++++++
 8 files changed, 32 insertions(+), 45 deletions(-)
--- 2.5.31/mm/swap.c~lru-mopup	Sun Aug 11 00:20:33 2002
+++ 2.5.31-akpm/mm/swap.c	Sun Aug 11 00:21:01 2002
@@ -60,32 +60,25 @@ void lru_cache_add(struct page * page)
 	}
 }
 
-/**
- * __lru_cache_del: remove a page from the page lists
- * @page: the page to add
- *
- * This function is for when the caller already holds
- * the pagemap_lru_lock.
+/*
+ * This path almost never happens - pages are normally freed via pagevecs.
  */
-void __lru_cache_del(struct page * page)
+void __page_cache_release(struct page *page)
 {
-	if (TestClearPageLRU(page)) {
+	BUG_ON(page_count(page) != 0);
+	if (PageLRU(page)) {
+		unsigned long flags;
+
+		spin_lock_irqsave(&_pagemap_lru_lock, flags);
+		if (!TestClearPageLRU(page))
+			BUG();
 		if (PageActive(page))
 			del_page_from_active_list(page);
 		else
 			del_page_from_inactive_list(page);
+		spin_unlock_irqrestore(&_pagemap_lru_lock, flags);
 	}
-}
-
-/**
- * lru_cache_del: remove a page from the page lists
- * @page: the page to remove
- */
-void lru_cache_del(struct page * page)
-{
-	spin_lock_irq(&_pagemap_lru_lock);
-	__lru_cache_del(page);
-	spin_unlock_irq(&_pagemap_lru_lock);
+	__free_page(page);
 }
 
 /*
--- 2.5.31/include/linux/swap.h~lru-mopup	Sun Aug 11 00:20:33 2002
+++ 2.5.31-akpm/include/linux/swap.h	Sun Aug 11 00:21:01 2002
@@ -157,8 +157,6 @@ extern int FASTCALL(page_over_rsslimit(s
 
 /* linux/mm/swap.c */
 extern void FASTCALL(lru_cache_add(struct page *));
-extern void FASTCALL(__lru_cache_del(struct page *));
-extern void FASTCALL(lru_cache_del(struct page *));
 
 extern void FASTCALL(activate_page(struct page *));
 
--- 2.5.31/mm/page_alloc.c~lru-mopup	Sun Aug 11 00:20:33 2002
+++ 2.5.31-akpm/mm/page_alloc.c	Sun Aug 11 00:21:01 2002
@@ -90,6 +90,7 @@ static void __free_pages_ok (struct page
 
 	KERNEL_STAT_ADD(pgfree, 1<<order);
 
+	BUG_ON(PageLRU(page));
 	BUG_ON(PagePrivate(page));
 	BUG_ON(page->mapping != NULL);
 	BUG_ON(PageLocked(page));
@@ -450,25 +451,6 @@ unsigned long get_zeroed_page(unsigned i
 	return 0;
 }
 
-void page_cache_release(struct page *page)
-{
-	/*
-	 * FIXME: this PageReserved test is really expensive
-	 */
-	if (!PageReserved(page) && put_page_testzero(page)) {
-		/*
-		 * This path almost never happens - pages are normally freed
-		 * via pagevecs.
-		 */
-		struct pagevec pvec;
-
-		page_cache_get(page);
-		pvec.nr = 1;
-		pvec.pages[0] = page;
-		__pagevec_release(&pvec);
-	}
-}
-
 void __pagevec_free(struct pagevec *pvec)
 {
 	int i = pagevec_count(pvec);
--- 2.5.31/include/linux/pagemap.h~lru-mopup	Sun Aug 11 00:20:33 2002
+++ 2.5.31-akpm/include/linux/pagemap.h	Sun Aug 11 00:20:33 2002
@@ -23,14 +23,18 @@
 #define PAGE_CACHE_ALIGN(addr)	(((addr)+PAGE_CACHE_SIZE-1)&PAGE_CACHE_MASK)
 
 #define page_cache_get(x)	get_page(x)
-extern void FASTCALL(page_cache_release(struct page *));
+
+static inline void page_cache_release(struct page *page)
+{
+	if (!PageReserved(page) && put_page_testzero(page))
+		__page_cache_release(page);
+}
 
 static inline struct page *page_cache_alloc(struct address_space *x)
 {
 	return alloc_pages(x->gfp_mask, 0);
 }
 
-
 typedef int filler_t(void *, struct page *);
 
 extern struct page * find_get_page(struct address_space *mapping,
--- 2.5.31/kernel/ksyms.c~lru-mopup	Sun Aug 11 00:20:33 2002
+++ 2.5.31-akpm/kernel/ksyms.c	Sun Aug 11 00:20:33 2002
@@ -92,7 +92,7 @@ EXPORT_SYMBOL(__alloc_pages);
 EXPORT_SYMBOL(alloc_pages_node);
 EXPORT_SYMBOL(__get_free_pages);
 EXPORT_SYMBOL(get_zeroed_page);
-EXPORT_SYMBOL(page_cache_release);
+EXPORT_SYMBOL(__page_cache_release);
 EXPORT_SYMBOL(__free_pages);
 EXPORT_SYMBOL(free_pages);
 EXPORT_SYMBOL(num_physpages);
--- 2.5.31/mm/filemap.c~lru-mopup	Sun Aug 11 00:20:33 2002
+++ 2.5.31-akpm/mm/filemap.c	Sun Aug 11 00:21:01 2002
@@ -53,7 +53,6 @@
 /*
  * Lock ordering:
  *
- *  pagemap_lru_lock
  *  ->i_shared_lock		(vmtruncate)
  *    ->private_lock		(__free_pte->__set_page_dirty_buffers)
  *      ->swap_list_lock
--- 2.5.31/include/linux/mm.h~lru-mopup	Sun Aug 11 00:20:33 2002
+++ 2.5.31-akpm/include/linux/mm.h	Sun Aug 11 00:21:01 2002
@@ -194,11 +194,16 @@ struct page {
  * routine so they can be sure the page doesn't go away from under them.
  */
 #define get_page(p)		atomic_inc(&(p)->count)
-#define put_page(p)		__free_page(p)
 #define __put_page(p)		atomic_dec(&(p)->count)
 #define put_page_testzero(p) 	atomic_dec_and_test(&(p)->count)
 #define page_count(p)		atomic_read(&(p)->count)
 #define set_page_count(p,v) 	atomic_set(&(p)->count, v)
+extern void FASTCALL(__page_cache_release(struct page *));
+#define put_page(p)					\
+	do {						\
+		if (put_page_testzero(p))		\
+			__page_cache_release(p);	\
+	} while (0)
 
 /*
  * Multiple processes may "see" the same page. E.g. for untouched
--- 2.5.31/mm/vmscan.c~lru-mopup	Sun Aug 11 00:20:33 2002
+++ 2.5.31-akpm/mm/vmscan.c	Sun Aug 11 00:21:01 2002
@@ -165,6 +165,12 @@ shrink_list(struct list_head *page_list,
 		pte_chain_unlock(page);
 		mapping = page->mapping;
 
+		/*
+		 * FIXME: this is CPU-inefficient for shared mappings.
+		 * try_to_unmap() will set the page dirty and ->vm_writeback
+		 * will write it.  So we're back to page-at-a-time writepage
+		 * in LRU order.
+		 */
 		if (PageDirty(page) && is_page_cache_freeable(page) &&
 					mapping && may_enter_fs) {
 			int (*writeback)(struct page *, int *);
.
-
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/

\
 
 \ /
  Last update: 2005-03-22 12:27    [W:0.353 / U:0.020 seconds]
©2003-2008 Jasper Spaans