LKML Archive on lore.kernel.org
help / color / mirror / Atom feed
* [rfc 00/10] [RFC] Page flags: Saving some, making handling easier etc.
@ 2008-03-01  4:05 Christoph Lameter
  2008-03-01  4:05 ` [rfc 01/10] Pageflags: Use an enum for the flags Christoph Lameter
                   ` (9 more replies)
  0 siblings, 10 replies; 19+ messages in thread
From: Christoph Lameter @ 2008-03-01  4:05 UTC (permalink / raw)
  To: linux-kernel
  Cc: Mel Gorman, Nick Piggin, Rik van Riel, Andrew Morton, apw, linux-mm

A set of patches that attempts to improve page flag handling. First of all a
method is introduces to generate the page flag functions using macros. Then
the number of page flags used by sparsemem is reduced.

Then we add a way to export enum constant to the preprocessor which allows
us to get rid of __ZONE_COUNT and use the NR_PAGEFLAGS for the calculation
of actually available page flags for fields.

Lastly there is a land grab of page flags for various ongoing VM projects.

-- 

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [rfc 01/10] Pageflags: Use an enum for the flags
  2008-03-01  4:05 [rfc 00/10] [RFC] Page flags: Saving some, making handling easier etc Christoph Lameter
@ 2008-03-01  4:05 ` Christoph Lameter
  2008-03-03 10:09   ` Mel Gorman
  2008-03-01  4:05 ` [rfc 02/10] Pageflags: Introduce macros to generate page flag functions Christoph Lameter
                   ` (8 subsequent siblings)
  9 siblings, 1 reply; 19+ messages in thread
From: Christoph Lameter @ 2008-03-01  4:05 UTC (permalink / raw)
  To: linux-kernel
  Cc: Mel Gorman, Nick Piggin, Rik van Riel, Andrew Morton, apw, linux-mm

