swap.c (3fc6b34f4803b959c1e30c15247e2180cd529115) swap.c (3aef83e0ef1ffb8ea3bea97be46821a45c952173)
1/*
2 * linux/kernel/power/swap.c
3 *
4 * This file provides functions for reading the suspend image from
5 * and writing it to a swap partition.
6 *
7 * Copyright (C) 1998,2001-2005 Pavel Machek <pavel@suse.cz>
8 * Copyright (C) 2006 Rafael J. Wysocki <rjw@sisk.pl>

--- 20 unchanged lines hidden (view full) ---

29
30#include "power.h"
31
32extern char resume_file[];
33
34#define SWSUSP_SIG "S1SUSPEND"
35
36static struct swsusp_header {
1/*
2 * linux/kernel/power/swap.c
3 *
4 * This file provides functions for reading the suspend image from
5 * and writing it to a swap partition.
6 *
7 * Copyright (C) 1998,2001-2005 Pavel Machek <pavel@suse.cz>
8 * Copyright (C) 2006 Rafael J. Wysocki <rjw@sisk.pl>

--- 20 unchanged lines hidden (view full) ---

29
30#include "power.h"
31
32extern char resume_file[];
33
34#define SWSUSP_SIG "S1SUSPEND"
35
36static struct swsusp_header {
37 char reserved[PAGE_SIZE - 20 - sizeof(swp_entry_t)];
38 swp_entry_t image;
37 char reserved[PAGE_SIZE - 20 - sizeof(sector_t)];
38 sector_t image;
39 char orig_sig[10];
40 char sig[10];
41} __attribute__((packed, aligned(PAGE_SIZE))) swsusp_header;
42
43/*
44 * General things
45 */
46

--- 48 unchanged lines hidden (view full) ---

95 return 0;
96}
97
98static int bio_read_page(pgoff_t page_off, void *addr, struct bio **bio_chain)
99{
100 return submit(READ, page_off, virt_to_page(addr), bio_chain);
101}
102
39 char orig_sig[10];
40 char sig[10];
41} __attribute__((packed, aligned(PAGE_SIZE))) swsusp_header;
42
43/*
44 * General things
45 */
46

--- 48 unchanged lines hidden (view full) ---

