2.2.9.17 release.
[linux-2.6/suspend2-2.6.18.git] / kernel / power / pageflags.c
blobdccac978ddc63ce93d954a206f67e71d2e8e1e3f
1 /*
2 * kernel/power/pageflags.c
4 * Copyright (C) 2004-2007 Nigel Cunningham (nigel at suspend2 net)
5 *
6 * This file is released under the GPLv2.
8 * Routines for serialising and relocating pageflags in which we
9 * store our image metadata.
12 #include <linux/kernel.h>
13 #include <linux/mm.h>
14 #include <linux/module.h>
15 #include <linux/bitops.h>
16 #include <linux/list.h>
17 #include <linux/suspend.h>
18 #include "pageflags.h"
19 #include "modules.h"
20 #include "pagedir.h"
21 #include "suspend.h"
23 dyn_pageflags_t pageset2_map;
24 dyn_pageflags_t page_resave_map;
25 dyn_pageflags_t io_map;
27 static int pages_for_zone(struct zone *zone)
29 return DIV_ROUND_UP(zone->spanned_pages, (PAGE_SIZE << 3));
32 int suspend_pageflags_space_needed(void)
34 int total = 0;
35 struct zone *zone;
37 for_each_zone(zone)
38 if (populated_zone(zone))
39 total += sizeof(int) * 3 + pages_for_zone(zone) * PAGE_SIZE;
41 total += sizeof(int);
43 return total;
46 /* save_dyn_pageflags
48 * Description: Save a set of pageflags.
49 * Arguments: dyn_pageflags_t *: Pointer to the bitmap being saved.
52 void save_dyn_pageflags(dyn_pageflags_t pagemap)
54 int i, zone_idx, size, node = 0;
55 struct zone *zone;
56 struct pglist_data *pgdat;
58 if (!*pagemap)
59 return;
61 for_each_online_pgdat(pgdat) {
62 for (zone_idx = 0; zone_idx < MAX_NR_ZONES; zone_idx++) {
63 zone = &pgdat->node_zones[zone_idx];
65 if (!populated_zone(zone))
66 continue;
68 suspendActiveAllocator->rw_header_chunk(WRITE, NULL,
69 (char *) &node, sizeof(int));
70 suspendActiveAllocator->rw_header_chunk(WRITE, NULL,
71 (char *) &zone_idx, sizeof(int));
72 size = pages_for_zone(zone);
73 suspendActiveAllocator->rw_header_chunk(WRITE, NULL,
74 (char *) &size, sizeof(int));
76 for (i = 0; i < size; i++)
77 suspendActiveAllocator->rw_header_chunk(WRITE,
78 NULL, (char *) pagemap[node][zone_idx][i],
79 PAGE_SIZE);
81 node++;
83 node = -1;
84 suspendActiveAllocator->rw_header_chunk(WRITE, NULL,
85 (char *) &node, sizeof(int));
88 /* load_dyn_pageflags
90 * Description: Load a set of pageflags.
91 * Arguments: dyn_pageflags_t *: Pointer to the bitmap being loaded.
92 * (It must be allocated before calling this routine).
95 int load_dyn_pageflags(dyn_pageflags_t pagemap)
97 int i, zone_idx, zone_check = 0, size, node = 0;
98 struct zone *zone;
99 struct pglist_data *pgdat;
101 if (!pagemap)
102 return 1;
104 for_each_online_pgdat(pgdat) {
105 for (zone_idx = 0; zone_idx < MAX_NR_ZONES; zone_idx++) {
106 zone = &pgdat->node_zones[zone_idx];
108 if (!populated_zone(zone))
109 continue;
111 /* Same node? */
112 suspendActiveAllocator->rw_header_chunk(READ, NULL,
113 (char *) &zone_check, sizeof(int));
114 if (zone_check != node) {
115 printk("Node read (%d) != node (%d).\n",
116 zone_check, node);
117 return 1;
120 /* Same zone? */
121 suspendActiveAllocator->rw_header_chunk(READ, NULL,
122 (char *) &zone_check, sizeof(int));
123 if (zone_check != zone_idx) {
124 printk("Zone read (%d) != node (%d).\n",
125 zone_check, zone_idx);
126 return 1;
130 suspendActiveAllocator->rw_header_chunk(READ, NULL,
131 (char *) &size, sizeof(int));
133 for (i = 0; i < size; i++)
134 suspendActiveAllocator->rw_header_chunk(READ, NULL,
135 (char *) pagemap[node][zone_idx][i],
136 PAGE_SIZE);
138 node++;
140 suspendActiveAllocator->rw_header_chunk(READ, NULL, (char *) &zone_check,
141 sizeof(int));
142 if (zone_check != -1) {
143 printk("Didn't read end of dyn pageflag data marker.(%x)\n",
144 zone_check);
145 return 1;
148 return 0;