linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] Dynamically allocated pageflags
@ 2006-02-02 11:11 Nigel Cunningham
  2006-02-02 13:31 ` Andi Kleen
  2006-02-09  7:00 ` Magnus Damm
  0 siblings, 2 replies; 6+ messages in thread
From: Nigel Cunningham @ 2006-02-02 11:11 UTC (permalink / raw)
  To: linux-mm, linux-kernel

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

Hi everyone.

This is my latest revision of the dynamically allocated pageflags patch.

The patch is useful for kernel space applications that sometimes need to flag
pages for some purpose, but don't otherwise need the retain the state. A prime
example is suspend-to-disk, which needs to flag pages as unsaveable, allocated
by suspend-to-disk and the like while it is working, but doesn't need to
retain any of this state between cycles.

Since the last revision, I have switched to using per-zone bitmaps within each
bitmap.

I know that I could still add hotplug memory support. Is there anything else
missing?

Regards,

Nigel

 include/linux/dyn_pageflags.h |   66 ++++++++
 lib/Kconfig                   |    3 
 lib/Makefile                  |    2 
 lib/dyn_pageflags.c           |  330 ++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 401 insertions(+)
diff -ruNp 3150-dynamic-pageflags.patch-old/include/linux/dyn_pageflags.h 3150-dynamic-pageflags.patch-new/include/linux/dyn_pageflags.h
--- 3150-dynamic-pageflags.patch-old/include/linux/dyn_pageflags.h	1970-01-01 10:00:00.000000000 +1000
+++ 3150-dynamic-pageflags.patch-new/include/linux/dyn_pageflags.h	2006-02-02 21:09:57.000000000 +1000
@@ -0,0 +1,66 @@
+/*
+ * include/linux/dyn_pageflags.h
+ *
+ * Copyright (C) 2004-2006 Nigel Cunningham <nigel@suspend2.net>
+ *
+ * This file is released under the GPLv2.
+ *
+ * It implements support for dynamically allocated bitmaps that are
+ * used for temporary or infrequently used pageflags, in lieu of
+ * bits in the struct page flags entry.
+ */
+
+#ifndef DYN_PAGEFLAGS_H
+#define DYN_PAGEFLAGS_H
+
+#include <linux/mm.h>
+
+typedef unsigned long *** dyn_pageflags_t;
+
+#define BITNUMBER(page) (page_to_pfn(page))
+
+#if BITS_PER_LONG == 32
+#define UL_SHIFT 5
+#else 
+#if BITS_PER_LONG == 64
+#define UL_SHIFT 6
+#else
+#error Bits per long not 32 or 64?
+#endif
+#endif
+
+#define BIT_NUM_MASK (sizeof(unsigned long) * 8 - 1)
+#define PAGE_NUM_MASK (~((1 << (PAGE_SHIFT + 3)) - 1))
+#define UL_NUM_MASK (~(BIT_NUM_MASK | PAGE_NUM_MASK))
+
+#define BITS_PER_PAGE (PAGE_SIZE << 3)
+#define PAGENUMBER(zone_offset) (zone_offset >> (PAGE_SHIFT + 3))
+#define PAGEINDEX(zone_offset) ((zone_offset & UL_NUM_MASK) >> UL_SHIFT)
+#define PAGEBIT(zone_offset) (zone_offset & BIT_NUM_MASK)
+
+#define PAGE_UL_PTR(bitmap, zone_num, zone_pfn) \
+       ((bitmap[zone_num][PAGENUMBER(zone_pfn)])+PAGEINDEX(zone_pfn))
+
+/* With the above macros defined, you can do...
+
+#define PagePageset1(page) (test_dynpageflag(&pageset1_map, page))
+#define SetPagePageset1(page) (set_dynpageflag(&pageset1_map, page))
+#define ClearPagePageset1(page) (clear_dynpageflag(&pageset1_map, page))
+*/
+
+#define BITMAP_FOR_EACH_SET(bitmap, counter) \
+	for (counter = get_next_bit_on(bitmap, -1); counter < max_pfn; \
+		counter = get_next_bit_on(bitmap, counter))
+
+extern void clear_dyn_pageflags(dyn_pageflags_t pagemap);
+extern int allocate_dyn_pageflags(dyn_pageflags_t *pagemap);
+extern int free_dyn_pageflags(dyn_pageflags_t *pagemap);
+extern int dyn_pageflags_pages_per_bitmap(void);
+extern int get_next_bit_on(dyn_pageflags_t bitmap, int counter);
+extern unsigned long *dyn_pageflags_ul_ptr(dyn_pageflags_t *bitmap,
+		struct page *pg);
+
+extern int test_dynpageflag(dyn_pageflags_t *bitmap, struct page *page);
+extern void set_dynpageflag(dyn_pageflags_t *bitmap, struct page *page);
+extern void clear_dynpageflag(dyn_pageflags_t *bitmap, struct page *page);
+#endif
diff -ruNp 3150-dynamic-pageflags.patch-old/lib/dyn_pageflags.c 3150-dynamic-pageflags.patch-new/lib/dyn_pageflags.c
--- 3150-dynamic-pageflags.patch-old/lib/dyn_pageflags.c	1970-01-01 10:00:00.000000000 +1000
+++ 3150-dynamic-pageflags.patch-new/lib/dyn_pageflags.c	2006-02-02 21:09:44.000000000 +1000
@@ -0,0 +1,330 @@
+/*
+ * lib/dyn_pageflags.c
+ *
+ * Copyright (C) 2004-2006 Nigel Cunningham <nigel@suspend2.net>
+ * 
+ * This file is released under the GPLv2.
+ *
+ * Routines for dynamically allocating and releasing bitmaps
+ * used as pseudo-pageflags.
+ *
+ * Arrays are not contiguous. The first sizeof(void *) bytes are
+ * the pointer to the next page in the bitmap. This allows us to
+ * work under low memory conditions where order 0 might be all
+ * that's available. In their original use (suspend2), it also
+ * lets us save the pages at suspend time, reload and relocate them
+ * as necessary at resume time without much effort.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/dyn_pageflags.h>
+#include <linux/bootmem.h>
+
+#define page_to_zone_offset(pg) (page_to_pfn(pg) - page_zone(pg)->zone_start_pfn)
+
+/* 
+ * num_zones
+ * 
+ * How many zones are there?
+ *
+ */
+
+static int num_zones(void)
+{
+	int result = 0;
+	struct zone *zone;
+
+	for_each_zone(zone)
+		result++;
+
+	return result;
+}
+
+/* 
+ * pages_for_zone(struct zone *zone)
+ * 
+ * How many pages do we need for a bitmap for this zone?
+ *
+ */
+
+static int pages_for_zone(struct zone *zone)
+{
+	return (zone->spanned_pages + (PAGE_SIZE << 3) - 1) >>
+			(PAGE_SHIFT + 3);
+}
+
+/*
+ * page_zone_number(struct page *page)
+ *
+ * Which zone index does the page match?
+ *
+ */
+
+static int page_zone_number(struct page *page)
+{
+	struct zone *zone, *zone_sought = page_zone(page);
+	int zone_num = 0;
+
+	for_each_zone(zone)
+		if (zone == zone_sought)
+			return zone_num;
+		else
+			zone_num++;
+
+	printk("Was looking for a zone for page %p.\n", page);
+	BUG_ON(1);
+
+	return 0;
+}
+
+/*
+ * dyn_pageflags_pages_per_bitmap
+ *
+ * Number of pages needed for a bitmap covering all zones.
+ *
+ */
+int dyn_pageflags_pages_per_bitmap(void)
+{
+	int total = 0;
+	struct zone *zone;
+
+	for_each_zone(zone)
+		total += pages_for_zone(zone);
+
+	return total;
+}
+
+/* 
+ * clear_dyn_pageflags(dyn_pageflags_t pagemap)
+ *
+ * Clear an array used to store local page flags.
+ *
+ */
+
+void clear_dyn_pageflags(dyn_pageflags_t pagemap)
+{
+	int i = 0, zone_num = 0;
+	struct zone *zone;
+	
+	BUG_ON(!pagemap);
+
+	for_each_zone(zone) {
+		for (i = 0; i < pages_for_zone(zone); i++)
+			memset((pagemap[zone_num][i]), 0, PAGE_SIZE);
+		zone_num++;
+	}
+}
+
+/* 
+ * allocate_dyn_pageflags(dyn_pageflags_t *pagemap)
+ *
+ * Allocate a bitmap for dynamic page flags.
+ *
+ */
+int allocate_dyn_pageflags(dyn_pageflags_t *pagemap)
+{
+	int i, zone_num = 0;
+	struct zone *zone;
+
+	BUG_ON(*pagemap);
+
+	*pagemap = kmalloc(sizeof(void *) * num_zones(), GFP_ATOMIC);
+
+	if (!*pagemap)
+		return -ENOMEM;
+
+	for_each_zone(zone) {
+		int zone_pages = pages_for_zone(zone);
+		(*pagemap)[zone_num] = kmalloc(sizeof(void *) * zone_pages,
+					       GFP_ATOMIC);
+
+		if (!(*pagemap)[zone_num]) {
+			kfree (*pagemap);
+			return -ENOMEM;
+		}
+
+		for (i = 0; i < zone_pages; i++) {
+			unsigned long address = get_zeroed_page(GFP_ATOMIC);
+			(*pagemap)[zone_num][i] = (unsigned long *) address;
+			if (!(*pagemap)[zone_num][i]) {
+				printk("Error. Unable to allocate memory for "
+					"dynamic pageflags.");
+				free_dyn_pageflags(pagemap);
+				return -ENOMEM;
+			}
+		}
+		zone_num++;
+	}
+
+	return 0;
+}
+
+/* 
+ * free_dyn_pageflags(dyn_pageflags_t *pagemap)
+ *
+ * Free a dynamically allocated pageflags bitmap. For Suspend2 usage, we
+ * support data being relocated from slab to pages that don't conflict
+ * with the image that will be copied back. This is the reason for the
+ * PageSlab tests below.
+ *
+ */
+void free_dyn_pageflags(dyn_pageflags_t *pagemap)
+{
+	int i = 0, zone_num = 0;
+	struct zone *zone;
+
+	if (!*pagemap)
+		return;
+	
+	for_each_zone(zone) {
+		int zone_pages = pages_for_zone(zone);
+
+		if (!((*pagemap)[zone_num]))
+			continue;
+		for (i = 0; i < zone_pages; i++)
+			if ((*pagemap)[zone_num][i])
+				free_page((unsigned long) (*pagemap)[zone_num][i]);
+	
+		if (PageSlab(virt_to_page((*pagemap)[zone_num])))
+			kfree((*pagemap)[zone_num]);
+		else
+			free_page((unsigned long) (*pagemap)[zone_num]);
+
+		zone_num++;
+	}
+
+	if (PageSlab(virt_to_page((*pagemap))))
+		kfree(*pagemap);
+	else
+		free_page((unsigned long) (*pagemap));
+
+	*pagemap = NULL;
+	return;
+}
+
+/*
+ * dyn_pageflags_ul_ptr(dyn_pageflags_t *bitmap, struct page *pg)
+ *
+ * Get a pointer to the unsigned long containing the flag in the bitmap
+ * for the given page.
+ *
+ */
+
+unsigned long *dyn_pageflags_ul_ptr(dyn_pageflags_t *bitmap, struct page *pg)
+{
+	int zone_pfn = page_to_zone_offset(pg);
+	int zone_num = page_zone_number(pg);
+	int pagenum = PAGENUMBER(zone_pfn);
+	int page_offset = PAGEINDEX(zone_pfn);
+	return ((*bitmap)[zone_num][pagenum]) + page_offset;
+}
+
+/*
+ * test_dynpageflag(dyn_pageflags_t *bitmap, struct page *page)
+ *
+ * Is the page flagged in the given bitmap?
+ *
+ */
+
+int test_dynpageflag(dyn_pageflags_t *bitmap, struct page *page)
+{
+	unsigned long *ul = dyn_pageflags_ul_ptr(bitmap, page);
+	int zone_offset = page_to_zone_offset(page);
+	int bit = PAGEBIT(zone_offset);
+	
+	return test_bit(bit, ul);
+}
+
+/*
+ * set_dynpageflag(dyn_pageflags_t *bitmap, struct page *page)
+ *
+ * Set the flag for the page in the given bitmap.
+ *
+ */
+
+void set_dynpageflag(dyn_pageflags_t *bitmap, struct page *page)
+{
+	unsigned long *ul = dyn_pageflags_ul_ptr(bitmap, page);
+	int zone_offset = page_to_zone_offset(page);
+	int bit = PAGEBIT(zone_offset);
+	set_bit(bit, ul);
+}
+
+/*
+ * clear_dynpageflags(dyn_pageflags_t *bitmap, struct page *page)
+ *
+ * Clear the flag for the page in the given bitmap.
+ *
+ */
+
+void clear_dynpageflag(dyn_pageflags_t *bitmap, struct page *page)
+{
+	unsigned long *ul = dyn_pageflags_ul_ptr(bitmap, page);
+	int zone_offset = page_to_zone_offset(page);
+	int bit = PAGEBIT(zone_offset);
+	clear_bit(bit, ul);
+}
+
+/*
+ * get_next_bit_on(dyn_pageflags_t bitmap, int counter)
+ *
+ * Given a pfn (possibly -1), find the next pfn in the bitmap that
+ * is set. If there are no more flags set, return max_pfn.
+ *
+ */
+
+int get_next_bit_on(dyn_pageflags_t bitmap, int counter)
+{
+	struct page *page;
+	struct zone *zone;
+	unsigned long *ul;
+	int zone_offset, pagebit, zone_num, first;
+
+	BUG_ON(counter == max_pfn);
+
+	first = (counter == -1);
+	
+	if (first)
+		counter = pgdat_list->node_zones->zone_start_pfn;
+
+	page = pfn_to_page(counter);
+	zone = page_zone(page);
+	zone_num = page_zone_number(page);
+
+	if (!first)
+		counter++;
+	
+	zone_offset = counter - zone->zone_start_pfn;
+
+	do {
+		if (zone_offset >= zone->spanned_pages) {
+			do {
+				zone = next_zone(zone);
+				if (!zone)
+					return max_pfn;
+				zone_num++;
+			} while(!zone->spanned_pages);
+
+			counter = zone->zone_start_pfn;
+			zone_offset = 0;
+			page = pfn_to_page(counter);
+		}
+		
+		/*
+		 * This could be optimised, but there are more
+		 * important things and the code is simple at
+		 * the moment 
+		 */
+		ul = (bitmap[zone_num][PAGENUMBER(zone_offset)]) + PAGEINDEX(zone_offset);
+		
+		pagebit = PAGEBIT(zone_offset);
+
+		counter++;
+		zone_offset++;
+		page = pfn_to_page(counter);
+	
+	} while((counter <= max_pfn) && (!test_bit(pagebit, ul)));
+	return counter - 1;
+}
+
diff -ruNp 3150-dynamic-pageflags.patch-old/lib/Kconfig 3150-dynamic-pageflags.patch-new/lib/Kconfig
--- 3150-dynamic-pageflags.patch-old/lib/Kconfig	2006-01-19 21:28:05.000000000 +1000
+++ 3150-dynamic-pageflags.patch-new/lib/Kconfig	2006-01-24 06:54:07.000000000 +1000
@@ -38,6 +38,9 @@ config LIBCRC32C
 	  require M here.  See Castagnoli93.
 	  Module will be libcrc32c.
 
