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 --- |