diff options
author | Nigel Cunningham <nigel@tuxonice.net> | 2009-12-06 10:15:53 -0500 |
---|---|---|
committer | Rafael J. Wysocki <rjw@sisk.pl> | 2009-12-06 10:15:53 -0500 |
commit | 0414f2ec03d72dc4e569627e6112fa6dafc99a79 (patch) | |
tree | 679fe5c0b89cc58194d187e25787f79bb7da3441 /kernel/power/swap.c | |
parent | 64357ed468025614d48daa6cc87674ae5616f8fb (diff) |
PM / Hibernate: Move swap functions to kernel/power/swap.c.
Move hibernation code's functions for allocating and freeing swap
from swsusp.c to swap.c, which is where you'd expect to find them.
Signed-off-by: Nigel Cunningham <nigel@tuxonice.net>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Diffstat (limited to 'kernel/power/swap.c')
-rw-r--r-- | kernel/power/swap.c | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/kernel/power/swap.c b/kernel/power/swap.c index 890f6b11b1d3..0ce9b00f5d33 100644 --- a/kernel/power/swap.c +++ b/kernel/power/swap.c | |||
@@ -38,6 +38,107 @@ struct swsusp_header { | |||
38 | 38 | ||
39 | static struct swsusp_header *swsusp_header; | 39 | static struct swsusp_header *swsusp_header; |
40 | 40 | ||
41 | /** | ||
42 | * The following functions are used for tracing the allocated | ||
43 | * swap pages, so that they can be freed in case of an error. | ||
44 | */ | ||
45 | |||
46 | struct swsusp_extent { | ||
47 | struct rb_node node; | ||
48 | unsigned long start; | ||
49 | unsigned long end; | ||
50 | }; | ||
51 | |||
52 | static struct rb_root swsusp_extents = RB_ROOT; | ||
53 | |||
54 | static int swsusp_extents_insert(unsigned long swap_offset) | ||
55 | { | ||
56 | struct rb_node **new = &(swsusp_extents.rb_node); | ||
57 | struct rb_node *parent = NULL; | ||
58 | struct swsusp_extent *ext; | ||
59 | |||
60 | /* Figure out where to put the new node */ | ||
61 | while (*new) { | ||
62 | ext = container_of(*new, struct swsusp_extent, node); | ||
63 | parent = *new; | ||
64 | if (swap_offset < ext->start) { | ||
65 | /* Try to merge */ | ||
66 | if (swap_offset == ext->start - 1) { | ||
67 | ext->start--; | ||
68 | return 0; | ||
69 | } | ||
70 | new = &((*new)->rb_left); | ||
71 | } else if (swap_offset > ext->end) { | ||
72 | /* Try to merge */ | ||
73 | if (swap_offset == ext->end + 1) { | ||
74 | ext->end++; | ||
75 | return 0; | ||
76 | } | ||
77 | new = &((*new)->rb_right); | ||
78 | } else { | ||
79 | /* It already is in the tree */ | ||
80 | return -EINVAL; | ||
81 | } | ||
82 | } | ||
83 | /* Add the new node and rebalance the tree. */ | ||
84 | ext = kzalloc(sizeof(struct swsusp_extent), GFP_KERNEL); | ||
85 | if (!ext) | ||
86 | return -ENOMEM; | ||
87 | |||
88 | ext->start = swap_offset; | ||
89 | ext->end = swap_offset; | ||
90 | rb_link_node(&ext->node, parent, new); | ||
91 | rb_insert_color(&ext->node, &swsusp_extents); | ||
92 | return 0; | ||
93 | } | ||
94 | |||
95 | /** | ||
96 | * alloc_swapdev_block - allocate a swap page and register that it has | ||
97 | * been allocated, so that it can be freed in case of an error. | ||
98 | */ | ||
99 | |||
100 | sector_t alloc_swapdev_block(int swap) | ||
101 | { | ||
102 | unsigned long offset; | ||
103 | |||
104 | offset = swp_offset(get_swap_page_of_type(swap)); | ||
105 | if (offset) { | ||
106 | if (swsusp_extents_insert(offset)) | ||
107 | swap_free(swp_entry(swap, offset)); | ||
108 | else | ||
109 | return swapdev_block(swap, offset); | ||
110 | } | ||
111 | return 0; | ||
112 | } | ||
113 | |||
114 | /** | ||
115 | * free_all_swap_pages - free swap pages allocated for saving image data. | ||
116 | * It also frees the extents used to register which swap entres had been | ||
117 | * allocated. | ||
118 | */ | ||
119 | |||
120 | void free_all_swap_pages(int swap) | ||
121 | { | ||
122 | struct rb_node *node; | ||
123 | |||
124 | while ((node = swsusp_extents.rb_node)) { | ||
125 | struct swsusp_extent *ext; | ||
126 | unsigned long offset; | ||
127 | |||
128 | ext = container_of(node, struct swsusp_extent, node); | ||
129 | rb_erase(node, &swsusp_extents); | ||
130 | for (offset = ext->start; offset <= ext->end; offset++) | ||
131 | swap_free(swp_entry(swap, offset)); | ||
132 | |||
133 | kfree(ext); | ||
134 | } | ||
135 | } | ||
136 | |||
137 | int swsusp_swap_in_use(void) | ||
138 | { | ||
139 | return (swsusp_extents.rb_node != NULL); | ||
140 | } | ||
141 | |||
41 | /* | 142 | /* |
42 | * General things | 143 | * General things |
43 | */ | 144 | */ |