[PATCH 1/12] Add a bitmap that is used to track flags affecting a block of pages

2007-03-01 Thread Mel Gorman

The fragmentation reduction strategy needs to track if pages within a block
can be moved or reclaimed so that pages are freed to the appropriate list.
This patch adds a bitmap for flags affecting a whole a MAX_ORDER block
of pages.

In non-SPARSEMEM configurations, the bitmap is stored in the struct zone
and allocated during initialisation. SPARSEMEM statically allocates the
bitmap in a struct mem_section so that bitmaps do not have to be resized
during memory hotadd. This wastes a small amount of memory per unused section
(usually sizeof(unsigned long)) but the complexity of dynamically allocating
the memory is quite high.

Additional credit to Andy Whitcroft who reviewed up an earlier implementation
of the mechanism an suggested how to make it a *lot* cleaner.

Signed-off-by: Mel Gorman <[EMAIL PROTECTED]>
---

 include/linux/mmzone.h  |   13 
 include/linux/pageblock-flags.h |   51 +++
 mm/page_alloc.c |  113 +++
 3 files changed, 177 insertions(+)

diff -rup -X /usr/src/patchset-0.6/bin//dontdiff 
linux-2.6.20-mm2-clean/include/linux/mmzone.h 
linux-2.6.20-mm2-001_pageblock_bits/include/linux/mmzone.h
--- linux-2.6.20-mm2-clean/include/linux/mmzone.h   2007-02-19 
01:22:30.0 +
+++ linux-2.6.20-mm2-001_pageblock_bits/include/linux/mmzone.h  2007-02-20 
18:23:25.0 +
@@ -13,6 +13,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -209,6 +210,14 @@ struct zone {
 #endif
struct free_areafree_area[MAX_ORDER];
 
+#ifndef CONFIG_SPARSEMEM
+   /*
+* Flags for a MAX_ORDER_NR_PAGES block. See pageblock-flags.h.
+* In SPARSEMEM, this map is stored in struct mem_section
+*/
+   unsigned long   *pageblock_flags;
+#endif /* CONFIG_SPARSEMEM */
+
 
ZONE_PADDING(_pad1_)
 
@@ -661,6 +670,9 @@ extern struct zone *next_zone(struct zon
 #define PAGES_PER_SECTION   (1UL << PFN_SECTION_SHIFT)
 #define PAGE_SECTION_MASK  (~(PAGES_PER_SECTION-1))
 
+#define SECTION_BLOCKFLAGS_BITS \
+   ((SECTION_SIZE_BITS - (MAX_ORDER-1)) * NR_PAGEBLOCK_BITS)
+
 #if (MAX_ORDER - 1 + PAGE_SHIFT) > SECTION_SIZE_BITS
 #error Allocator MAX_ORDER exceeds SECTION_SIZE
 #endif
@@ -680,6 +692,7 @@ struct mem_section {
 * before using it wrong.
 */
unsigned long section_mem_map;
+   DECLARE_BITMAP(pageblock_flags, SECTION_BLOCKFLAGS_BITS);
 };
 
 #ifdef CONFIG_SPARSEMEM_EXTREME
diff -rup -X /usr/src/patchset-0.6/bin//dontdiff 
linux-2.6.20-mm2-clean/include/linux/pageblock-flags.h 
linux-2.6.20-mm2-001_pageblock_bits/include/linux/pageblock-flags.h
--- linux-2.6.20-mm2-clean/include/linux/pageblock-flags.h  2007-02-19 
13:53:43.0 +
+++ linux-2.6.20-mm2-001_pageblock_bits/include/linux/pageblock-flags.h 
2007-02-20 19:44:47.0 +
@@ -0,0 +1,51 @@
+/*
+ * Macros for manipulating and testing flags related to a
+ * MAX_ORDER_NR_PAGES block of pages.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) IBM Corporation, 2006
+ *
+ * Original author, Mel Gorman
+ * Major cleanups and reduction of bit operations, Andy Whitcroft
+ */
+#ifndef PAGEBLOCK_FLAGS_H
+#define PAGEBLOCK_FLAGS_H
+
+#include 
+
+/* Macro to aid the definition of ranges of bits */
+#define PB_range(name, required_bits) \
+   name, name ## _end = (name + required_bits) - 1
+
+/* Bit indices that affect a whole block of pages */
+enum pageblock_bits {
+   NR_PAGEBLOCK_BITS
+};
+
+/* Forward declaration */
+struct page;
+
+/* Declarations for getting and setting flags. See mm/page_alloc.c */
+unsigned long get_pageblock_flags_group(struct page *page,
+   int start_bitidx, int end_bitidx);
+void set_pageblock_flags_group(struct page *page, unsigned long flags,
+   int start_bitidx, int end_bitidx);
+
+#define get_pageblock_flags(page) \
+   get_pageblock_flags_group(page, 0, NR_PAGEBLOCK_BITS-1)
+#define set_pageblock_flags(page) \
+   set_pageblock_flags_group(page, 0, NR_PAGEBLOCK_BITS-1)
+
+#endif /* PAGEBLOCK_FLAGS_H */
diff -rup -X /usr/src/patchset-0.6/bin//dontdiff 
linux-2.6.20-mm2-clean/mm/page_alloc.c 
linux-2.6.20-mm2-001_pageblock_bits/mm/page_alloc.c
--- 

[PATCH 1/12] Add a bitmap that is used to track flags affecting a block of pages

2007-03-01 Thread Mel Gorman

The fragmentation reduction strategy needs to track if pages within a block
can be moved or reclaimed so that pages are freed to the appropriate list.
This patch adds a bitmap for flags affecting a whole a MAX_ORDER block
of pages.

In non-SPARSEMEM configurations, the bitmap is stored in the struct zone
and allocated during initialisation. SPARSEMEM statically allocates the
bitmap in a struct mem_section so that bitmaps do not have to be resized
during memory hotadd. This wastes a small amount of memory per unused section
(usually sizeof(unsigned long)) but the complexity of dynamically allocating
the memory is quite high.

Additional credit to Andy Whitcroft who reviewed up an earlier implementation
of the mechanism an suggested how to make it a *lot* cleaner.

Signed-off-by: Mel Gorman [EMAIL PROTECTED]
---

 include/linux/mmzone.h  |   13 
 include/linux/pageblock-flags.h |   51 +++
 mm/page_alloc.c |  113 +++
 3 files changed, 177 insertions(+)

diff -rup -X /usr/src/patchset-0.6/bin//dontdiff 
linux-2.6.20-mm2-clean/include/linux/mmzone.h 
linux-2.6.20-mm2-001_pageblock_bits/include/linux/mmzone.h
--- linux-2.6.20-mm2-clean/include/linux/mmzone.h   2007-02-19 
01:22:30.0 +
+++ linux-2.6.20-mm2-001_pageblock_bits/include/linux/mmzone.h  2007-02-20 
18:23:25.0 +
@@ -13,6 +13,7 @@
 #include linux/init.h
 #include linux/seqlock.h
 #include linux/nodemask.h
+#include linux/pageblock-flags.h
 #include asm/atomic.h
 #include asm/page.h
 
@@ -209,6 +210,14 @@ struct zone {
 #endif
struct free_areafree_area[MAX_ORDER];
 
+#ifndef CONFIG_SPARSEMEM
+   /*
+* Flags for a MAX_ORDER_NR_PAGES block. See pageblock-flags.h.
+* In SPARSEMEM, this map is stored in struct mem_section
+*/
+   unsigned long   *pageblock_flags;
+#endif /* CONFIG_SPARSEMEM */
+
 
ZONE_PADDING(_pad1_)
 
@@ -661,6 +670,9 @@ extern struct zone *next_zone(struct zon
 #define PAGES_PER_SECTION   (1UL  PFN_SECTION_SHIFT)
 #define PAGE_SECTION_MASK  (~(PAGES_PER_SECTION-1))
 
+#define SECTION_BLOCKFLAGS_BITS \
+   ((SECTION_SIZE_BITS - (MAX_ORDER-1)) * NR_PAGEBLOCK_BITS)
+
 #if (MAX_ORDER - 1 + PAGE_SHIFT)  SECTION_SIZE_BITS
 #error Allocator MAX_ORDER exceeds SECTION_SIZE
 #endif
@@ -680,6 +692,7 @@ struct mem_section {
 * before using it wrong.
 */
unsigned long section_mem_map;
+   DECLARE_BITMAP(pageblock_flags, SECTION_BLOCKFLAGS_BITS);
 };
 
 #ifdef CONFIG_SPARSEMEM_EXTREME
diff -rup -X /usr/src/patchset-0.6/bin//dontdiff 
linux-2.6.20-mm2-clean/include/linux/pageblock-flags.h 
linux-2.6.20-mm2-001_pageblock_bits/include/linux/pageblock-flags.h
--- linux-2.6.20-mm2-clean/include/linux/pageblock-flags.h  2007-02-19 
13:53:43.0 +
+++ linux-2.6.20-mm2-001_pageblock_bits/include/linux/pageblock-flags.h 
2007-02-20 19:44:47.0 +
@@ -0,0 +1,51 @@
+/*
+ * Macros for manipulating and testing flags related to a
+ * MAX_ORDER_NR_PAGES block of pages.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) IBM Corporation, 2006
+ *
+ * Original author, Mel Gorman
+ * Major cleanups and reduction of bit operations, Andy Whitcroft
+ */
+#ifndef PAGEBLOCK_FLAGS_H
+#define PAGEBLOCK_FLAGS_H
+
+#include linux/types.h
+
+/* Macro to aid the definition of ranges of bits */
+#define PB_range(name, required_bits) \
+   name, name ## _end = (name + required_bits) - 1
+
+/* Bit indices that affect a whole block of pages */
+enum pageblock_bits {
+   NR_PAGEBLOCK_BITS
+};
+
+/* Forward declaration */
+struct page;
+
+/* Declarations for getting and setting flags. See mm/page_alloc.c */
+unsigned long get_pageblock_flags_group(struct page *page,
+   int start_bitidx, int end_bitidx);
+void set_pageblock_flags_group(struct page *page, unsigned long flags,
+   int start_bitidx, int end_bitidx);
+
+#define get_pageblock_flags(page) \
+   get_pageblock_flags_group(page, 0, NR_PAGEBLOCK_BITS-1)
+#define set_pageblock_flags(page) \
+   set_pageblock_flags_group(page, 0, NR_PAGEBLOCK_BITS-1)
+
+#endif /* PAGEBLOCK_FLAGS_H */
diff -rup -X /usr/src/patchset-0.6/bin//dontdiff