+config DYN_PAGEFLAGS
+	bool
+
 #
 # compression support is select'ed if needed
 #
diff -ruNp 3150-dynamic-pageflags.patch-old/lib/Makefile 3150-dynamic-pageflags.patch-new/lib/Makefile
--- 3150-dynamic-pageflags.patch-old/lib/Makefile	2006-01-19 21:28:05.000000000 +1000
+++ 3150-dynamic-pageflags.patch-new/lib/Makefile	2006-01-24 06:54:07.000000000 +1000
@@ -28,6 +28,8 @@ ifneq ($(CONFIG_HAVE_DEC_LOCK),y)
   lib-y += dec_and_lock.o
 endif
 
+obj-$(CONFIG_DYN_PAGEFLAGS) += dyn_pageflags.o
+
 obj-$(CONFIG_CRC_CCITT)	+= crc-ccitt.o
 obj-$(CONFIG_CRC16)	+= crc16.o
 obj-$(CONFIG_CRC32)	+= crc32.o

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

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

* Re: [PATCH] Dynamically allocated pageflags
  2006-02-02 11:11 [PATCH] Dynamically allocated pageflags Nigel Cunningham
@ 2006-02-02 13:31 ` Andi Kleen
  2006-02-02 16:47   ` Dave Hansen
  2006-02-08 23:43   ` Nigel Cunningham
  2006-02-09  7:00 ` Magnus Damm
  1 sibling, 2 replies; 6+ messages in thread
