2 * kernel/power/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 "pageflags.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)
38 if (populated_zone(zone
))
39 total
+= sizeof(int) * 3 + pages_for_zone(zone
) * PAGE_SIZE
;
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;
56 struct pglist_data
*pgdat
;
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
))
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
],
84 suspendActiveAllocator
->rw_header_chunk(WRITE
, NULL
,
85 (char *) &node
, sizeof(int));
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;
99 struct pglist_data
*pgdat
;
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
))
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",
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
);
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
],
140 suspendActiveAllocator
->rw_header_chunk(READ
, NULL
, (char *) &zone_check
,
142 if (zone_check
!= -1) {
143 printk("Didn't read end of dyn pageflag data marker.(%x)\n",