[-- Attachment #1: pageflags-use-enum --]
[-- Type: text/plain, Size: 3047 bytes --]

Use an enum to ease the maintenance of page flags. This is going to change the
numbering from 0 to 18.

Signed-off-by: Christoph Lameter <clameter@sgi.com>

---
 include/linux/page-flags.h |   54 ++++++++++++++++++++-------------------------
 1 file changed, 24 insertions(+), 30 deletions(-)

Index: linux-2.6/include/linux/page-flags.h
===================================================================
--- linux-2.6.orig/include/linux/page-flags.h	2008-02-29 14:54:22.000000000 -0800
+++ linux-2.6/include/linux/page-flags.h	2008-02-29 15:00:00.000000000 -0800
@@ -67,35 +67,28 @@
  * FLAGS_RESERVED which defines the width of the fields section
  * (see linux/mmzone.h).  New flags must _not_ overlap with this area.
  */
-#define PG_locked	 	 0	/* Page is locked. Don't touch. */
-#define PG_error		 1
-#define PG_referenced		 2
-#define PG_uptodate		 3
-
-#define PG_dirty	 	 4
-#define PG_lru			 5
-#define PG_active		 6
-#define PG_slab			 7	/* slab debug (Suparna wants this) */
-
-#define PG_owner_priv_1		 8	/* Owner use. If pagecache, fs may use*/
-#define PG_arch_1		 9
-#define PG_reserved		10
-#define PG_private		11	/* If pagecache, has fs-private data */
-
-#define PG_writeback		12	/* Page is under writeback */
-#define PG_compound		14	/* Part of a compound page */
-#define PG_swapcache		15	/* Swap page: swp_entry_t in private */
-
-#define PG_mappedtodisk		16	/* Has blocks allocated on-disk */
-#define PG_reclaim		17	/* To be reclaimed asap */
-#define PG_buddy		19	/* Page is free, on buddy lists */
-
-/* PG_readahead is only used for file reads; PG_reclaim is only for writes */
-#define PG_readahead		PG_reclaim /* Reminder to do async read-ahead */
-
-/* PG_owner_priv_1 users should have descriptive aliases */
-#define PG_checked		PG_owner_priv_1 /* Used by some filesystems */
-#define PG_pinned		PG_owner_priv_1	/* Xen pinned pagetable */
+enum pageflags {
+	PG_locked,		/* Page is locked. Don't touch. */
+	PG_error,
+	PG_referenced,
+	PG_uptodate,
+	PG_dirty,
+	PG_lru,
+	PG_active,
+	PG_slab,
+	PG_owner_priv_1,	/* Owner use. If pagecache, fs may use*/
+	PG_arch_1,
+	PG_reserved,
+	PG_private,		/* If pagecache, has fs-private data */
+	PG_writeback,		/* Page is under writeback */
+	PG_compound,		/* A compound page */
+	PG_swapcache,		/* Swap page: swp_entry_t in private */
+	PG_mappedtodisk,	/* Has blocks allocated on-disk */
+	PG_reclaim,		/* To be reclaimed asap */
+	/* PG_readahead is only used for file reads; PG_reclaim is only for writes */
+	PG_readahead = PG_reclaim, /* Reminder to do async read-ahead */
+	PG_buddy,		/* Page is free, on buddy lists */
+	NR_PAGEFLAGS,		/* For verification purposes */
 
 #if (BITS_PER_LONG > 32)
 /*
@@ -105,8 +98,9 @@
  * 64 bit  |           FIELDS             | ??????         FLAGS         |
  *         63                            32                              0
  */
-#define PG_uncached		31	/* Page has been mapped as uncached */
+	PG_uncached = 31,		/* Page has been mapped as uncached */
 #endif
+};
 
 /*
  * Manipulation of page state flags

-- 

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [rfc 02/10] Pageflags: Introduce macros to generate page flag functions
  2008-03-01  4:05 [rfc 00/10] [RFC] Page flags: Saving some, making handling easier etc Christoph Lameter
  2008-03-01  4:05 ` [rfc 01/10] Pageflags: Use an enum for the flags Christoph Lameter
@ 2008-03-01  4:05 ` Christoph Lameter
  2008-03-01  4:05 ` [rfc 03/10] Pageflags: Convert to the use of new macros Christoph Lameter
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 19+ messages in thread
From: Christoph Lameter @ 2008-03-01  4:05 UTC (permalink / raw)
  To: linux-kernel
  Cc: Mel Gorman, Nick Piggin, Rik van Riel, Andrew Morton, apw, linux-mm

[-- Attachment #1: pageflags-add-macros --]
[-- Type: text/plain, Size: 2873 bytes --]

Introduce a set of macros that generate functions to handle page flags.


A page flag function group typically starts with either

	SETPAGEFLAG(<part of function name>,<part of PG_ flagname>)

to create a set of page flag operations that are atomic. Or

	__SETPAGEFLAG(<part of function name>,<part of PG_ flagname)

to create a set of page flag operations that are not atomic.


Then additional operations can be added using the following macros

TESTSCFLAG		Create additional atomic test-and-set and
			test-and-clear functions

TESTSETFLAG		Create additional test and set function
TESTCLEARFLAG		Create additional test and clear function
TESTPAGEFLAG		Create additional atomic set function
SETPAGEFLAG		Create additional atomic clear function
__TESTPAGEFLAG		Create additional atomic set function
__SETPAGEFLAG		Create additional atomic clear function

Signed-off-by: Christoph Lameter <clameter@sgi.com>

---
 include/linux/page-flags.h |   41 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 41 insertions(+)

Index: linux-2.6/include/linux/page-flags.h
===================================================================
--- linux-2.6.orig/include/linux/page-flags.h	2008-02-29 19:14:30.000000000 -0800
+++ linux-2.6/include/linux/page-flags.h	2008-02-29 19:15:28.000000000 -0800
@@ -103,6 +103,47 @@ enum pageflags {
 };
 
 /*
+ * Macros to create function definitions for page flags
+ */
+#define TESTPAGEFLAG(uname, lname)					\
+static inline int Page##uname(struct page *page) 			\
+			{ return test_bit(PG_##lname, page); }
+
+#define SETPAGEFLAG(uname, lname)					\
+static inline void SetPage##uname(struct page *page)			\
+			{ set_bit(PG_##lname, page); }
+
+#define CLEARPAGEFLAG(uname, lname)					\
+static inline void ClearPage##uname(struct page *page)			\
+			{ clear_bit(PG_##lname, page); }
+
+#define __SETPAGEFLAG(uname, lname)					\
+static inline void __SetPage##uname(struct page *page)			\
+			{ __set_bit(PG_##lname, page); }
+
+#define __CLEARPAGEFLAG(uname, lname)					\
+static inline void __ClearPage##uname(struct page *page)		\
+			{ __clear_bit(PG_##lname, page); }
+
+#define TESTSETFLAG(uname, lname)					\
+static inline int TestSetPage##uname(struct page *page)			\
+		{ return test_and_set_bit(PG_##lname, &page->flags); }
+
+#define TESTCLEARFLAG(uname, lname)					\
+static inline int TestClearPage##uname(struct page *page)		\
+		{ return test_and_clear_bit(PG_##lname, &page->flags); }
+
+
+#define PAGEFLAG(uname, lname) TESTPAGEFLAG(uname, lname)		\
+	SETPAGEFLAG(uname, lname) CLEARPAGEFLAG(uname, lname)
+
+#define __PAGEFLAG(uname, lname) TESTPAGEFLAG(uname, lname)		\
+	__SETPAGEFLAG(uname, lname)  __CLEARPAGEFLAG(uname, lname)
+
+#define TESTSCFLAG(uname, lname)					\
+			TESTSETFLAG(uname, lname) TESTCLEARFLAG(uname, lname)
+
+/*
  * Manipulation of page state flags
  */
 #define PageLocked(page)		\

-- 

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [rfc 03/10] Pageflags: Convert to the use of new macros
  2008-03-01  4:05 [rfc 00/10] [RFC] Page flags: Saving some, making handling easier etc Christoph Lameter
  2008-03-01  4:05 ` [rfc 01/10] Pageflags: Use an enum for the flags Christoph Lameter
  2008-03-01  4:05 ` [rfc 02/10] Pageflags: Introduce macros to generate page flag functions Christoph Lameter
@ 2008-03-01  4:05 ` Christoph Lameter
  2008-03-03 10:24   ` Mel Gorman
  2008-03-01  4:05 ` [rfc 04/10] Pageflags: Eliminate PG_readahead Christoph Lameter
                   ` (6 subsequent siblings)
  9 siblings, 1 reply; 19+ messages in thread
From: Christoph Lameter @ 2008-03-01  4:05 UTC (permalink / raw)
  To: linux-kernel
  Cc: Mel Gorman, Nick Piggin, Rik van Riel, Andrew Morton, apw, linux-mm

[-- Attachment #1: pageflags-conversion --]
[-- Type: text/plain, Size: 9686 bytes --]

Replace explicit definitions of page flags through the use of macros.
Significantly reduces the size of the definitions and removes a lot of
opportunity for errors. Additonal page flags can typically be generated
with a single line.

Signed-off-by: Christoph Lameter <clameter@sgi.com>

---
 include/linux/page-flags.h |  188 ++++++++++++++-------------------------------
 1 file changed, 61 insertions(+), 127 deletions(-)

Index: linux-2.6/include/linux/page-flags.h
===================================================================
--- linux-2.6.orig/include/linux/page-flags.h	2008-02-29 19:15:28.000000000 -0800
+++ linux-2.6/include/linux/page-flags.h	2008-02-29 19:20:03.000000000 -0800
@@ -143,28 +143,51 @@ static inline int TestClearPage##uname(s
 #define TESTSCFLAG(uname, lname)					\
 			TESTSETFLAG(uname, lname) TESTCLEARFLAG(uname, lname)
 
+struct page;	/* forward declaration */
+
+PAGEFLAG(Locked, locked) TESTSCFLAG(Locked, locked)
+PAGEFLAG(Error, error)
+PAGEFLAG(Referenced, referenced) TESTCLEARFLAG(Referenced, referenced)
+PAGEFLAG(Dirty, dirty) TESTSCFLAG(Dirty, dirty) __CLEARPAGEFLAG(Dirty, dirty)
+PAGEFLAG(LRU, lru) __CLEARPAGEFLAG(LRU, lru)
+PAGEFLAG(Active, active) __CLEARPAGEFLAG(Active, active)
+__PAGEFLAG(Slab, slab)
+PAGEFLAG(Checked, owner_priv_1)		/* Used by some filesystems */
+PAGEFLAG(Pinned, owner_priv_1)		/* Xen pinned pagetable */
+PAGEFLAG(Reserved, reserved) __CLEARPAGEFLAG(Reserved, reserved)
+PAGEFLAG(Private, private) __CLEARPAGEFLAG(Private, private)
+	__SETPAGEFLAG(Private, private)
+
 /*
- * Manipulation of page state flags
+ * Only test-and-set exist for PG_writeback.  The unconditional operators are
+ * risky: they bypass page accounting.
  */
-#define PageLocked(page)		\
-		test_bit(PG_locked, &(page)->flags)
-#define SetPageLocked(page)		\
-		set_bit(PG_locked, &(page)->flags)
-#define TestSetPageLocked(page)		\
-		test_and_set_bit(PG_locked, &(page)->flags)
-#define ClearPageLocked(page)		\
-		clear_bit(PG_locked, &(page)->flags)
-#define TestClearPageLocked(page)	\
-		test_and_clear_bit(PG_locked, &(page)->flags)
-
-#define PageError(page)		test_bit(PG_error, &(page)->flags)
-#define SetPageError(page)	set_bit(PG_error, &(page)->flags)
-#define ClearPageError(page)	clear_bit(PG_error, &(page)->flags)
-
-#define PageReferenced(page)	test_bit(PG_referenced, &(page)->flags)
-#define SetPageReferenced(page)	set_bit(PG_referenced, &(page)->flags)
-#define ClearPageReferenced(page)	clear_bit(PG_referenced, &(page)->flags)
-#define TestClearPageReferenced(page) test_and_clear_bit(PG_referenced, &(page)->flags)
+TESTPAGEFLAG(Writeback, writeback) TESTSCFLAG(Writeback, writeback)
+__PAGEFLAG(Buddy, buddy)
+PAGEFLAG(MappedToDisk, mappedtodisk)
+
+/* PG_readahead is only used for file reads; PG_reclaim is only for writes */
+PAGEFLAG(Reclaim, reclaim) TESTCLEARFLAG(Reclaim, reclaim)
+PAGEFLAG(Readahead, readahead)		/* Reminder to do async read-ahead */
+
+#ifdef CONFIG_HIGHMEM
+#define PageHighMem(page)	is_highmem(page_zone(page))
+#else
+#define PageHighMem(page)	0 /* needed to optimize away at compile time */
+#endif
+
+#ifdef CONFIG_SWAP
+PAGEFLAG(SwapCache, swapcache)
+#else
+static inline int PageSwapCache(struct page *page)
+{
+	return 0;
+}
+#endif
+
+#if (BITS_PER_LONG > 32)
+PAGEFLAG(Uncached, uncached)
+#endif
 
 static inline int PageUptodate(struct page *page)
 {
@@ -212,97 +235,37 @@ static inline void SetPageUptodate(struc
 #endif
 }
 
-#define ClearPageUptodate(page)	clear_bit(PG_uptodate, &(page)->flags)
+CLEARPAGEFLAG(Uptodate, uptodate)
 
-#define PageDirty(page)		test_bit(PG_dirty, &(page)->flags)
-#define SetPageDirty(page)	set_bit(PG_dirty, &(page)->flags)
-#define TestSetPageDirty(page)	test_and_set_bit(PG_dirty, &(page)->flags)
-#define ClearPageDirty(page)	clear_bit(PG_dirty, &(page)->flags)
-#define __ClearPageDirty(page)	__clear_bit(PG_dirty, &(page)->flags)
-#define TestClearPageDirty(page) test_and_clear_bit(PG_dirty, &(page)->flags)
-
-#define PageLRU(page)		test_bit(PG_lru, &(page)->flags)
-#define SetPageLRU(page)	set_bit(PG_lru, &(page)->flags)
-#define ClearPageLRU(page)	clear_bit(PG_lru, &(page)->flags)
-#define __ClearPageLRU(page)	__clear_bit(PG_lru, &(page)->flags)
-
-#define PageActive(page)	test_bit(PG_active, &(page)->flags)
-#define SetPageActive(page)	set_bit(PG_active, &(page)->flags)
-#define ClearPageActive(page)	clear_bit(PG_active, &(page)->flags)
-#define __ClearPageActive(page)	__clear_bit(PG_active, &(page)->flags)
-
-#define PageSlab(page)		test_bit(PG_slab, &(page)->flags)
-#define __SetPageSlab(page)	__set_bit(PG_slab, &(page)->flags)
-#define __ClearPageSlab(page)	__clear_bit(PG_slab, &(page)->flags)
+extern void cancel_dirty_page(struct page *page, unsigned int account_size);
 
-#ifdef CONFIG_HIGHMEM
-#define PageHighMem(page)	is_highmem(page_zone(page))
-#else
-#define PageHighMem(page)	0 /* needed to optimize away at compile time */
-#endif
+int test_clear_page_writeback(struct page *page);
+int test_set_page_writeback(struct page *page);
 
-#define PageChecked(page)	test_bit(PG_checked, &(page)->flags)
-#define SetPageChecked(page)	set_bit(PG_checked, &(page)->flags)
-#define ClearPageChecked(page)	clear_bit(PG_checked, &(page)->flags)
-
-#define PagePinned(page)	test_bit(PG_pinned, &(page)->flags)
-#define SetPagePinned(page)	set_bit(PG_pinned, &(page)->flags)
-#define ClearPagePinned(page)	clear_bit(PG_pinned, &(page)->flags)
-
-#define PageReserved(page)	test_bit(PG_reserved, &(page)->flags)
-#define SetPageReserved(page)	set_bit(PG_reserved, &(page)->flags)
-#define ClearPageReserved(page)	clear_bit(PG_reserved, &(page)->flags)
-#define __ClearPageReserved(page)	__clear_bit(PG_reserved, &(page)->flags)
-
-#define SetPagePrivate(page)	set_bit(PG_private, &(page)->flags)
-#define ClearPagePrivate(page)	clear_bit(PG_private, &(page)->flags)
-#define PagePrivate(page)	test_bit(PG_private, &(page)->flags)
-#define __SetPagePrivate(page)  __set_bit(PG_private, &(page)->flags)
-#define __ClearPagePrivate(page) __clear_bit(PG_private, &(page)->flags)
+static inline void set_page_writeback(struct page *page)
+{
+	test_set_page_writeback(page);
+}
 
-/*
- * Only test-and-set exist for PG_writeback.  The unconditional operators are
- * risky: they bypass page accounting.
- */
-#define PageWriteback(page)	test_bit(PG_writeback, &(page)->flags)
-#define TestSetPageWriteback(page) test_and_set_bit(PG_writeback,	\
-							&(page)->flags)
-#define TestClearPageWriteback(page) test_and_clear_bit(PG_writeback,	\
-							&(page)->flags)
-
-#define PageBuddy(page)		test_bit(PG_buddy, &(page)->flags)
-#define __SetPageBuddy(page)	__set_bit(PG_buddy, &(page)->flags)
-#define __ClearPageBuddy(page)	__clear_bit(PG_buddy, &(page)->flags)
-
-#define PageMappedToDisk(page)	test_bit(PG_mappedtodisk, &(page)->flags)
-#define SetPageMappedToDisk(page) set_bit(PG_mappedtodisk, &(page)->flags)
-#define ClearPageMappedToDisk(page) clear_bit(PG_mappedtodisk, &(page)->flags)
-
-#define PageReadahead(page)	test_bit(PG_readahead, &(page)->flags)
-#define SetPageReadahead(page)	set_bit(PG_readahead, &(page)->flags)
-#define ClearPageReadahead(page) clear_bit(PG_readahead, &(page)->flags)
-
-#define PageReclaim(page)	test_bit(PG_reclaim, &(page)->flags)
-#define SetPageReclaim(page)	set_bit(PG_reclaim, &(page)->flags)
-#define ClearPageReclaim(page)	clear_bit(PG_reclaim, &(page)->flags)
-#define TestClearPageReclaim(page) test_and_clear_bit(PG_reclaim, &(page)->flags)
-
-#define PageCompound(page)	test_bit(PG_compound, &(page)->flags)
-#define __SetPageCompound(page)	__set_bit(PG_compound, &(page)->flags)
-#define __ClearPageCompound(page) __clear_bit(PG_compound, &(page)->flags)
+TESTPAGEFLAG(Compound, compound)
+__PAGEFLAG(Head, compound)
 
 /*
  * PG_reclaim is used in combination with PG_compound to mark the
- * head and tail of a compound page
+ * head and tail of a compound page. This saves one page flag
+ * but makes it impossible to use compound pages for the page cache.
+ * The PG_reclaim bit would have to be used for reclaim or readahead
+ * if compound pages enter the page cache.
  *
  * PG_compound & PG_reclaim	=> Tail page
  * PG_compound & ~PG_reclaim	=> Head page
  */
-
 #define PG_head_tail_mask ((1L << PG_compound) | (1L << PG_reclaim))
 
-#define PageTail(page)	(((page)->flags & PG_head_tail_mask)	\
-				== PG_head_tail_mask)
+static inline int PageTail(struct page *page)
+{
+	return ((page->flags & PG_head_tail_mask) == PG_head_tail_mask);
+}
 
 static inline void __SetPageTail(struct page *page)
 {
@@ -314,33 +277,4 @@ static inline void __ClearPageTail(struc
 	page->flags &= ~PG_head_tail_mask;
 }
 
-#define PageHead(page)	(((page)->flags & PG_head_tail_mask)	\
-				== (1L << PG_compound))
-#define __SetPageHead(page)	__SetPageCompound(page)
-#define __ClearPageHead(page)	__ClearPageCompound(page)
-
-#ifdef CONFIG_SWAP
-#define PageSwapCache(page)	test_bit(PG_swapcache, &(page)->flags)
-#define SetPageSwapCache(page)	set_bit(PG_swapcache, &(page)->flags)
-#define ClearPageSwapCache(page) clear_bit(PG_swapcache, &(page)->flags)
-#else
-#define PageSwapCache(page)	0
-#endif
-
-#define PageUncached(page)	test_bit(PG_uncached, &(page)->flags)
-#define SetPageUncached(page)	set_bit(PG_uncached, &(page)->flags)
-#define ClearPageUncached(page)	clear_bit(PG_uncached, &(page)->flags)
-
-struct page;	/* forward declaration */
-
-extern void cancel_dirty_page(struct page *page, unsigned int account_size);
-
-int test_clear_page_writeback(struct page *page);
-int test_set_page_writeback(struct page *page);
-
-static inline void set_page_writeback(struct page *page)
-{
-	test_set_page_writeback(page);
-}
-
 #endif	/* PAGE_FLAGS_H */

-- 

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [rfc 04/10] Pageflags: Eliminate PG_readahead
  2008-03-01  4:05 [rfc 00/10] [RFC] Page flags: Saving some, making handling easier etc Christoph Lameter
                   ` (2 preceding siblings ...)
  2008-03-01  4:05 ` [rfc 03/10] Pageflags: Convert to the use of new macros Christoph Lameter
@ 2008-03-01  4:05 ` Christoph Lameter
  2008-03-01  4:05 ` [rfc 05/10] Sparsemem: Vmemmap does not need section bits Christoph Lameter
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 19+ messages in thread
From: Christoph Lameter @ 2008-03-01  4:05 UTC (permalink / raw)
  To: linux-kernel
  Cc: Mel Gorman, Nick Piggin, Rik van Riel, Andrew Morton, apw, linux-mm

[-- Attachment #1: pageflags-elimiate_pg_readahead --]
[-- Type: text/plain, Size: 2088 bytes --]

PG_readahead is an alias of PG_reclaim. We can easily drop that now and
alias by specifying PG_reclaim in the macro that generates the functions
for PageReadahead().

Signed-off-by: Christoph Lameter <clameter@sgi.com>

---
 include/linux/page-flags.h |    4 +---
 mm/page_alloc.c            |    2 +-
 2 files changed, 2 insertions(+), 4 deletions(-)

Index: linux-2.6/mm/page_alloc.c
===================================================================
--- linux-2.6.orig/mm/page_alloc.c	2008-02-29 19:13:56.000000000 -0800
+++ linux-2.6/mm/page_alloc.c	2008-02-29 19:20:11.000000000 -0800
@@ -623,7 +623,7 @@ static int prep_new_page(struct page *pa
 	if (PageReserved(page))
 		return 1;
 
-	page->flags &= ~(1 << PG_uptodate | 1 << PG_error | 1 << PG_readahead |
+	page->flags &= ~(1 << PG_uptodate | 1 << PG_error | 1 << PG_reclaim |
 			1 << PG_referenced | 1 << PG_arch_1 |
 			1 << PG_owner_priv_1 | 1 << PG_mappedtodisk);
 	set_page_private(page, 0);
Index: linux-2.6/include/linux/page-flags.h
===================================================================
--- linux-2.6.orig/include/linux/page-flags.h	2008-02-29 19:20:03.000000000 -0800
+++ linux-2.6/include/linux/page-flags.h	2008-02-29 19:20:11.000000000 -0800
@@ -85,8 +85,6 @@ enum pageflags {
 	PG_swapcache,		/* Swap page: swp_entry_t in private */
 	PG_mappedtodisk,	/* Has blocks allocated on-disk */
 	PG_reclaim,		/* To be reclaimed asap */
-	/* PG_readahead is only used for file reads; PG_reclaim is only for writes */
-	PG_readahead = PG_reclaim, /* Reminder to do async read-ahead */
 	PG_buddy,		/* Page is free, on buddy lists */
 	NR_PAGEFLAGS,		/* For verification purposes */
 
@@ -168,7 +166,7 @@ PAGEFLAG(MappedToDisk, mappedtodisk)
 
 /* PG_readahead is only used for file reads; PG_reclaim is only for writes */
 PAGEFLAG(Reclaim, reclaim) TESTCLEARFLAG(Reclaim, reclaim)
-PAGEFLAG(Readahead, readahead)		/* Reminder to do async read-ahead */
+PAGEFLAG(Readahead, reclaim)		/* Reminder to do async read-ahead */
 
 #ifdef CONFIG_HIGHMEM
 #define PageHighMem(page)	is_highmem(page_zone(page))

-- 

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [rfc 05/10] Sparsemem: Vmemmap does not need section bits
  2008-03-01  4:05 [rfc 00/10] [RFC] Page flags: Saving some, making handling easier etc Christoph Lameter
                   ` (3 preceding siblings ...)
  2008-03-01  4:05 ` [rfc 04/10] Pageflags: Eliminate PG_readahead Christoph Lameter
@ 2008-03-01  4:05 ` Christoph Lameter
  2008-03-01  4:05 ` [rfc 06/10] Kbuild: Create a way to create preprocessor constants from C expressions Christoph Lameter
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 19+ messages in thread
From: Christoph Lameter @ 2008-03-01  4:05 UTC (permalink / raw)
  To: linux-kernel
  Cc: Mel Gorman, Nick Piggin, Rik van Riel, Andrew Morton, apw, linux-mm

[-- Attachment #1: sparsemem_vmemmap_does_not_need_section_flags --]
[-- Type: text/plain, Size: 2297 bytes --]

Sparsemem vmemmap does not need any section bits. This patch has
the effect of reducing the number of bits used in page->flags
by at least 6.

Add an #error in sparse.c to avoid trouble if the page flags use
becomes so large that no node number fits in there anymore. We can then
no longer fallback from the use of the node to the use of the sectionID
for sparsemem vmemmap. The node width is always smaller than the width
of the section. So one would never want to fallback this way for
vmemmap.

Signed-off-by: Christoph Lameter <clameter@sgi.com>

---
 include/linux/mm.h |    8 ++++----
 mm/sparse.c        |    4 ++++
 2 files changed, 8 insertions(+), 4 deletions(-)

Index: linux-2.6/include/linux/mm.h
===================================================================
--- linux-2.6.orig/include/linux/mm.h	2008-02-29 16:09:13.000000000 -0800
+++ linux-2.6/include/linux/mm.h	2008-02-29 16:11:28.000000000 -0800
@@ -390,11 +390,11 @@ static inline void set_compound_order(st
  * we have run out of space and have to fall back to an
  * alternate (slower) way of determining the node.
  *
- *        No sparsemem: |       NODE     | ZONE | ... | FLAGS |
- * with space for node: | SECTION | NODE | ZONE | ... | FLAGS |
- *   no space for node: | SECTION |     ZONE    | ... | FLAGS |
+ * No sparsemem or sparsemem vmemmap: |       NODE     | ZONE | ... | FLAGS |
+ * classic sparse with space for node:| SECTION | NODE | ZONE | ... | FLAGS |
+ * classic sparse no space for node:  | SECTION |     ZONE    | ... | FLAGS |
  */
-#ifdef CONFIG_SPARSEMEM
+#if defined(CONFIG_SPARSEMEM) && !defined(CONFIG_SPARSEMEM_VMEMMAP)
 #define SECTIONS_WIDTH		SECTIONS_SHIFT
 #else
 #define SECTIONS_WIDTH		0
Index: linux-2.6/mm/sparse.c
===================================================================
--- linux-2.6.orig/mm/sparse.c	2008-02-29 16:11:32.000000000 -0800
+++ linux-2.6/mm/sparse.c	2008-02-29 16:12:28.000000000 -0800
@@ -27,6 +27,10 @@ struct mem_section mem_section[NR_SECTIO
 EXPORT_SYMBOL(mem_section);
 
 #ifdef NODE_NOT_IN_PAGE_FLAGS
+#ifdef CONFIG_SPARSEMEM_VMEMMAP
+#error SPARSEMEM_VMEMMAP must have the node in page flags
+#endif
+
 /*
  * If we did not store the node number in the page then we have to
  * do a lookup in the section_to_node_table in order to find which

-- 

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [rfc 06/10] Kbuild: Create a way to create preprocessor constants from C expressions
  2008-03-01  4:05 [rfc 00/10] [RFC] Page flags: Saving some, making handling easier etc Christoph Lameter
                   ` (4 preceding siblings ...)
  2008-03-01  4:05 ` [rfc 05/10] Sparsemem: Vmemmap does not need section bits Christoph Lameter
@ 2008-03-01  4:05 ` Christoph Lameter
  2008-03-01  4:05 ` [rfc 07/10] Pageflags: Get rid of FLAGS_RESERVED Christoph Lameter
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 19+ messages in thread
From: Christoph Lameter @ 2008-03-01  4:05 UTC (permalink / raw)
  To: linux-kernel
  Cc: Mel Gorman, Nick Piggin, Rik van Riel, Andrew Morton, apw, linux-mm

[-- Attachment #1: kbuild_cpp_export --]
[-- Type: text/plain, Size: 3158 bytes --]

The use of enums create constants that are not available to the preprocessor
when building the kernel (f.e. MAX_NR_ZONES).

Arch code already has a way to export constants calculated to the
preprocessor through the asm-offsets.c file. Generate something
similar for the core kernel through kbuild.

Signed-off-by: Christoph Lameter <clameter@sgi.com>

---
 Kbuild                 |   31 +++++++++++++++++++++++++++++--
 include/linux/bounds.h |   10 ++++++++++
 kernel/bounds.c        |   16 ++++++++++++++++
 3 files changed, 55 insertions(+), 2 deletions(-)

Index: linux-2.6/Kbuild
===================================================================
--- linux-2.6.orig/Kbuild	2008-02-29 19:27:40.000000000 -0800
+++ linux-2.6/Kbuild	2008-02-29 19:29:38.000000000 -0800
@@ -9,9 +9,10 @@
 #
 
 offsets-file := include/asm-$(SRCARCH)/asm-offsets.h
+bounds := include/linux/bounds.h
 
-always  := $(offsets-file)
-targets := $(offsets-file)
+always  := $(offsets-file) $(bounds)
+targets := $(offsets-file) $(bounds)
 targets += arch/$(SRCARCH)/kernel/asm-offsets.s
 clean-files := $(addprefix $(objtree)/,$(targets))
 
@@ -39,6 +40,23 @@ define cmd_offsets
 	 echo "#endif" ) > $@
 endef
 
+quiet_cmd_bounds = GEN     $@
+define cmd_bounds
+	(set -e; \
+	 echo "#ifndef __LINUX_BOUNDS_H__"; \
+	 echo "#define __LINUX_BOUNDS_H__"; \
+	 echo "/*"; \
+	 echo " * DO NOT MODIFY."; \
+	 echo " *"; \
+	 echo " * This file was generated by Kbuild"; \
+	 echo " *"; \
+	 echo " */"; \
+	 echo ""; \
+	 sed -ne $(sed-y) $<; \
+	 echo ""; \
+	 echo "#endif" ) > $@
+endef
+
 # We use internal kbuild rules to avoid the "is up to date" message from make
 arch/$(SRCARCH)/kernel/asm-offsets.s: arch/$(SRCARCH)/kernel/asm-offsets.c FORCE
 	$(Q)mkdir -p $(dir $@)
@@ -48,6 +66,15 @@ $(obj)/$(offsets-file): arch/$(SRCARCH)/
 	$(Q)mkdir -p $(dir $@)
 	$(call cmd,offsets)
 
+# We use internal kbuild rules to avoid the "is up to date" message from make
+kernel/bounds.s: kernel/bounds.c FORCE
+	$(Q)mkdir -p $(dir $@)
+	$(call if_changed_dep,cc_s_c)
+
+$(obj)/$(bounds): kernel/bounds.s Kbuild
+	$(Q)mkdir -p $(dir $@)
+	$(call cmd,bounds)
+
 #####
 # 2) Check for missing system calls
 #
Index: linux-2.6/kernel/bounds.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6/kernel/bounds.c	2008-02-29 19:29:38.000000000 -0800
@@ -0,0 +1,16 @@
+/*
+ * Generate definitions needed by the preprocessor.
+ * This code generates raw asm output which is post-processed
+ * to extract and format the required data.
+ */
+
+#include <linux/mm.h>
+
+#define DEFINE(sym, val) \
+        asm volatile("\n->" #sym " %0 " #val : : "i" (val))
+
+#define BLANK() asm volatile("\n->" : : )
+
+void foo(void)
+{
+}
Index: linux-2.6/include/linux/bounds.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6/include/linux/bounds.h	2008-02-29 19:29:50.000000000 -0800
@@ -0,0 +1,10 @@
+#ifndef __LINUX_BOUNDS_H__
+#define __LINUX_BOUNDS_H__
+/*
+ * DO NOT MODIFY.
+ *
+ * This file was generated by Kbuild
+ *
+ */
+
+#endif

-- 

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [rfc 07/10] Pageflags: Get rid of FLAGS_RESERVED
  2008-03-01  4:05 [rfc 00/10] [RFC] Page flags: Saving some, making handling easier etc Christoph Lameter
                   ` (5 preceding siblings ...)
  2008-03-01  4:05 ` [rfc 06/10] Kbuild: Create a way to create preprocessor constants from C expressions Christoph Lameter
@ 2008-03-01  4:05 ` Christoph Lameter
  2008-03-01 16:26   ` Rik van Riel
  2008-03-01  4:05 ` [rfc 08/10] Export NR_MAX_ZONES to the preprocessor Christoph Lameter
                   ` (2 subsequent siblings)
  9 siblings, 1 reply; 19+ messages in thread
From: Christoph Lameter @ 2008-03-01  4:05 UTC (permalink / raw)
  To: linux-kernel
  Cc: Mel Gorman, Nick Piggin, Rik van Riel, Andrew Morton, apw, linux-mm

[-- Attachment #1: pageflags-get-rid-of-flags-reserved --]
[-- Type: text/plain, Size: 4924 bytes --]

NR_PAGEFLAGS specifies the number of page flags we are using.
>From that we can calculate the number of bits leftover that can
be used for zone, node (and maybe the sections id). There is
no need anymore for FLAGS_RESERVED if we use NR_PAGEFLAGS.

Use the new methods to make NR_PAGEFLAGS available via
the preprocessor. NR_PAGEFLAGS is used to calculate field
boundaries in the page flags fields. These field widths have
to be available to the preprocessor.

Signed-off-by: Christoph Lameter <clameter@sgi.com>

---
 include/linux/bounds.h     |    2 ++
 include/linux/mm.h         |    6 +++---
 include/linux/mmzone.h     |   19 -------------------
 include/linux/page-flags.h |   14 +++++++-------
 kernel/bounds.c            |    1 +
 5 files changed, 13 insertions(+), 29 deletions(-)

Index: linux-2.6/include/linux/mm.h
===================================================================
--- linux-2.6.orig/include/linux/mm.h	2008-02-29 19:21:35.000000000 -0800
+++ linux-2.6/include/linux/mm.h	2008-02-29 19:29:53.000000000 -0800
@@ -402,7 +402,7 @@ static inline void set_compound_order(st
 
 #define ZONES_WIDTH		ZONES_SHIFT
 
-#if SECTIONS_WIDTH+ZONES_WIDTH+NODES_SHIFT <= FLAGS_RESERVED
+#if SECTIONS_WIDTH+ZONES_WIDTH+NODES_SHIFT <= BITS_PER_LONG - NR_PAGEFLAGS
 #define NODES_WIDTH		NODES_SHIFT
 #else
 #define NODES_WIDTH		0
@@ -447,8 +447,8 @@ static inline void set_compound_order(st
 
 #define ZONEID_PGSHIFT		(ZONEID_PGOFF * (ZONEID_SHIFT != 0))
 
-#if SECTIONS_WIDTH+NODES_WIDTH+ZONES_WIDTH > FLAGS_RESERVED
-#error SECTIONS_WIDTH+NODES_WIDTH+ZONES_WIDTH > FLAGS_RESERVED
+#if SECTIONS_WIDTH+NODES_WIDTH+ZONES_WIDTH > BITS_PER_LONG - NR_PAGEFLAGS
+#error SECTIONS_WIDTH+NODES_WIDTH+ZONES_WIDTH > BITS_PER_LONG - NR_PAGEFLAGS
 #endif
 
 #define ZONES_MASK		((1UL << ZONES_WIDTH) - 1)
Index: linux-2.6/include/linux/mmzone.h
===================================================================
--- linux-2.6.orig/include/linux/mmzone.h	2008-02-29 19:13:55.000000000 -0800
+++ linux-2.6/include/linux/mmzone.h	2008-02-29 19:29:53.000000000 -0800
@@ -735,25 +735,6 @@ extern struct zone *next_zone(struct zon
 #include <asm/sparsemem.h>
 #endif
 
-#if BITS_PER_LONG == 32
-/*
- * with 32 bit page->flags field, we reserve 9 bits for node/zone info.
- * there are 4 zones (3 bits) and this leaves 9-3=6 bits for nodes.
- */
-#define FLAGS_RESERVED		9
-
-#elif BITS_PER_LONG == 64
-/*
- * with 64 bit flags field, there's plenty of room.
- */
-#define FLAGS_RESERVED		32
-
-#else
-
-#error BITS_PER_LONG not defined
-
-#endif
-
 #if !defined(CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID) && \
 	!defined(CONFIG_ARCH_POPULATES_NODE_MAP)
 #define early_pfn_to_nid(nid)  (0UL)
Index: linux-2.6/include/linux/page-flags.h
===================================================================
--- linux-2.6.orig/include/linux/page-flags.h	2008-02-29 19:20:11.000000000 -0800
+++ linux-2.6/include/linux/page-flags.h	2008-02-29 19:29:53.000000000 -0800
@@ -7,6 +7,7 @@
 
 #include <linux/types.h>
 #include <linux/mm_types.h>
+#include <linux/bounds.h>
 
 /*
  * Various page->flags bits:
@@ -59,13 +60,12 @@
  * extends from the high bits downwards.
  *
  *  | FIELD | ... | FLAGS |
- *  N-1     ^             0
- *          (N-FLAGS_RESERVED)
+ *  N-1           ^       0
+ *               (NR_PAGEFLAGS)
  *
- * The fields area is reserved for fields mapping zone, node and SPARSEMEM
- * section.  The boundry between these two areas is defined by
- * FLAGS_RESERVED which defines the width of the fields section
- * (see linux/mmzone.h).  New flags must _not_ overlap with this area.
+ * The fields area is reserved for fields mapping zone, node (for NUMA) and
+ * SPARSEMEM section (for variants of SPARSEMEM that require section ids like
+ * SPARSEMEM_EXTREME with !SPARSEMEM_VMEMMAP).
  */
 enum pageflags {
 	PG_locked,		/* Page is locked. Don't touch. */
@@ -86,7 +86,6 @@ enum pageflags {
 	PG_mappedtodisk,	/* Has blocks allocated on-disk */
 	PG_reclaim,		/* To be reclaimed asap */
 	PG_buddy,		/* Page is free, on buddy lists */
-	NR_PAGEFLAGS,		/* For verification purposes */
 
 #if (BITS_PER_LONG > 32)
 /*
@@ -98,6 +97,7 @@ enum pageflags {
  */
 	PG_uncached = 31,		/* Page has been mapped as uncached */
 #endif
+	__NR_PAGEFLAGS,
 };
 
 /*
Index: linux-2.6/kernel/bounds.c
===================================================================
--- linux-2.6.orig/kernel/bounds.c	2008-02-29 19:29:38.000000000 -0800
+++ linux-2.6/kernel/bounds.c	2008-02-29 19:29:53.000000000 -0800
@@ -13,4 +13,5 @@
 
 void foo(void)
 {
+	DEFINE(NR_PAGEFLAGS, __NR_PAGEFLAGS);
 }
Index: linux-2.6/include/linux/bounds.h
===================================================================
--- linux-2.6.orig/include/linux/bounds.h	2008-02-29 19:30:04.000000000 -0800
+++ linux-2.6/include/linux/bounds.h	2008-02-29 19:30:08.000000000 -0800
@@ -7,4 +7,6 @@
  *
  */
 
+#define NR_PAGEFLAGS 32 /* __NR_PAGEFLAGS	# */
+
 #endif

-- 

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [rfc 08/10] Export NR_MAX_ZONES to the preprocessor
  2008-03-01  4:05 [rfc 00/10] [RFC] Page flags: Saving some, making handling easier etc Christoph Lameter
                   ` (6 preceding siblings ...)
  2008-03-01  4:05 ` [rfc 07/10] Pageflags: Get rid of FLAGS_RESERVED Christoph Lameter
@ 2008-03-01  4:05 ` Christoph Lameter
  2008-03-01  4:05 ` [rfc 09/10] Get rid of __ZONE_COUNT Christoph Lameter
  2008-03-01  4:05 ` [rfc 10/10] Pageflags land grab Christoph Lameter
  9 siblings, 0 replies; 19+ messages in thread
From: Christoph Lameter @ 2008-03-01  4:05 UTC (permalink / raw)
  To: linux-kernel
  Cc: Mel Gorman, Nick Piggin, Rik van Riel, Andrew Morton, apw, linux-mm

[-- Attachment #1: bounds_nr_max_zones --]
[-- Type: text/plain, Size: 1559 bytes --]

Signed-off-by: Christoph Lameter <clameter@sgi.com>

---
 include/linux/bounds.h |    1 +
 include/linux/mmzone.h |    3 ++-
 kernel/bounds.c        |    1 +
 3 files changed, 4 insertions(+), 1 deletion(-)

Index: linux-2.6/include/linux/mmzone.h
===================================================================
--- linux-2.6.orig/include/linux/mmzone.h	2008-02-29 18:18:19.000000000 -0800
+++ linux-2.6/include/linux/mmzone.h	2008-02-29 18:20:30.000000000 -0800
@@ -17,6 +17,7 @@
 #include <linux/pageblock-flags.h>
 #include <asm/atomic.h>
 #include <asm/page.h>
+#include <linux/bounds.h>
 
 /* Free memory management - zoned buddy allocator.  */
 #ifndef CONFIG_FORCE_MAX_ZONEORDER
@@ -177,7 +178,7 @@ enum zone_type {
 	ZONE_HIGHMEM,
 #endif
 	ZONE_MOVABLE,
-	MAX_NR_ZONES
+	__MAX_NR_ZONES
 };
 
 /*
Index: linux-2.6/kernel/bounds.c
===================================================================
--- linux-2.6.orig/kernel/bounds.c	2008-02-29 18:18:19.000000000 -0800
+++ linux-2.6/kernel/bounds.c	2008-02-29 18:18:53.000000000 -0800
@@ -14,4 +14,5 @@
 void foo(void)
 {
 	DEFINE(NR_PAGEFLAGS, __NR_PAGEFLAGS);
+	DEFINE(MAX_NR_ZONES, __MAX_NR_ZONES);
 }
Index: linux-2.6/include/linux/bounds.h
===================================================================
--- linux-2.6.orig/include/linux/bounds.h	2008-02-29 18:18:19.000000000 -0800
+++ linux-2.6/include/linux/bounds.h	2008-02-29 18:20:32.000000000 -0800
@@ -8,5 +8,6 @@
  */
 
 #define NR_PAGEFLAGS 32 /* __NR_PAGEFLAGS	# */
+#define MAX_NR_ZONES 4 /* __MAX_NR_ZONES	# */
 
 #endif

-- 

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [rfc 09/10] Get rid of __ZONE_COUNT
  2008-03-01  4:05 [rfc 00/10] [RFC] Page flags: Saving some, making handling easier etc Christoph Lameter
                   ` (7 preceding siblings ...)
  2008-03-01  4:05 ` [rfc 08/10] Export NR_MAX_ZONES to the preprocessor Christoph Lameter
@ 2008-03-01  4:05 ` Christoph Lameter
  2008-03-01  4:05 ` [rfc 10/10] Pageflags land grab Christoph Lameter
  9 siblings, 0 replies; 19+ messages in thread
From: Christoph Lameter @ 2008-03-01  4:05 UTC (permalink / raw)
  To: linux-kernel
  Cc: Mel Gorman, Nick Piggin, Rik van Riel, Andrew Morton, apw, linux-mm

[-- Attachment #1: max_zones_get_rid_of___zone_count --]
[-- Type: text/plain, Size: 1378 bytes --]

It was used to compensate because MAX_NR_ZONES was not available
to the #ifdefs.

Signed-off-by: Christoph Lameter <clameter@sgi.com>

---
 include/linux/mmzone.h |   19 +++----------------
 1 file changed, 3 insertions(+), 16 deletions(-)

Index: linux-2.6/include/linux/mmzone.h
===================================================================
--- linux-2.6.orig/include/linux/mmzone.h	2008-02-29 19:34:28.000000000 -0800
+++ linux-2.6/include/linux/mmzone.h	2008-02-29 19:35:32.000000000 -0800
@@ -189,28 +189,15 @@ enum zone_type {
  * match the requested limits. See gfp_zone() in include/linux/gfp.h
  */
 
-/*
- * Count the active zones.  Note that the use of defined(X) outside
- * #if and family is not necessarily defined so ensure we cannot use
- * it later.  Use __ZONE_COUNT to work out how many shift bits we need.
- */
-#define __ZONE_COUNT (			\
-	  defined(CONFIG_ZONE_DMA)	\
-	+ defined(CONFIG_ZONE_DMA32)	\
-	+ 1				\
-	+ defined(CONFIG_HIGHMEM)	\
-	+ 1				\
-)
-#if __ZONE_COUNT < 2
+#if MAX_NR_ZONES < 2
 #define ZONES_SHIFT 0
-#elif __ZONE_COUNT <= 2
+#elif MAX_NR_ZONES <= 2
 #define ZONES_SHIFT 1
-#elif __ZONE_COUNT <= 4
+#elif MAX_NR_ZONES <= 4
 #define ZONES_SHIFT 2
 #else
 #error ZONES_SHIFT -- too many zones configured adjust calculation
 #endif
-#undef __ZONE_COUNT
 
 struct zone {
 	/* Fields commonly accessed by the page allocator */

-- 

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [rfc 10/10] Pageflags land grab
  2008-03-01  4:05 [rfc 00/10] [RFC] Page flags: Saving some, making handling easier etc Christoph Lameter
                   ` (8 preceding siblings ...)
  2008-03-01  4:05 ` [rfc 09/10] Get rid of __ZONE_COUNT Christoph Lameter
@ 2008-03-01  4:05 ` Christoph Lameter
  2008-03-01 17:21   ` Rik van Riel
  9 siblings, 1 reply; 19+ messages in thread
From: Christoph Lameter @ 2008-03-01  4:05 UTC (permalink / raw)
  To: linux-kernel
  Cc: Mel Gorman, Nick Piggin, Rik van Riel, Andrew Morton, apw, linux-mm

[-- Attachment #1: pageflags_land_grab --]
[-- Type: text/plain, Size: 3811 bytes --]

We have enough page flags after vmemmap no longer uses section ids.

Reserve 5 of the 6 saved flags for functionality that is currently
under development in the VM.

The new flags are only available if either of these conditions are met:

1. 64 Bit system. (then we have 8 more free of the 32)

2. !NUMA. In that case 2 bits are needed for the zone
   id which leaves 30 page flag bits. Of those we use 24. 6 left.

3. !SPARSEMEM. In that case we use 5 bits of the 30 available
   for the node. 1 leftover.

4. SPARSEMEM_VMEMMAP. Case 3 applies.

The remaining case is classic sparsemem with NUMA on a 32 bit platform.
In that case we need to use additional bits from the remaining 25 which
does not allow the use of all 5 extended page flags.

We could deal with that case by only allowing sparsemem vmemmap (if
sparsemem is selected as a model) on 32 bit NUMA platforms.

Signed-off-by: Christoph Lameter <clameter@sgi.com>

---
 include/linux/page-flags.h |   32 +++++++++++++++++++++++++++++---
 mm/Kconfig                 |   11 +++++++++++
 2 files changed, 40 insertions(+), 3 deletions(-)

Index: linux-2.6/include/linux/page-flags.h
===================================================================
--- linux-2.6.orig/include/linux/page-flags.h	2008-02-29 19:33:01.000000000 -0800
+++ linux-2.6/include/linux/page-flags.h	2008-02-29 19:37:31.000000000 -0800
@@ -81,11 +81,24 @@ enum pageflags {
 	PG_reserved,
 	PG_private,		/* If pagecache, has fs-private data */
 	PG_writeback,		/* Page is under writeback */
-	PG_compound,		/* A compound page */
 	PG_swapcache,		/* Swap page: swp_entry_t in private */
 	PG_mappedtodisk,	/* Has blocks allocated on-disk */
 	PG_reclaim,		/* To be reclaimed asap */
 	PG_buddy,		/* Page is free, on buddy lists */
+#ifdef CONFIG_EXTENDED_PAGEFLAGS
+	/*
+	 * Page flags that are only available without sparsemem on 32 bit
+	 * (sparsemem vmemmap is ok. Flags are always available on 64 bit.
+	 */
+	PG_mlock,		/* Page cannot be swapped out */
+	PG_pin,			/* Page cannot be moved in memory */
+	PG_tail,		/* Tail of a compound page */
+	PG_head,		/* Head of a compound page */
+	PG_vcompound,		/* Compound page is virtually mapped */
+	PG_filebacked,		/* Page is backed by an actual disk (not RAM) */
+#else
+	PG_compound,		/* A compound page */
+#endif
 
 #if (BITS_PER_LONG > 32)
 /*
@@ -245,8 +258,20 @@ static inline void set_page_writeback(st
 	test_set_page_writeback(page);
 }
 
-TESTPAGEFLAG(Compound, compound)
-__PAGEFLAG(Head, compound)
+#ifdef CONFIG_EXTENDED_PAGEFLAGS
+__PAGEFLAG(Head, head)
+__PAGEFLAG(Tail, tail)
+__PAGEFLAG(Vcompound, vcompound)
+__PAGEFLAG(Mlock, mlock)
+__PAGEFLAG(Pin, pin)
+__PAGEFLAG(FileBacked, filebacked)
+
+static inline int PageCompound(struct page *page)
+{
+	return (page->flags & ((1 << PG_tail) | (1 << PG_head))) != 0;
+}
+
+#else
 
 /*
  * PG_reclaim is used in combination with PG_compound to mark the
@@ -274,5 +299,6 @@ static inline void __ClearPageTail(struc
 {
 	page->flags &= ~PG_head_tail_mask;
 }
+#endif
 
 #endif	/* PAGE_FLAGS_H */
Index: linux-2.6/mm/Kconfig
===================================================================
--- linux-2.6.orig/mm/Kconfig	2008-02-29 19:13:55.000000000 -0800
+++ linux-2.6/mm/Kconfig	2008-02-29 19:37:31.000000000 -0800
@@ -193,3 +193,14 @@ config NR_QUICK
 config VIRT_TO_BUS
 	def_bool y
 	depends on !ARCH_NO_VIRT_TO_BUS
+
+#
+# I wish we could get rid of this...... The main problem is the page
+# flag use on 32 bit system with NUMA and SPARSEMEM (no sparsemem_vmemmap).
+# Does not really make any sense to use sparsemem there since 32 bit spaces
+# will typically be backed by contiguous RAM these days. So there is nothing
+# sparse there anymore.
+#
+config EXTENDED_PAGEFLAGS
+	def_bool y
+	depends on 64BIT || !SPARSEMEM || !NUMA || SPARSEMEM_VMEMMAP

-- 

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [rfc 07/10] Pageflags: Get rid of FLAGS_RESERVED
  2008-03-01  4:05 ` [rfc 07/10] Pageflags: Get rid of FLAGS_RESERVED Christoph Lameter
@ 2008-03-01 16:26   ` Rik van Riel
  2008-03-03 17:57     ` Christoph Lameter
  0 siblings, 1 reply; 19+ messages in thread
From: Rik van Riel @ 2008-03-01 16:26 UTC (permalink / raw)
  To: Christoph Lameter
  Cc: linux-kernel, Mel Gorman, Nick Piggin, Andrew Morton, apw, linux-mm

On Fri, 29 Feb 2008 20:05:41 -0800
Christoph Lameter <clameter@sgi.com> wrote:

> Index: linux-2.6/include/linux/bounds.h
> ===================================================================
> --- linux-2.6.orig/include/linux/bounds.h	2008-02-29 19:30:04.000000000 -0800
> +++ linux-2.6/include/linux/bounds.h	2008-02-29 19:30:08.000000000 -0800
> @@ -7,4 +7,6 @@
>   *
>   */
>  
> +#define NR_PAGEFLAGS 32 /* __NR_PAGEFLAGS	# */
> +
>  #endif

Did part of your automatically generated file just leak into the patch
series?

-- 
All rights reversed.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [rfc 10/10] Pageflags land grab
  2008-03-01  4:05 ` [rfc 10/10] Pageflags land grab Christoph Lameter
@ 2008-03-01 17:21   ` Rik van Riel
  0 siblings, 0 replies; 19+ messages in thread
From: Rik van Riel @ 2008-03-01 17:21 UTC (permalink / raw)
  To: Christoph Lameter
  Cc: linux-kernel, Mel Gorman, Nick Piggin, Andrew Morton, apw, linux-mm

On Fri, 29 Feb 2008 20:05:44 -0800
Christoph Lameter <clameter@sgi.com> wrote:

> We have enough page flags after vmemmap no longer uses section ids.
> 
> Reserve 5 of the 6 saved flags for functionality that is currently
> under development in the VM.
> 
> The new flags are only available if either of these conditions are met:
> 
> 1. 64 Bit system. (then we have 8 more free of the 32)
> 
> 2. !NUMA. In that case 2 bits are needed for the zone
>    id which leaves 30 page flag bits. Of those we use 24. 6 left.
> 
> 3. !SPARSEMEM. In that case we use 5 bits of the 30 available
>    for the node. 1 leftover.
> 
> 4. SPARSEMEM_VMEMMAP. Case 3 applies.

Nice!  I like your patch series.

-- 
All rights reversed.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [rfc 01/10] Pageflags: Use an enum for the flags
  2008-03-01  4:05 ` [rfc 01/10] Pageflags: Use an enum for the flags Christoph Lameter
@ 2008-03-03 10:09   ` Mel Gorman
  0 siblings, 0 replies; 19+ messages in thread
From: Mel Gorman @ 2008-03-03 10:09 UTC (permalink / raw)
  To: Christoph Lameter
  Cc: linux-kernel, Nick Piggin, Rik van Riel, Andrew Morton, apw, linux-mm

On (29/02/08 20:05), Christoph Lameter didst pronounce:
> Use an enum to ease the maintenance of page flags. This is going to change the
> numbering from 0 to 18.
> 
> Signed-off-by: Christoph Lameter <clameter@sgi.com>
> 
> ---
>  include/linux/page-flags.h |   54 ++++++++++++++++++++-------------------------
>  1 file changed, 24 insertions(+), 30 deletions(-)
> 
> Index: linux-2.6/include/linux/page-flags.h
> ===================================================================
> --- linux-2.6.orig/include/linux/page-flags.h	2008-02-29 14:54:22.000000000 -0800
> +++ linux-2.6/include/linux/page-flags.h	2008-02-29 15:00:00.000000000 -0800
> @@ -67,35 +67,28 @@
>   * FLAGS_RESERVED which defines the width of the fields section
>   * (see linux/mmzone.h).  New flags must _not_ overlap with this area.
>   */
> -#define PG_locked	 	 0	/* Page is locked. Don't touch. */
> -#define PG_error		 1
> -#define PG_referenced		 2
> -#define PG_uptodate		 3
> -
> -#define PG_dirty	 	 4
> -#define PG_lru			 5
> -#define PG_active		 6
> -#define PG_slab			 7	/* slab debug (Suparna wants this) */
> -
> -#define PG_owner_priv_1		 8	/* Owner use. If pagecache, fs may use*/
> -#define PG_arch_1		 9
> -#define PG_reserved		10
> -#define PG_private		11	/* If pagecache, has fs-private data */
> -
> -#define PG_writeback		12	/* Page is under writeback */
> -#define PG_compound		14	/* Part of a compound page */
> -#define PG_swapcache		15	/* Swap page: swp_entry_t in private */
> -
> -#define PG_mappedtodisk		16	/* Has blocks allocated on-disk */
> -#define PG_reclaim		17	/* To be reclaimed asap */
> -#define PG_buddy		19	/* Page is free, on buddy lists */
> -
> -/* PG_readahead is only used for file reads; PG_reclaim is only for writes */
> -#define PG_readahead		PG_reclaim /* Reminder to do async read-ahead */
> -
> -/* PG_owner_priv_1 users should have descriptive aliases */
> -#define PG_checked		PG_owner_priv_1 /* Used by some filesystems */
> -#define PG_pinned		PG_owner_priv_1	/* Xen pinned pagetable */

These two verbose descriptions appear to go missing in the enum below.
It probably is intentional because they are aliases but you can preseve them
being aliases with

PG_checked = PG_owner_priv_1,
PG_pinned = PG_owner_priv_1,

That would keep the comments about flags in one place. I note that you
move the comment to the macro definitions in a later patch but maybe having
comments about some flags in multiple places is not very desirable?

> +enum pageflags {
> +	PG_locked,		/* Page is locked. Don't touch. */
> +	PG_error,
> +	PG_referenced,
> +	PG_uptodate,
> +	PG_dirty,
> +	PG_lru,
> +	PG_active,
> +	PG_slab,
> +	PG_owner_priv_1,	/* Owner use. If pagecache, fs may use*/
> +	PG_arch_1,
> +	PG_reserved,
> +	PG_private,		/* If pagecache, has fs-private data */
> +	PG_writeback,		/* Page is under writeback */
> +	PG_compound,		/* A compound page */
> +	PG_swapcache,		/* Swap page: swp_entry_t in private */
> +	PG_mappedtodisk,	/* Has blocks allocated on-disk */
> +	PG_reclaim,		/* To be reclaimed asap */
> +	/* PG_readahead is only used for file reads; PG_reclaim is only for writes */
> +	PG_readahead = PG_reclaim, /* Reminder to do async read-ahead */
> +	PG_buddy,		/* Page is free, on buddy lists */
> +	NR_PAGEFLAGS,		/* For verification purposes */
>  
>  #if (BITS_PER_LONG > 32)
>  /*
> @@ -105,8 +98,9 @@
>   * 64 bit  |           FIELDS             | ??????         FLAGS         |
>   *         63                            32                              0
>   */
> -#define PG_uncached		31	/* Page has been mapped as uncached */
> +	PG_uncached = 31,		/* Page has been mapped as uncached */
>  #endif
> +};
>  
>  /*
>   * Manipulation of page state flags
> 
> -- 
> 

-- 
Mel Gorman
Part-time Phd Student                          Linux Technology Center
University of Limerick                         IBM Dublin Software Lab

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [rfc 03/10] Pageflags: Convert to the use of new macros
  2008-03-01  4:05 ` [rfc 03/10] Pageflags: Convert to the use of new macros Christoph Lameter
@ 2008-03-03 10:24   ` Mel Gorman
  2008-03-03 18:03     ` Christoph Lameter
  0 siblings, 1 reply; 19+ messages in thread
From: Mel Gorman @ 2008-03-03 10:24 UTC (permalink / raw)
  To: Christoph Lameter
  Cc: linux-kernel, Nick Piggin, Rik van Riel, Andrew Morton, apw, linux-mm

On (29/02/08 20:05), Christoph Lameter didst pronounce:
> Replace explicit definitions of page flags through the use of macros.
> Significantly reduces the size of the definitions and removes a lot of
> opportunity for errors. Additonal page flags can typically be generated
> with a single line.
> 
> Signed-off-by: Christoph Lameter <clameter@sgi.com>
> 
> ---
>  include/linux/page-flags.h |  188 ++++++++++++++-------------------------------
>  1 file changed, 61 insertions(+), 127 deletions(-)
> 
> Index: linux-2.6/include/linux/page-flags.h
> ===================================================================
> --- linux-2.6.orig/include/linux/page-flags.h	2008-02-29 19:15:28.000000000 -0800
> +++ linux-2.6/include/linux/page-flags.h	2008-02-29 19:20:03.000000000 -0800
> @@ -143,28 +143,51 @@ static inline int TestClearPage##uname(s
>  #define TESTSCFLAG(uname, lname)					\
>  			TESTSETFLAG(uname, lname) TESTCLEARFLAG(uname, lname)
>  
> +struct page;	/* forward declaration */
> +
> +PAGEFLAG(Locked, locked) TESTSCFLAG(Locked, locked)
> +PAGEFLAG(Error, error)
> +PAGEFLAG(Referenced, referenced) TESTCLEARFLAG(Referenced, referenced)
> +PAGEFLAG(Dirty, dirty) TESTSCFLAG(Dirty, dirty) __CLEARPAGEFLAG(Dirty, dirty)
> +PAGEFLAG(LRU, lru) __CLEARPAGEFLAG(LRU, lru)
> +PAGEFLAG(Active, active) __CLEARPAGEFLAG(Active, active)
> +__PAGEFLAG(Slab, slab)
> +PAGEFLAG(Checked, owner_priv_1)		/* Used by some filesystems */
> +PAGEFLAG(Pinned, owner_priv_1)		/* Xen pinned pagetable */

This is what I was on about earlier with some flag comments being in a
separate place. Someone grepping for PG_pinned to see what it is for
would have a bad day.

> +PAGEFLAG(Reserved, reserved) __CLEARPAGEFLAG(Reserved, reserved)
> +PAGEFLAG(Private, private) __CLEARPAGEFLAG(Private, private)
> +	__SETPAGEFLAG(Private, private)
> +
>  /*
> - * Manipulation of page state flags
> + * Only test-and-set exist for PG_writeback.  The unconditional operators are
> + * risky: they bypass page accounting.
>   */
> -#define PageLocked(page)		\
> -		test_bit(PG_locked, &(page)->flags)
> -#define SetPageLocked(page)		\
> -		set_bit(PG_locked, &(page)->flags)
> -#define TestSetPageLocked(page)		\
> -		test_and_set_bit(PG_locked, &(page)->flags)
> -#define ClearPageLocked(page)		\
> -		clear_bit(PG_locked, &(page)->flags)
> -#define TestClearPageLocked(page)	\
> -		test_and_clear_bit(PG_locked, &(page)->flags)
> -
> -#define PageError(page)		test_bit(PG_error, &(page)->flags)
> -#define SetPageError(page)	set_bit(PG_error, &(page)->flags)
> -#define ClearPageError(page)	clear_bit(PG_error, &(page)->flags)
> -
> -#define PageReferenced(page)	test_bit(PG_referenced, &(page)->flags)
> -#define SetPageReferenced(page)	set_bit(PG_referenced, &(page)->flags)
> -#define ClearPageReferenced(page)	clear_bit(PG_referenced, &(page)->flags)
> -#define TestClearPageReferenced(page) test_and_clear_bit(PG_referenced, &(page)->flags)
> +TESTPAGEFLAG(Writeback, writeback) TESTSCFLAG(Writeback, writeback)
> +__PAGEFLAG(Buddy, buddy)
> +PAGEFLAG(MappedToDisk, mappedtodisk)
> +
> +/* PG_readahead is only used for file reads; PG_reclaim is only for writes */
> +PAGEFLAG(Reclaim, reclaim) TESTCLEARFLAG(Reclaim, reclaim)
> +PAGEFLAG(Readahead, readahead)		/* Reminder to do async read-ahead */
> +
> +#ifdef CONFIG_HIGHMEM
> +#define PageHighMem(page)	is_highmem(page_zone(page))
> +#else
> +#define PageHighMem(page)	0 /* needed to optimize away at compile time */
> +#endif
> +

Seems to be a tiny inconsistency here. PageSwapCache below is a static
inline returning 0 that you fixed up as part of the shuffling where as
PageHighMem is #defined to 0. Care to fix it up too?

> +#ifdef CONFIG_SWAP
> +PAGEFLAG(SwapCache, swapcache)
> +#else
> +static inline int PageSwapCache(struct page *page)
> +{
> +	return 0;
> +}
> +#endif
> +
> +#if (BITS_PER_LONG > 32)
> +PAGEFLAG(Uncached, uncached)
> +#endif
>  
>  static inline int PageUptodate(struct page *page)
>  {
> @@ -212,97 +235,37 @@ static inline void SetPageUptodate(struc
>  #endif
>  }
>  
> -#define ClearPageUptodate(page)	clear_bit(PG_uptodate, &(page)->flags)
> +CLEARPAGEFLAG(Uptodate, uptodate)
>  
> -#define PageDirty(page)		test_bit(PG_dirty, &(page)->flags)
> -#define SetPageDirty(page)	set_bit(PG_dirty, &(page)->flags)
> -#define TestSetPageDirty(page)	test_and_set_bit(PG_dirty, &(page)->flags)
> -#define ClearPageDirty(page)	clear_bit(PG_dirty, &(page)->flags)
> -#define __ClearPageDirty(page)	__clear_bit(PG_dirty, &(page)->flags)
> -#define TestClearPageDirty(page) test_and_clear_bit(PG_dirty, &(page)->flags)
> -
> -#define PageLRU(page)		test_bit(PG_lru, &(page)->flags)
> -#define SetPageLRU(page)	set_bit(PG_lru, &(page)->flags)
> -#define ClearPageLRU(page)	clear_bit(PG_lru, &(page)->flags)
> -#define __ClearPageLRU(page)	__clear_bit(PG_lru, &(page)->flags)
> -
> -#define PageActive(page)	test_bit(PG_active, &(page)->flags)
> -#define SetPageActive(page)	set_bit(PG_active, &(page)->flags)
> -#define ClearPageActive(page)	clear_bit(PG_active, &(page)->flags)
> -#define __ClearPageActive(page)	__clear_bit(PG_active, &(page)->flags)
> -
> -#define PageSlab(page)		test_bit(PG_slab, &(page)->flags)
> -#define __SetPageSlab(page)	__set_bit(PG_slab, &(page)->flags)
> -#define __ClearPageSlab(page)	__clear_bit(PG_slab, &(page)->flags)
> +extern void cancel_dirty_page(struct page *page, unsigned int account_size);
>  
> -#ifdef CONFIG_HIGHMEM
> -#define PageHighMem(page)	is_highmem(page_zone(page))
> -#else
> -#define PageHighMem(page)	0 /* needed to optimize away at compile time */
> -#endif
> +int test_clear_page_writeback(struct page *page);
> +int test_set_page_writeback(struct page *page);
>  
> -#define PageChecked(page)	test_bit(PG_checked, &(page)->flags)
> -#define SetPageChecked(page)	set_bit(PG_checked, &(page)->flags)
> -#define ClearPageChecked(page)	clear_bit(PG_checked, &(page)->flags)
> -
> -#define PagePinned(page)	test_bit(PG_pinned, &(page)->flags)
> -#define SetPagePinned(page)	set_bit(PG_pinned, &(page)->flags)
> -#define ClearPagePinned(page)	clear_bit(PG_pinned, &(page)->flags)
> -
> -#define PageReserved(page)	test_bit(PG_reserved, &(page)->flags)
> -#define SetPageReserved(page)	set_bit(PG_reserved, &(page)->flags)
> -#define ClearPageReserved(page)	clear_bit(PG_reserved, &(page)->flags)
> -#define __ClearPageReserved(page)	__clear_bit(PG_reserved, &(page)->flags)
> -
> -#define SetPagePrivate(page)	set_bit(PG_private, &(page)->flags)
> -#define ClearPagePrivate(page)	clear_bit(PG_private, &(page)->flags)
> -#define PagePrivate(page)	test_bit(PG_private, &(page)->flags)
> -#define __SetPagePrivate(page)  __set_bit(PG_private, &(page)->flags)
> -#define __ClearPagePrivate(page) __clear_bit(PG_private, &(page)->flags)
> +static inline void set_page_writeback(struct page *page)
> +{
> +	test_set_page_writeback(page);
> +}

It's been around for ages and unrelated to your patch series but it
looks odd that set_page_writeback() is simply a function alias that
ignores return values :/

>  
> -/*
> - * Only test-and-set exist for PG_writeback.  The unconditional operators are
> - * risky: they bypass page accounting.
> - */
> -#define PageWriteback(page)	test_bit(PG_writeback, &(page)->flags)
> -#define TestSetPageWriteback(page) test_and_set_bit(PG_writeback,	\
> -							&(page)->flags)
> -#define TestClearPageWriteback(page) test_and_clear_bit(PG_writeback,	\
> -							&(page)->flags)
> -
> -#define PageBuddy(page)		test_bit(PG_buddy, &(page)->flags)
> -#define __SetPageBuddy(page)	__set_bit(PG_buddy, &(page)->flags)
> -#define __ClearPageBuddy(page)	__clear_bit(PG_buddy, &(page)->flags)
> -
> -#define PageMappedToDisk(page)	test_bit(PG_mappedtodisk, &(page)->flags)
> -#define SetPageMappedToDisk(page) set_bit(PG_mappedtodisk, &(page)->flags)
> -#define ClearPageMappedToDisk(page) clear_bit(PG_mappedtodisk, &(page)->flags)
> -
> -#define PageReadahead(page)	test_bit(PG_readahead, &(page)->flags)
> -#define SetPageReadahead(page)	set_bit(PG_readahead, &(page)->flags)
> -#define ClearPageReadahead(page) clear_bit(PG_readahead, &(page)->flags)
> -
> -#define PageReclaim(page)	test_bit(PG_reclaim, &(page)->flags)
> -#define SetPageReclaim(page)	set_bit(PG_reclaim, &(page)->flags)
> -#define ClearPageReclaim(page)	clear_bit(PG_reclaim, &(page)->flags)
> -#define TestClearPageReclaim(page) test_and_clear_bit(PG_reclaim, &(page)->flags)
> -
> -#define PageCompound(page)	test_bit(PG_compound, &(page)->flags)
> -#define __SetPageCompound(page)	__set_bit(PG_compound, &(page)->flags)
> -#define __ClearPageCompound(page) __clear_bit(PG_compound, &(page)->flags)
> +TESTPAGEFLAG(Compound, compound)
> +__PAGEFLAG(Head, compound)
>  
>  /*
>   * PG_reclaim is used in combination with PG_compound to mark the
> - * head and tail of a compound page
> + * head and tail of a compound page. This saves one page flag
> + * but makes it impossible to use compound pages for the page cache.
> + * The PG_reclaim bit would have to be used for reclaim or readahead
> + * if compound pages enter the page cache.
>   *
>   * PG_compound & PG_reclaim	=> Tail page
>   * PG_compound & ~PG_reclaim	=> Head page
>   */
> -
>  #define PG_head_tail_mask ((1L << PG_compound) | (1L << PG_reclaim))
>  
> -#define PageTail(page)	(((page)->flags & PG_head_tail_mask)	\
> -				== PG_head_tail_mask)
> +static inline int PageTail(struct page *page)
> +{
> +	return ((page->flags & PG_head_tail_mask) == PG_head_tail_mask);
> +}
>  
>  static inline void __SetPageTail(struct page *page)
>  {
> @@ -314,33 +277,4 @@ static inline void __ClearPageTail(struc
>  	page->flags &= ~PG_head_tail_mask;
>  }
>  
> -#define PageHead(page)	(((page)->flags & PG_head_tail_mask)	\
> -				== (1L << PG_compound))
> -#define __SetPageHead(page)	__SetPageCompound(page)
> -#define __ClearPageHead(page)	__ClearPageCompound(page)
> -
> -#ifdef CONFIG_SWAP
> -#define PageSwapCache(page)	test_bit(PG_swapcache, &(page)->flags)
> -#define SetPageSwapCache(page)	set_bit(PG_swapcache, &(page)->flags)
> -#define ClearPageSwapCache(page) clear_bit(PG_swapcache, &(page)->flags)
> -#else
> -#define PageSwapCache(page)	0
> -#endif
> -
> -#define PageUncached(page)	test_bit(PG_uncached, &(page)->flags)
> -#define SetPageUncached(page)	set_bit(PG_uncached, &(page)->flags)
> -#define ClearPageUncached(page)	clear_bit(PG_uncached, &(page)->flags)
> -
> -struct page;	/* forward declaration */
> -
> -extern void cancel_dirty_page(struct page *page, unsigned int account_size);
> -
> -int test_clear_page_writeback(struct page *page);
> -int test_set_page_writeback(struct page *page);
> -
> -static inline void set_page_writeback(struct page *page)
> -{
> -	test_set_page_writeback(page);
> -}
> -
>  #endif	/* PAGE_FLAGS_H */
> 
> -- 
> 

-- 
Mel Gorman
Part-time Phd Student                          Linux Technology Center
University of Limerick                         IBM Dublin Software Lab

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [rfc 07/10] Pageflags: Get rid of FLAGS_RESERVED
  2008-03-01 16:26   ` Rik van Riel
@ 2008-03-03 17:57     ` Christoph Lameter
  0 siblings, 0 replies; 19+ messages in thread
From: Christoph Lameter @ 2008-03-03 17:57 UTC (permalink / raw)
  To: Rik van Riel
  Cc: linux-kernel, Mel Gorman, Nick Piggin, Andrew Morton, apw, linux-mm

On Sat, 1 Mar 2008, Rik van Riel wrote:

> Did part of your automatically generated file just leak into the patch
> series?

Some setting is necessary for kernel/bounds.c to compile. Value will be 
updated with the current value.


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [rfc 03/10] Pageflags: Convert to the use of new macros
  2008-03-03 10:24   ` Mel Gorman
@ 2008-03-03 18:03     ` Christoph Lameter
  2008-03-07 11:13       ` Mel Gorman
  0 siblings, 1 reply; 19+ messages in thread
From: Christoph Lameter @ 2008-03-03 18:03 UTC (permalink / raw)
  To: Mel Gorman
  Cc: linux-kernel, Nick Piggin, Rik van Riel, Andrew Morton, apw, linux-mm

On Mon, 3 Mar 2008, Mel Gorman wrote:

> > +PAGEFLAG(Checked, owner_priv_1)		/* Used by some filesystems */
> > +PAGEFLAG(Pinned, owner_priv_1)		/* Xen pinned pagetable */
> 
> This is what I was on about earlier with some flag comments being in a
> separate place. Someone grepping for PG_pinned to see what it is for
> would have a bad day.

These aliases seem to be not a good thing. PG_pinned etc are never used. 
Greeping for SetPagePinned etc may be better.

> > +#ifdef CONFIG_HIGHMEM
> > +#define PageHighMem(page)	is_highmem(page_zone(page))
> > +#else
> > +#define PageHighMem(page)	0 /* needed to optimize away at compile time */
> > +#endif
> > +
> 
> Seems to be a tiny inconsistency here. PageSwapCache below is a static
> inline returning 0 that you fixed up as part of the shuffling where as
> PageHighMem is #defined to 0. Care to fix it up too?

Ok.

> > -#define SetPagePrivate(page)	set_bit(PG_private, &(page)->flags)
> > -#define ClearPagePrivate(page)	clear_bit(PG_private, &(page)->flags)
> > -#define PagePrivate(page)	test_bit(PG_private, &(page)->flags)
> > -#define __SetPagePrivate(page)  __set_bit(PG_private, &(page)->flags)
> > -#define __ClearPagePrivate(page) __clear_bit(PG_private, &(page)->flags)
> > +static inline void set_page_writeback(struct page *page)
> > +{
> > +	test_set_page_writeback(page);
> > +}
> 
> It's been around for ages and unrelated to your patch series but it
> looks odd that set_page_writeback() is simply a function alias that
> ignores return values :/

Yes its strange. Is there a set_page_writeback function?

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [rfc 03/10] Pageflags: Convert to the use of new macros
  2008-03-03 18:03     ` Christoph Lameter
@ 2008-03-07 11:13       ` Mel Gorman
  0 siblings, 0 replies; 19+ messages in thread
From: Mel Gorman @ 2008-03-07 11:13 UTC (permalink / raw)
  To: Christoph Lameter
  Cc: linux-kernel, Nick Piggin, Rik van Riel, Andrew Morton, apw, linux-mm

On (03/03/08 10:03), Christoph Lameter didst pronounce:
> On Mon, 3 Mar 2008, Mel Gorman wrote:
> 
> > > +PAGEFLAG(Checked, owner_priv_1)		/* Used by some filesystems */
> > > +PAGEFLAG(Pinned, owner_priv_1)		/* Xen pinned pagetable */
> > 
> > This is what I was on about earlier with some flag comments being in a
> > separate place. Someone grepping for PG_pinned to see what it is for
> > would have a bad day.
> 
> These aliases seem to be not a good thing. PG_pinned etc are never used. 
> Greeping for SetPagePinned etc may be better.
> 

I guess it's a question of taste. I would prefer all the flags that
exist to be named in the one place so all the comments are there.
However, functionally it's identical no harm.

> > > +#ifdef CONFIG_HIGHMEM
> > > +#define PageHighMem(page)	is_highmem(page_zone(page))
> > > +#else
> > > +#define PageHighMem(page)	0 /* needed to optimize away at compile time */
> > > +#endif
> > > +
> > 
> > Seems to be a tiny inconsistency here. PageSwapCache below is a static
> > inline returning 0 that you fixed up as part of the shuffling where as
> > PageHighMem is #defined to 0. Care to fix it up too?
> 
> Ok.
> 
> > > -#define SetPagePrivate(page)	set_bit(PG_private, &(page)->flags)
> > > -#define ClearPagePrivate(page)	clear_bit(PG_private, &(page)->flags)
> > > -#define PagePrivate(page)	test_bit(PG_private, &(page)->flags)
> > > -#define __SetPagePrivate(page)  __set_bit(PG_private, &(page)->flags)
> > > -#define __ClearPagePrivate(page) __clear_bit(PG_private, &(page)->flags)
> > > +static inline void set_page_writeback(struct page *page)
> > > +{
> > > +	test_set_page_writeback(page);
> > > +}
> > 
> > It's been around for ages and unrelated to your patch series but it
> > looks odd that set_page_writeback() is simply a function alias that
> > ignores return values :/
> 
> Yes its strange. Is there a set_page_writeback function?
> 

Other than this inline, none that I spotted. It has a number of call-sites
though so I guess the intention was to implicitly document that ignoring
the return value was deliberate. Might as well leave it.

-- 
Mel Gorman
Part-time Phd Student                          Linux Technology Center
University of Limerick                         IBM Dublin Software Lab

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [rfc 02/10] Pageflags: Introduce macros to generate page flag functions
  2008-03-04  0:04 [rfc 00/10] [Patch] Page flags: Cleanup, reorg and introduce 5 new flags Christoph Lameter
@ 2008-03-04  0:04 ` Christoph Lameter
  0 siblings, 0 replies; 19+ messages in thread
From: Christoph Lameter @ 2008-03-04  0:04 UTC (permalink / raw)
  To: Andrew Morton
  Cc: linux-kernel, Mel Gorman, apw, KAMEZAWA Hiroyuki,
	KOSAKI Motohiro, Rik van Riel, linux-mm

[-- Attachment #1: pageflags-add-macros --]
[-- Type: text/plain, Size: 2880 bytes --]

Introduce a set of macros that generate functions to handle page flags.


A page flag function group typically starts with either

	SETPAGEFLAG(<part of function name>,<part of PG_ flagname>)

to create a set of page flag operations that are atomic. Or

	__SETPAGEFLAG(<part of function name>,<part of PG_ flagname)

to create a set of page flag operations that are not atomic.


Then additional operations can be added using the following macros

TESTSCFLAG		Create additional atomic test-and-set and
			test-and-clear functions

TESTSETFLAG		Create additional test and set function
TESTCLEARFLAG		Create additional test and clear function
SETPAGEFLAG		Create additional atomic set function
CLEARPAGEFLAG		Create additional atomic clear function
__TESTPAGEFLAG		Create additional non atomic set function
__SETPAGEFLAG		Create additional non atomic clear function

Signed-off-by: Christoph Lameter <clameter@sgi.com>

---
 include/linux/page-flags.h |   41 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 41 insertions(+)

Index: linux-2.6/include/linux/page-flags.h
===================================================================
--- linux-2.6.orig/include/linux/page-flags.h	2008-03-03 15:45:20.895497292 -0800
+++ linux-2.6/include/linux/page-flags.h	2008-03-03 15:45:56.827992817 -0800
@@ -105,6 +105,47 @@ enum pageflags {
 };
 
 /*
+ * Macros to create function definitions for page flags
+ */
+#define TESTPAGEFLAG(uname, lname)					\
+static inline int Page##uname(struct page *page) 			\
+			{ return test_bit(PG_##lname, page); }
+
+#define SETPAGEFLAG(uname, lname)					\
+static inline void SetPage##uname(struct page *page)			\
+			{ set_bit(PG_##lname, page); }
+
+#define CLEARPAGEFLAG(uname, lname)					\
+static inline void ClearPage##uname(struct page *page)			\
+			{ clear_bit(PG_##lname, page); }
+
+#define __SETPAGEFLAG(uname, lname)					\
+static inline void __SetPage##uname(struct page *page)			\
+			{ __set_bit(PG_##lname, page); }
+
+#define __CLEARPAGEFLAG(uname, lname)					\
+static inline void __ClearPage##uname(struct page *page)		\
+			{ __clear_bit(PG_##lname, page); }
+
+#define TESTSETFLAG(uname, lname)					\
+static inline int TestSetPage##uname(struct page *page)			\
+		{ return test_and_set_bit(PG_##lname, &page->flags); }
+
+#define TESTCLEARFLAG(uname, lname)					\
+static inline int TestClearPage##uname(struct page *page)		\
+		{ return test_and_clear_bit(PG_##lname, &page->flags); }
+
+
+#define PAGEFLAG(uname, lname) TESTPAGEFLAG(uname, lname)		\
+	SETPAGEFLAG(uname, lname) CLEARPAGEFLAG(uname, lname)
+
+#define __PAGEFLAG(uname, lname) TESTPAGEFLAG(uname, lname)		\
+	__SETPAGEFLAG(uname, lname)  __CLEARPAGEFLAG(uname, lname)
+
+#define TESTSCFLAG(uname, lname)					\
+	TESTSETFLAG(uname, lname) TESTCLEARFLAG(uname, lname)
+
+/*
  * Manipulation of page state flags
  */
 #define PageLocked(page)		\

-- 

^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2008-03-07 11:14 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-03-01  4:05 [rfc 00/10] [RFC] Page flags: Saving some, making handling easier etc Christoph Lameter
2008-03-01  4:05 ` [rfc 01/10] Pageflags: Use an enum for the flags Christoph Lameter
2008-03-03 10:09   ` Mel Gorman
2008-03-01  4:05 ` [rfc 02/10] Pageflags: Introduce macros to generate page flag functions Christoph Lameter
2008-03-01  4:05 ` [rfc 03/10] Pageflags: Convert to the use of new macros Christoph Lameter
2008-03-03 10:24   ` Mel Gorman
2008-03-03 18:03     ` Christoph Lameter
2008-03-07 11:13       ` Mel Gorman
2008-03-01  4:05 ` [rfc 04/10] Pageflags: Eliminate PG_readahead Christoph Lameter
2008-03-01  4:05 ` [rfc 05/10] Sparsemem: Vmemmap does not need section bits Christoph Lameter
2008-03-01  4:05 ` [rfc 06/10] Kbuild: Create a way to create preprocessor constants from C expressions Christoph Lameter
2008-03-01  4:05 ` [rfc 07/10] Pageflags: Get rid of FLAGS_RESERVED Christoph Lameter
2008-03-01 16:26   ` Rik van Riel
2008-03-03 17:57     ` Christoph Lameter
2008-03-01  4:05 ` [rfc 08/10] Export NR_MAX_ZONES to the preprocessor Christoph Lameter
2008-03-01  4:05 ` [rfc 09/10] Get rid of __ZONE_COUNT Christoph Lameter
2008-03-01  4:05 ` [rfc 10/10] Pageflags land grab Christoph Lameter
2008-03-01 17:21   ` Rik van Riel
2008-03-04  0:04 [rfc 00/10] [Patch] Page flags: Cleanup, reorg and introduce 5 new flags Christoph Lameter
2008-03-04  0:04 ` [rfc 02/10] Pageflags: Introduce macros to generate page flag functions Christoph Lameter

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).