95 return 0;
96}
97
98static int bio_read_page(pgoff_t page_off, void *addr, struct bio **bio_chain)
99{
100 return submit(READ, page_off, virt_to_page(addr), bio_chain);
101}
102
103static int bio_write_page(pgoff_t page_off, void *addr)
103static int bio_write_page(pgoff_t page_off, void *addr, struct bio **bio_chain)
104{
104{
105 return submit(WRITE, page_off, virt_to_page(addr), NULL);
105 return submit(WRITE, page_off, virt_to_page(addr), bio_chain);
106}
107
108static int wait_on_bio_chain(struct bio **bio_chain)
109{
110 struct bio *bio;
111 struct bio *next_bio;
112 int ret = 0;
113

--- 38 unchanged lines hidden (view full) ---

152 centisecs / 100, centisecs % 100,
153 kps / 1000, (kps % 1000) / 10);
154}
155
156/*
157 * Saving part
158 */
159
106}
107
108static int wait_on_bio_chain(struct bio **bio_chain)
109{
110 struct bio *bio;
111 struct bio *next_bio;
112 int ret = 0;
113

--- 38 unchanged lines hidden (view full) ---

152 centisecs / 100, centisecs % 100,
153 kps / 1000, (kps % 1000) / 10);
154}
155
156/*
157 * Saving part
158 */
159
160static int mark_swapfiles(swp_entry_t start)
160static int mark_swapfiles(sector_t start)
161{
162 int error;
163
161{
162 int error;
163
164 rw_swap_page_sync(READ, swp_entry(root_swap, 0),
165 virt_to_page((unsigned long)&swsusp_header), NULL);
164 bio_read_page(0, &swsusp_header, NULL);
166 if (!memcmp("SWAP-SPACE",swsusp_header.sig, 10) ||
167 !memcmp("SWAPSPACE2",swsusp_header.sig, 10)) {
168 memcpy(swsusp_header.orig_sig,swsusp_header.sig, 10);
169 memcpy(swsusp_header.sig,SWSUSP_SIG, 10);
170 swsusp_header.image = start;
165 if (!memcmp("SWAP-SPACE",swsusp_header.sig, 10) ||
166 !memcmp("SWAPSPACE2",swsusp_header.sig, 10)) {
167 memcpy(swsusp_header.orig_sig,swsusp_header.sig, 10);
168 memcpy(swsusp_header.sig,SWSUSP_SIG, 10);
169 swsusp_header.image = start;
171 error = rw_swap_page_sync(WRITE, swp_entry(root_swap, 0),
172 virt_to_page((unsigned long)&swsusp_header),
173 NULL);
170 error = bio_write_page(0, &swsusp_header, NULL);
174 } else {
171 } else {
175 pr_debug("swsusp: Partition is not swap space.\n");
172 printk(KERN_ERR "swsusp: Swap header not found!\n");
176 error = -ENODEV;
177 }
178 return error;
179}
180
181/**
182 * swsusp_swap_check - check if the resume device is a swap device
183 * and get its index (if so)
184 */
185
186static int swsusp_swap_check(void) /* This is called before saving image */
187{
173 error = -ENODEV;
174 }
175 return error;
176}
177
178/**
179 * swsusp_swap_check - check if the resume device is a swap device
180 * and get its index (if so)
181 */
182
183static int swsusp_swap_check(void) /* This is called before saving image */
184{
188 int res = swap_type_of(swsusp_resume_device, 0);
185 int res;
189
186
190 if (res >= 0) {
191 root_swap = res;
192 return 0;
193 }
187 res = swap_type_of(swsusp_resume_device, 0);
188 if (res < 0)
189 return res;
190
191 root_swap = res;
192 resume_bdev = open_by_devnum(swsusp_resume_device, FMODE_WRITE);
193 if (IS_ERR(resume_bdev))
194 return PTR_ERR(resume_bdev);
195
196 res = set_blocksize(resume_bdev, PAGE_SIZE);
197 if (res < 0)
198 blkdev_put(resume_bdev);
199
194 return res;
195}
196
197/**
198 * write_page - Write one page to given swap location.
199 * @buf: Address we're writing.
200 * @offset: Offset of the swap page we're writing to.
201 * @bio_chain: Link the next write BIO here
202 */
203
200 return res;
201}
202
203/**
204 * write_page - Write one page to given swap location.
205 * @buf: Address we're writing.
206 * @offset: Offset of the swap page we're writing to.
207 * @bio_chain: Link the next write BIO here
208 */
209
204static int write_page(void *buf, unsigned long offset, struct bio **bio_chain)
210static int write_page(void *buf, sector_t offset, struct bio **bio_chain)
205{
211{
206 swp_entry_t entry;
207 int error = -ENOSPC;
212 void *src;
208
213
209 if (offset) {
210 struct page *page = virt_to_page(buf);
214 if (!offset)
215 return -ENOSPC;
211
216
212 if (bio_chain) {
213 /*
214 * Whether or not we successfully allocated a copy page,
215 * we take a ref on the page here. It gets undone in
216 * wait_on_bio_chain().
217 */
218 struct page *page_copy;
219 page_copy = alloc_page(GFP_ATOMIC);
220 if (page_copy == NULL) {
221 WARN_ON_ONCE(1);
222 bio_chain = NULL; /* Go synchronous */
223 get_page(page);
224 } else {
225 memcpy(page_address(page_copy),
226 page_address(page), PAGE_SIZE);
227 page = page_copy;
228 }
217 if (bio_chain) {
218 src = (void *)__get_free_page(GFP_ATOMIC);
219 if (src) {
220 memcpy(src, buf, PAGE_SIZE);
221 } else {
222 WARN_ON_ONCE(1);
223 bio_chain = NULL; /* Go synchronous */
224 src = buf;
229 }
225 }
230 entry = swp_entry(root_swap, offset);
231 error = rw_swap_page_sync(WRITE, entry, page, bio_chain);
226 } else {
227 src = buf;
232 }
228 }
233 return error;
229 return bio_write_page(offset, src, bio_chain);
234}
235
236/*
237 * The swap map is a data structure used for keeping track of each page
238 * written to a swap partition. It consists of many swap_map_page
239 * structures that contain each an array of MAP_PAGE_SIZE swap entries.
240 * These structures are stored on the swap and linked together with the
241 * help of the .next_swap member.
242 *
243 * The swap map is created during suspend. The swap map pages are
244 * allocated and populated one at a time, so we only need one memory
245 * page to set up the entire structure.
246 *
247 * During resume we also only need to use one swap_map_page structure
248 * at a time.
249 */
250
230}
231
232/*
233 * The swap map is a data structure used for keeping track of each page
234 * written to a swap partition. It consists of many swap_map_page
235 * structures that contain each an array of MAP_PAGE_SIZE swap entries.
236 * These structures are stored on the swap and linked together with the
237 * help of the .next_swap member.
238 *
239 * The swap map is created during suspend. The swap map pages are
240 * allocated and populated one at a time, so we only need one memory
241 * page to set up the entire structure.
242 *
243 * During resume we also only need to use one swap_map_page structure
244 * at a time.
245 */
246
251#define MAP_PAGE_ENTRIES (PAGE_SIZE / sizeof(long) - 1)
247#define MAP_PAGE_ENTRIES (PAGE_SIZE / sizeof(sector_t) - 1)
252
253struct swap_map_page {
248
249struct swap_map_page {
254 unsigned long entries[MAP_PAGE_ENTRIES];
255 unsigned long next_swap;
250 sector_t entries[MAP_PAGE_ENTRIES];
251 sector_t next_swap;
256};
257
258/**
259 * The swap_map_handle structure is used for handling swap in
260 * a file-alike way
261 */
262
263struct swap_map_handle {
264 struct swap_map_page *cur;
252};
253
254/**
255 * The swap_map_handle structure is used for handling swap in
256 * a file-alike way
257 */
258
259struct swap_map_handle {
260 struct swap_map_page *cur;
265 unsigned long cur_swap;
261 sector_t cur_swap;
266 struct bitmap_page *bitmap;
267 unsigned int k;
268};
269
270static void release_swap_writer(struct swap_map_handle *handle)
271{
272 if (handle->cur)
273 free_page((unsigned long)handle->cur);

--- 8 unchanged lines hidden (view full) ---

282 handle->cur = (struct swap_map_page *)get_zeroed_page(GFP_KERNEL);
283 if (!handle->cur)
284 return -ENOMEM;
285 handle->bitmap = alloc_bitmap(count_swap_pages(root_swap, 0));
286 if (!handle->bitmap) {
287 release_swap_writer(handle);
288 return -ENOMEM;
289 }
262 struct bitmap_page *bitmap;
263 unsigned int k;
264};
265
266static void release_swap_writer(struct swap_map_handle *handle)
267{
268 if (handle->cur)
269 free_page((unsigned long)handle->cur);

--- 8 unchanged lines hidden (view full) ---

278 handle->cur = (struct swap_map_page *)get_zeroed_page(GFP_KERNEL);
279 if (!handle->cur)
280 return -ENOMEM;
281 handle->bitmap = alloc_bitmap(count_swap_pages(root_swap, 0));
282 if (!handle->bitmap) {
283 release_swap_writer(handle);
284 return -ENOMEM;
285 }
290 handle->cur_swap = alloc_swap_page(root_swap, handle->bitmap);
286 handle->cur_swap = alloc_swapdev_block(root_swap, handle->bitmap);
291 if (!handle->cur_swap) {
292 release_swap_writer(handle);
293 return -ENOSPC;
294 }
295 handle->k = 0;
296 return 0;
297}
298
299static int swap_write_page(struct swap_map_handle *handle, void *buf,
300 struct bio **bio_chain)
301{
302 int error = 0;
287 if (!handle->cur_swap) {
288 release_swap_writer(handle);
289 return -ENOSPC;
290 }
291 handle->k = 0;
292 return 0;
293}
294
295static int swap_write_page(struct swap_map_handle *handle, void *buf,
296 struct bio **bio_chain)
297{
298 int error = 0;
303 unsigned long offset;
299 sector_t offset;
304
305 if (!handle->cur)
306 return -EINVAL;
300
301 if (!handle->cur)
302 return -EINVAL;
307 offset = alloc_swap_page(root_swap, handle->bitmap);
303 offset = alloc_swapdev_block(root_swap, handle->bitmap);
308 error = write_page(buf, offset, bio_chain);
309 if (error)
310 return error;
311 handle->cur->entries[handle->k++] = offset;
312 if (handle->k >= MAP_PAGE_ENTRIES) {
313 error = wait_on_bio_chain(bio_chain);
314 if (error)
315 goto out;
304 error = write_page(buf, offset, bio_chain);
305 if (error)
306 return error;
307 handle->cur->entries[handle->k++] = offset;
308 if (handle->k >= MAP_PAGE_ENTRIES) {
309 error = wait_on_bio_chain(bio_chain);
310 if (error)
311 goto out;
316 offset = alloc_swap_page(root_swap, handle->bitmap);
312 offset = alloc_swapdev_block(root_swap, handle->bitmap);
317 if (!offset)
318 return -ENOSPC;
319 handle->cur->next_swap = offset;
320 error = write_page(handle->cur, handle->cur_swap, NULL);
321 if (error)
322 goto out;
323 memset(handle->cur, 0, PAGE_SIZE);
324 handle->cur_swap = offset;

--- 83 unchanged lines hidden (view full) ---

408
409int swsusp_write(void)
410{
411 struct swap_map_handle handle;
412 struct snapshot_handle snapshot;
413 struct swsusp_info *header;
414 int error;
415
313 if (!offset)
314 return -ENOSPC;
315 handle->cur->next_swap = offset;
316 error = write_page(handle->cur, handle->cur_swap, NULL);
317 if (error)
318 goto out;
319 memset(handle->cur, 0, PAGE_SIZE);
320 handle->cur_swap = offset;

--- 83 unchanged lines hidden (view full) ---

404
405int swsusp_write(void)
406{
407 struct swap_map_handle handle;
408 struct snapshot_handle snapshot;
409 struct swsusp_info *header;
410 int error;
411
416 if ((error = swsusp_swap_check())) {
412 error = swsusp_swap_check();
413 if (error) {
417 printk(KERN_ERR "swsusp: Cannot find swap device, try "
418 "swapon -a.\n");
419 return error;
420 }
421 memset(&snapshot, 0, sizeof(struct snapshot_handle));
422 error = snapshot_read_next(&snapshot, PAGE_SIZE);
414 printk(KERN_ERR "swsusp: Cannot find swap device, try "
415 "swapon -a.\n");
416 return error;
417 }
418 memset(&snapshot, 0, sizeof(struct snapshot_handle));
419 error = snapshot_read_next(&snapshot, PAGE_SIZE);
423 if (error < PAGE_SIZE)
424 return error < 0 ? error : -EFAULT;
420 if (error < PAGE_SIZE) {
421 if (error >= 0)
422 error = -EFAULT;
423
424 goto out;
425 }
425 header = (struct swsusp_info *)data_of(snapshot);
426 if (!enough_swap(header->pages)) {
427 printk(KERN_ERR "swsusp: Not enough free swap\n");
426 header = (struct swsusp_info *)data_of(snapshot);
427 if (!enough_swap(header->pages)) {
428 printk(KERN_ERR "swsusp: Not enough free swap\n");
428 return -ENOSPC;
429 error = -ENOSPC;
430 goto out;
429 }
430 error = get_swap_writer(&handle);
431 if (!error) {
431 }
432 error = get_swap_writer(&handle);
433 if (!error) {
432 unsigned long start = handle.cur_swap;
434 sector_t start = handle.cur_swap;
435
433 error = swap_write_page(&handle, header, NULL);
434 if (!error)
435 error = save_image(&handle, &snapshot,
436 header->pages - 1);
436 error = swap_write_page(&handle, header, NULL);
437 if (!error)
438 error = save_image(&handle, &snapshot,
439 header->pages - 1);
440
437 if (!error) {
438 flush_swap_writer(&handle);
439 printk("S");
441 if (!error) {
442 flush_swap_writer(&handle);
443 printk("S");
440 error = mark_swapfiles(swp_entry(root_swap, start));
444 error = mark_swapfiles(start);
441 printk("|\n");
442 }
443 }
444 if (error)
445 free_all_swap_pages(root_swap, handle.bitmap);
446 release_swap_writer(&handle);
445 printk("|\n");
446 }
447 }
448 if (error)
449 free_all_swap_pages(root_swap, handle.bitmap);
450 release_swap_writer(&handle);
451out:
452 swsusp_close();
447 return error;
448}
449
450/**
451 * The following functions allow us to read data using a swap map
452 * in a file-alike way
453 */
454
455static void release_swap_reader(struct swap_map_handle *handle)
456{
457 if (handle->cur)
458 free_page((unsigned long)handle->cur);
459 handle->cur = NULL;
460}
461
453 return error;
454}
455
456/**
457 * The following functions allow us to read data using a swap map
458 * in a file-alike way
459 */
460
461static void release_swap_reader(struct swap_map_handle *handle)
462{
463 if (handle->cur)
464 free_page((unsigned long)handle->cur);
465 handle->cur = NULL;
466}
467
462static int get_swap_reader(struct swap_map_handle *handle,
463 swp_entry_t start)
468static int get_swap_reader(struct swap_map_handle *handle, sector_t start)
464{
465 int error;
466
469{
470 int error;
471
467 if (!swp_offset(start))
472 if (!start)
468 return -EINVAL;
473 return -EINVAL;
474
469 handle->cur = (struct swap_map_page *)get_zeroed_page(GFP_ATOMIC);
470 if (!handle->cur)
471 return -ENOMEM;
475 handle->cur = (struct swap_map_page *)get_zeroed_page(GFP_ATOMIC);
476 if (!handle->cur)
477 return -ENOMEM;
472 error = bio_read_page(swp_offset(start), handle->cur, NULL);
478
479 error = bio_read_page(start, handle->cur, NULL);
473 if (error) {
474 release_swap_reader(handle);
475 return error;
476 }
477 handle->k = 0;
478 return 0;
479}
480
481static int swap_read_page(struct swap_map_handle *handle, void *buf,
482 struct bio **bio_chain)
483{
480 if (error) {
481 release_swap_reader(handle);
482 return error;
483 }
484 handle->k = 0;
485 return 0;
486}
487
488static int swap_read_page(struct swap_map_handle *handle, void *buf,
489 struct bio **bio_chain)
490{
484 unsigned long offset;
491 sector_t offset;
485 int error;
486
487 if (!handle->cur)
488 return -EINVAL;
489 offset = handle->cur->entries[handle->k];
490 if (!offset)
491 return -EFAULT;
492 error = bio_read_page(offset, buf, bio_chain);

--- 110 unchanged lines hidden (view full) ---

603 if (!IS_ERR(resume_bdev)) {
604 set_blocksize(resume_bdev, PAGE_SIZE);
605 memset(&swsusp_header, 0, sizeof(swsusp_header));
606 if ((error = bio_read_page(0, &swsusp_header, NULL)))
607 return error;
608 if (!memcmp(SWSUSP_SIG, swsusp_header.sig, 10)) {
609 memcpy(swsusp_header.sig, swsusp_header.orig_sig, 10);
610 /* Reset swap signature now */
492 int error;
493
494 if (!handle->cur)
495 return -EINVAL;
496 offset = handle->cur->entries[handle->k];
497 if (!offset)
498 return -EFAULT;
499 error = bio_read_page(offset, buf, bio_chain);

--- 110 unchanged lines hidden (view full) ---

610 if (!IS_ERR(resume_bdev)) {
611 set_blocksize(resume_bdev, PAGE_SIZE);
612 memset(&swsusp_header, 0, sizeof(swsusp_header));
613 if ((error = bio_read_page(0, &swsusp_header, NULL)))
614 return error;
615 if (!memcmp(SWSUSP_SIG, swsusp_header.sig, 10)) {
616 memcpy(swsusp_header.sig, swsusp_header.orig_sig, 10);
617 /* Reset swap signature now */
611 error = bio_write_page(0, &swsusp_header);
618 error = bio_write_page(0, &swsusp_header, NULL);
612 } else {
613 return -EINVAL;
614 }
615 if (error)
616 blkdev_put(resume_bdev);
617 else
618 pr_debug("swsusp: Signature found, resuming\n");
619 } else {

--- 22 unchanged lines hidden ---
619 } else {
620 return -EINVAL;
621 }
622 if (error)
623 blkdev_put(resume_bdev);
624 else
625 pr_debug("swsusp: Signature found, resuming\n");
626 } else {

--- 22 unchanged lines hidden ---