From: Andi Kleen @ 2006-02-02 13:31 UTC (permalink / raw)
  To: Nigel Cunningham; +Cc: linux-mm, linux-kernel

On Thursday 02 February 2006 12:11, Nigel Cunningham wrote:
> Hi everyone.
> 
> This is my latest revision of the dynamically allocated pageflags patch.
> 
> The patch is useful for kernel space applications that sometimes need to flag
> pages for some purpose, but don't otherwise need the retain the state. A prime
> example is suspend-to-disk, which needs to flag pages as unsaveable, allocated
> by suspend-to-disk and the like while it is working, but doesn't need to
> retain any of this state between cycles.

It looks like total overkill for a simple problem to me. And is there really
any other user of this other than swsusp?

-Andi


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

* Re: [PATCH] Dynamically allocated pageflags
  2006-02-02 13:31 ` Andi Kleen
@ 2006-02-02 16:47   ` Dave Hansen
  2006-02-08 23:43   ` Nigel Cunningham
  1 sibling, 0 replies; 6+ messages in thread
From: Dave Hansen @ 2006-02-02 16:47 UTC (permalink / raw)
  To: Andi Kleen; +Cc: Nigel Cunningham, linux-mm, linux-kernel

On Thu, 2006-02-02 at 14:31 +0100, Andi Kleen wrote:
> On Thursday 02 February 2006 12:11, Nigel Cunningham wrote:
> > This is my latest revision of the dynamically allocated pageflags patch.
> > 
> > The patch is useful for kernel space applications that sometimes need to flag
> > pages for some purpose, but don't otherwise need the retain the state. A prime
> > example is suspend-to-disk, which needs to flag pages as unsaveable, allocated
> > by suspend-to-disk and the like while it is working, but doesn't need to
> > retain any of this state between cycles.
> 
> It looks like total overkill for a simple problem to me. And is there really
> any other user of this other than swsusp?

We'll probably end up needing a similar mechanism for memory hotplug.
What I need is a mechanism that is exceedingly quick during normal
runtime, any maybe marginally slower during a memory remove operation.

We basically put three or so hooks into some crucial parts of the page
allocator to grab out pages which we want to remove so that they never
make it back into the allocator or out to the system.

Those hooks have to be _really_ fast at runtime, obviously.  In my
testing code, I always just added a page flag, but that's only because I
was being lazy when I coded it up.

-- Dave


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

* Re: [PATCH] Dynamically allocated pageflags
  2006-02-02 13:31 ` Andi Kleen
  2006-02-02 16:47   ` Dave Hansen
@ 2006-02-08 23:43   ` Nigel Cunningham
  1 sibling, 0 replies; 6+ messages in thread
