aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2006-12-06 23:34:07 -0500
committerLinus Torvalds <torvalds@woody.osdl.org>2006-12-07 11:39:27 -0500
commit915bae9ebe41e52d71ad8b06d50e4ab26189f964 (patch)
treedaf0c9a370d3a551c1bb5beea69a3a0cfecd9885
parent3592695c363c3f3119621bdcf5ed852d6b9d1a5c (diff)
[PATCH] swsusp: use partition device and offset to identify swap areas
The Linux kernel handles swap files almost in the same way as it handles swap partitions and there are only two differences between these two types of swap areas: (1) swap files need not be contiguous, (2) the header of a swap file is not in the first block of the partition that holds it. From the swsusp's point of view (1) is not a problem, because it is already taken care of by the swap-handling code, but (2) has to be taken into consideration. In principle the location of a swap file's header may be determined with the help of appropriate filesystem driver. Unfortunately, however, it requires the filesystem holding the swap file to be mounted, and if this filesystem is journaled, it cannot be mounted during a resume from disk. For this reason we need some other means by which swap areas can be identified. For example, to identify a swap area we can use the partition that holds the area and the offset from the beginning of this partition at which the swap header is located. The following patch allows swsusp to identify swap areas this way. It changes swap_type_of() so that it takes an additional argument representing an offset of the swap header within the partition represented by its first argument. Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> Acked-by: Pavel Machek <pavel@ucw.cz> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--include/linux/swap.h2
-rw-r--r--kernel/power/swap.c2
-rw-r--r--kernel/power/user.c5
-rw-r--r--mm/swapfile.c38
4 files changed, 31 insertions, 16 deletions
diff --git a/include/linux/swap.h b/include/linux/swap.h
index 89f8a39773bf..d51e35e4e168 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -247,7 +247,7 @@ extern int swap_duplicate(swp_entry_t);
247extern int valid_swaphandles(swp_entry_t, unsigned long *); 247extern int valid_swaphandles(swp_entry_t, unsigned long *);
248extern void swap_free(swp_entry_t); 248extern void swap_free(swp_entry_t);
249extern void free_swap_and_cache(swp_entry_t); 249extern void free_swap_and_cache(swp_entry_t);
250extern int swap_type_of(dev_t); 250extern int swap_type_of(dev_t, sector_t);
251extern unsigned int count_swap_pages(int, int); 251extern unsigned int count_swap_pages(int, int);
252extern sector_t map_swap_page(struct swap_info_struct *, pgoff_t); 252extern sector_t map_swap_page(struct swap_info_struct *, pgoff_t);
253extern struct swap_info_struct *get_swap_info_struct(unsigned); 253extern struct swap_info_struct *get_swap_info_struct(unsigned);
diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index 1a3b0dd2c3fc..7b10da16389e 100644
--- a/kernel/power/swap.c
+++ b/kernel/power/swap.c
@@ -74,7 +74,7 @@ static int mark_swapfiles(swp_entry_t start)
74 74
75static int swsusp_swap_check(void) /* This is called before saving image */ 75static int swsusp_swap_check(void) /* This is called before saving image */
76{ 76{
77 int res = swap_type_of(swsusp_resume_device); 77 int res = swap_type_of(swsusp_resume_device, 0);
78 78
79 if (res >= 0) { 79 if (res >= 0) {
80 root_swap = res; 80 root_swap = res;
diff --git a/kernel/power/user.c b/kernel/power/user.c
index 4c24ca5d62e3..a327b18a5ffd 100644
--- a/kernel/power/user.c
+++ b/kernel/power/user.c
@@ -55,7 +55,8 @@ static int snapshot_open(struct inode *inode, struct file *filp)
55 filp->private_data = data; 55 filp->private_data = data;
56 memset(&data->handle, 0, sizeof(struct snapshot_handle)); 56 memset(&data->handle, 0, sizeof(struct snapshot_handle));
57 if ((filp->f_flags & O_ACCMODE) == O_RDONLY) { 57 if ((filp->f_flags & O_ACCMODE) == O_RDONLY) {
58 data->swap = swsusp_resume_device ? swap_type_of(swsusp_resume_device) : -1; 58 data->swap = swsusp_resume_device ?
59 swap_type_of(swsusp_resume_device, 0) : -1;
59 data->mode = O_RDONLY; 60 data->mode = O_RDONLY;
60 } else { 61 } else {
61 data->swap = -1; 62 data->swap = -1;
@@ -265,7 +266,7 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp,
265 * so we need to recode them 266 * so we need to recode them
266 */ 267 */
267 if (old_decode_dev(arg)) { 268 if (old_decode_dev(arg)) {
268 data->swap = swap_type_of(old_decode_dev(arg)); 269 data->swap = swap_type_of(old_decode_dev(arg), 0);
269 if (data->swap < 0) 270 if (data->swap < 0)
270 error = -ENODEV; 271 error = -ENODEV;
271 } else { 272 } else {
diff --git a/mm/swapfile.c b/mm/swapfile.c
index f315131db006..2bfacbac0f4c 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -427,34 +427,48 @@ void free_swap_and_cache(swp_entry_t entry)
427 427
428#ifdef CONFIG_SOFTWARE_SUSPEND 428#ifdef CONFIG_SOFTWARE_SUSPEND
429/* 429/*
430 * Find the swap type that corresponds to given device (if any) 430 * Find the swap type that corresponds to given device (if any).
431 * 431 *
432 * This is needed for software suspend and is done in such a way that inode 432 * @offset - number of the PAGE_SIZE-sized block of the device, starting
433 * aliasing is allowed. 433 * from 0, in which the swap header is expected to be located.
434 *
435 * This is needed for the suspend to disk (aka swsusp).
434 */ 436 */
435int swap_type_of(dev_t device) 437int swap_type_of(dev_t device, sector_t offset)
436{ 438{
439 struct block_device *bdev = NULL;
437 int i; 440 int i;
438 441
442 if (device)
443 bdev = bdget(device);
444
439 spin_lock(&swap_lock); 445 spin_lock(&swap_lock);
440 for (i = 0; i < nr_swapfiles; i++) { 446 for (i = 0; i < nr_swapfiles; i++) {
441 struct inode *inode; 447 struct swap_info_struct *sis = swap_info + i;
442 448
443 if (!(swap_info[i].flags & SWP_WRITEOK)) 449 if (!(sis->flags & SWP_WRITEOK))
444 continue; 450 continue;
445 451
446 if (!device) { 452 if (!bdev) {
447 spin_unlock(&swap_lock); 453 spin_unlock(&swap_lock);
448 return i; 454 return i;
449 } 455 }
450 inode = swap_info[i].swap_file->f_dentry->d_inode; 456 if (bdev == sis->bdev) {
451 if (S_ISBLK(inode->i_mode) && 457 struct swap_extent *se;
452 device == MKDEV(imajor(inode), iminor(inode))) { 458
453 spin_unlock(&swap_lock); 459 se = list_entry(sis->extent_list.next,
454 return i; 460 struct swap_extent, list);
461 if (se->start_block == offset) {
462 spin_unlock(&swap_lock);
463 bdput(bdev);
464 return i;
465 }
455 } 466 }
456 } 467 }
457 spin_unlock(&swap_lock); 468 spin_unlock(&swap_lock);
469 if (bdev)
470 bdput(bdev);
471
458 return -ENODEV; 472 return -ENODEV;
459} 473}
460 474