2 * kernel/power/tuxonice_pageflags.c
4 * Copyright (C) 2004-2007 Nigel Cunningham (nigel at suspend2 net)
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>
14 #include <linux/module.h>
15 #include <linux/bitops.h>
16 #include <linux/list.h>
17 #include <linux/suspend.h>
18 #include "tuxonice_pageflags.h"
19 #include "tuxonice_modules.h"
20 #include "tuxonice_pagedir.h"
23 dyn_pageflags_t pageset2_map
;
24 dyn_pageflags_t page_resave_map
;
25 dyn_pageflags_t io_map
;
26 dyn_pageflags_t nosave_map
;
27 dyn_pageflags_t free_map
;
29 static int pages_for_zone(struct zone
*zone
)
31 return DIV_ROUND_UP(zone
->spanned_pages
, (PAGE_SIZE
<< 3));
34 int toi_pageflags_space_needed(void)
40 if (populated_zone(zone
))
41 total
+= sizeof(int) * 3 + pages_for_zone(zone
) * PAGE_SIZE
;
50 * Description: Save a set of pageflags.
51 * Arguments: dyn_pageflags_t *: Pointer to the bitmap being saved.
54 void save_dyn_pageflags(dyn_pageflags_t pagemap
)
56 int i
, zone_idx
, size
, node
= 0;
58 struct pglist_data
*pgdat
;
63 for_each_online_pgdat(pgdat
) {
64 for (zone_idx
= 0; zone_idx
< MAX_NR_ZONES
; zone_idx
++) {
65 zone
= &pgdat
->node_zones
[zone_idx
];
67 if (!populated_zone(zone
))
70 toiActiveAllocator
->rw_header_chunk(WRITE
, NULL
,
71 (char *) &node
, sizeof(int));
72 toiActiveAllocator
->rw_header_chunk(WRITE
, NULL
,
73 (char *) &zone_idx
, sizeof(int));
74 size
= pages_for_zone(zone
);
75 toiActiveAllocator
->rw_header_chunk(WRITE
, NULL
,
76 (char *) &size
, sizeof(int));
78 for (i
= 0; i
< size
; i
++)
79 toiActiveAllocator
->rw_header_chunk(WRITE
,
80 NULL
, (char *) pagemap
[node
][zone_idx
][i
],
86 toiActiveAllocator
->rw_header_chunk(WRITE
, NULL
,
87 (char *) &node
, sizeof(int));
92 * Description: Load a set of pageflags.
93 * Arguments: dyn_pageflags_t *: Pointer to the bitmap being loaded.
94 * (It must be allocated before calling this routine).
97 int load_dyn_pageflags(dyn_pageflags_t pagemap
)
99 int i
, zone_idx
, zone_check
= 0, size
, node
= 0;
101 struct pglist_data
*pgdat
;
106 for_each_online_pgdat(pgdat
) {
107 for (zone_idx
= 0; zone_idx
< MAX_NR_ZONES
; zone_idx
++) {
108 zone
= &pgdat
->node_zones
[zone_idx
];
110 if (!populated_zone(zone
))
114 toiActiveAllocator
->rw_header_chunk(READ
, NULL
,
115 (char *) &zone_check
, sizeof(int));
116 if (zone_check
!= node
) {
117 printk("Node read (%d) != node (%d).\n",
123 toiActiveAllocator
->rw_header_chunk(READ
, NULL
,
124 (char *) &zone_check
, sizeof(int));
125 if (zone_check
!= zone_idx
) {
126 printk("Zone read (%d) != node (%d).\n",
127 zone_check
, zone_idx
);
132 toiActiveAllocator
->rw_header_chunk(READ
, NULL
,
133 (char *) &size
, sizeof(int));
135 for (i
= 0; i
< size
; i
++)
136 toiActiveAllocator
->rw_header_chunk(READ
, NULL
,
137 (char *) pagemap
[node
][zone_idx
][i
],
142 toiActiveAllocator
->rw_header_chunk(READ
, NULL
, (char *) &zone_check
,
144 if (zone_check
!= -1) {
145 printk("Didn't read end of dyn pageflag data marker.(%x)\n",