From: Nigel Cunningham @ 2006-02-08 23:43 UTC (permalink / raw)
  To: Andi Kleen; +Cc: linux-mm, linux-kernel

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

Hi.

On Thursday 02 February 2006 23:31, Andi Kleen wrote:
> On Thursday 02 February 2006 12:11, Nigel Cunningham wrote:
> > Hi everyone.
> > 
> > This is my latest revision of the dynamically allocated pageflags patch.
> > 
> > The patch is useful for kernel space applications that sometimes need to flag
> > pages for some purpose, but don't otherwise need the retain the state. A prime
> > example is suspend-to-disk, which needs to flag pages as unsaveable, allocated
> > by suspend-to-disk and the like while it is working, but doesn't need to
> > retain any of this state between cycles.
> 
> It looks like total overkill for a simple problem to me. And is there really
> any other user of this other than swsusp?

Sorry for the slow response. I switched email clients and gained a bogus
filter along the way (entirely my fault, of course).

As Dave said, he might make use of them too. I use about 5 or 6 of these,
depending upon exactly how Suspend2 is configured.

In the meanwhile, AKPM gave me a suggestion for a better solution
(radix-trees). My algorithms & data-structures course was 14 years ago,
so I'll go dust off Kingston (IIRC) and learn what he's talking about again :)

Thanks for the feedback and regards,

Nigel

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

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

* Re: [PATCH] Dynamically allocated pageflags
  2006-02-02 11:11 [PATCH] Dynamically allocated pageflags Nigel Cunningham
  2006-02-02 13:31 ` Andi Kleen
@ 2006-02-09  7:00 ` Magnus Damm
  2006-02-09  7:08   ` Nigel Cunningham
  1 sibling, 1 reply; 6+ messages in thread
From: Magnus Damm @ 2006-02-09  7:00 UTC (permalink / raw)
  To: Nigel Cunningham; +Cc: linux-mm, linux-kernel

Hi Nigel,

On 2/2/06, Nigel Cunningham <ncunningham@cyclades.com> wrote:
> Hi everyone.
>
> This is my latest revision of the dynamically allocated pageflags patch.
>
> The patch is useful for kernel space applications that sometimes need to flag
> pages for some purpose, but don't otherwise need the retain the state. A prime
> example is suspend-to-disk, which needs to flag pages as unsaveable, allocated
> by suspend-to-disk and the like while it is working, but doesn't need to
> retain any of this state between cycles.
>
> Since the last revision, I have switched to using per-zone bitmaps within each
> bitmap.
>
> I know that I could still add hotplug memory support. Is there anything else
> missing?

I like the idea of the patch, but the code looks a bit too complicated
IMO. What is wrong with using vmalloc() to allocate a virtual
contiguous range of 0-order pages (one bit per page), and then use the
functions in linux/bitmap.h...? Or maybe I'm misunderstanding.

A system that has 2 GB RAM and 4 KB pages would use 64 KB per bitmap
(one bitmap per node), which is not so bad memory wise if you plan to
use all bits.

OTOH, if your plan is to use a single bit here and there, and leave
most of the bits unused then some kind of tree is probably better.

Or does the kernel already implement some kind of data structure that
never consumes _that_ much more space than a bitmap when fully used,
and saves a lot of memory when just sparsely populated?

/ magnus

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

* Re: [PATCH] Dynamically allocated pageflags
  2006-02-09  7:00 ` Magnus Damm
@ 2006-02-09  7:08   ` Nigel Cunningham
  0 siblings, 0 replies; 6+ messages in thread
From: Nigel Cunningham @ 2006-02-09  7:08 UTC (permalink / raw)
  To: Magnus Damm; +Cc: linux-mm, linux-kernel, Andrew Morton

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

Hi.

On Thursday 09 February 2006 17:00, Magnus Damm wrote:
> Hi Nigel,
> 
> On 2/2/06, Nigel Cunningham <ncunningham@cyclades.com> wrote:
> > Hi everyone.
> >
> > This is my latest revision of the dynamically allocated pageflags patch.
> >
> > The patch is useful for kernel space applications that sometimes need to flag
> > pages for some purpose, but don't otherwise need the retain the state. A prime
> > example is suspend-to-disk, which needs to flag pages as unsaveable, allocated
> > by suspend-to-disk and the like while it is working, but doesn't need to
> > retain any of this state between cycles.
> >
> > Since the last revision, I have switched to using per-zone bitmaps within each
> > bitmap.
> >
> > I know that I could still add hotplug memory support. Is there anything else
> > missing?
> 
> I like the idea of the patch, but the code looks a bit too complicated
> IMO. What is wrong with using vmalloc() to allocate a virtual
> contiguous range of 0-order pages (one bit per page), and then use the
> functions in linux/bitmap.h...? Or maybe I'm misunderstanding.
> 
> A system that has 2 GB RAM and 4 KB pages would use 64 KB per bitmap
> (one bitmap per node), which is not so bad memory wise if you plan to
> use all bits.
> 
> OTOH, if your plan is to use a single bit here and there, and leave
> most of the bits unused then some kind of tree is probably better.
> 
> Or does the kernel already implement some kind of data structure that
> never consumes _that_ much more space than a bitmap when fully used,
> and saves a lot of memory when just sparsely populated?

Thanks for the suggestion - I'll look into it too.

Part of my reason for implementing them in this way was to make serialising
the data in an image header easy, when suspending to disk. I use the
bitmaps to record which pages were atomically copied, and generate a
similar bitmap for addresses of the freshly loaded pages prior to restoring
the image at resume time. Of course the routines that does the atomic
restore also iterates through these bitmaps. I'm not sure whether that
changes anything, but thought it was worth mentioning.

Regards,

Nigel

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

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

end of thread, other threads:[~2006-02-09  7:12 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-02-02 11:11 [PATCH] Dynamically allocated pageflags Nigel Cunningham
2006-02-02 13:31 ` Andi Kleen
2006-02-02 16:47   ` Dave Hansen
2006-02-08 23:43   ` Nigel Cunningham
2006-02-09  7:00 ` Magnus Damm
2006-02-09  7:08   ` Nigel Cunningham

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).