lkml.org 
[lkml]   [2004]   [May]   [10]   [last100]   RSS Feed
Views: [more markup]  [less markup]  [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Subject[PATCH] 2.6.6 swsusp.c: allow device aliasing
FromSau Dan Lee <>
Date10 May 2004 18:22:39 +0200
swsusp has  been working on my  notebook on 2.6.2 and  2.6.5, but does
not work on 2.6.6.  It  panics.  Here are the 'dmesg' after activating
swsusp: (The number of "=" and  "." aren't correct, and I have retyped
them from the console message.)

        ACPI: (supports S0 S1 S3 S4 S5)
        Stopping tasks: =================================|
        Freeing memory: .............|
        /critical section: counting pages to copy.[no save pfn 0x338].....
         (pages needed: 12532+512=13044 free: 28407)
        Alloc pagedir
        .[nosave pfn 0x338]......................
        critical section/: done (12532 pages copied)
        Writing data to swap (12532 pages): . <0>Kernel panic:
        Not enough swapspace when writing data
         <3>swap_free: Unused swap file entry 0000003d
Here is another trial:


        ACPI: (supports S0 S1 S3 S4 S5)
        Stopping tasks: =================================|
        Freeing memory: .............|
        /critical section: counting pages to copy.
              [nosave pfn 0x338].................. 
              (pages needed: 12191+512=12703 free: 28748)
        Alloc pagedir
        .[nosave pfn 0x338].....................critical section/:
              done 912191 pages copied)
        Writing data to swap (12191 pages): .<0>Kernel panic:
        Not enough swapspace when writing data
        swap_free: Unused swap file entry 00000026

Cause:


I'm  using  devfs.   (I'm   using  /dev/hda7  for  swsusp.)   So,  cat
/proc/swaps shows my swap device as:

    Filename                                Type      Size  Used Priority
    /dev/ide/host0/bus0/target0/lun0/part7  partition 498920  0   -1

whereas  I  specify  "resume=/dev/hda7"  as a  boot  parameter.   Upon
suspend, swsusp can't find a swap device exactly named "/dev/hda7" and
hence thinks there is no swapspace.


The problem is that:

1) Upon suspend, kernel/power/swsusp.c compares the devices names
   "/dev/hda7" and "/dev/ide/.../part7" and they don't match.  So
   swsusp refuses to suspend to the swap partition.  Changing the
   boot parameter to "resume=/dev/ide/host0/bus0/target0/lun0/part7"
   solves this problem, BUT:

2) Upon resume, kernel/power/swsusp.c doesn't understand what a device
   "/dev/ide/host0/bus0/target0/lun0/part7" is.  It only knows what
   "/dev/hda7".  So, I have to set "resume=/dev/hda7" for resume to
   work.  But this would create problem (1).

So, I can't get both suspend and resume to work!  :(

Why did it  work in pre-2.6.6?  Because that check  in swsusp.c in pre
2.6.6 didn't really check if  the device is correct upon suspend.  The
suspend code  only writes  the suspend/resume data  to the  FIRST swap
device.  2.6.6 has corrected this bug, but can't equate "/dev/hda7" to
"/dev/ide/host0/bus0/target0/lun0/part7",  although the  two  refer to
the same device.


The following patch (against 2.6.6)  fixes this problem in the suspend
code.  It  will check whether both  the swap device  and the "resume="
parameter refer to a block  device with the same (major,minor) number.
If so, the swap device is taken  to be the one specified for swsusp to
use.   So, aliasing  of devices  is support.   This means  I  must say
"resume=/dev/hda7"                       and                       not
"resume=/dev/ide/host0/bus0/target0/lun0/part7".    If,  however,  the
specified swap devices are (swap)  files rather block devices, it only
does a filename comparison.  (Does  swsusp support swap files?  If so,
should we also support file aliasing?  How?)


--- linux-2.6.6-official/kernel/power/swsusp.c	2004/05/10 14:11:17	1.1
+++ linux-2.6.6-swsusp-dev-aliasing/kernel/power/swsusp.c	2004/05/10 16:11:41	1.3
@@ -215,47 +215,67 @@
 		else if ((!memcmp("SWAPSPACE2",cur->swh.magic.magic,10)))
 			memcpy(cur->swh.magic.magic,"S2SUSP....",10);
 		else panic("\nSwapspace is not swapspace (%.10s)\n", cur->swh.magic.magic);
 		cur->link.next = prev; /* prev is the first/last swap page of the resume area */
 		/* link.next lies *no more* in last 4/8 bytes of magic */
 	}
 	rw_swap_page_sync(WRITE, entry, page);
 	__free_page(page);
 }
 
+static int is_resume_file(const struct swap_info_struct *swap_info) {
+	/* check whether the swap device is the specified resume file */
+
+	static char buff[sizeof(resume_file)], *sname;
+	struct file *file = swap_info->swap_file;
+	struct inode *inode = file->f_dentry->d_inode;
+
+	/* now, see if it is a swap (block) device.  If so, we compare
+	   the device (MAJOR,MINOR), so as to support device inode
+	   aliasing.
+	*/
+	if (S_ISBLK(inode->i_mode)) {
+		if (resume_device == MKDEV(imajor(inode), iminor(inode)))
+			return 1; /* true */
+	}
+
+	/* otherwise, we compare filenames */
+	sname = d_path(swap_info->swap_file->f_dentry,
+		       swap_info->swap_file->f_vfsmnt,
+		       buff,
+		       sizeof(buff));
+
+	return !strcmp(sname, resume_file);
+}
+
 static void read_swapfiles(void) /* This is called before saving image */
 {
 	int i, len;
-	static char buff[sizeof(resume_file)], *sname;
 	
 	len=strlen(resume_file);
 	root_swap = 0xFFFF;
 	
 	swap_list_lock();
 	for(i=0; i<MAX_SWAPFILES; i++) {
 		if (swap_info[i].flags == 0) {
 			swapfile_used[i]=SWAPFILE_UNUSED;
 		} else {
 			if(!len) {
 	    			printk(KERN_WARNING "resume= option should be used to set suspend device" );
 				if(root_swap == 0xFFFF) {
 					swapfile_used[i] = SWAPFILE_SUSPEND;
 					root_swap = i;
 				} else
 					swapfile_used[i] = SWAPFILE_IGNORED;				  
 			} else {
 	  			/* we ignore all swap devices that are not the resume_file */
-				sname = d_path(swap_info[i].swap_file->f_dentry,
-					       swap_info[i].swap_file->f_vfsmnt,
-					       buff,
-					       sizeof(buff));
-				if (!strcmp(sname, resume_file)) {
+				if (is_resume_file(&swap_info[i])) {
 					swapfile_used[i] = SWAPFILE_SUSPEND;
 					root_swap = i;
 				} else {
 #if 0
 					printk( "Resume: device %s (%x != %x) ignored\n", swap_info[i].swap_file->d_name.name, swap_info[i].swap_device, resume_device );				  
 #endif
 				  	swapfile_used[i] = SWAPFILE_IGNORED;
 				}
 			}
 		}



-- 
Sau Dan LEE                     李守敦(Big5)                    ~{@nJX6X~}(HZ) 
E-mail: danlee@informatik.uni-freiburg.de
Home page: http://www.informatik.uni-freiburg.de/~danlee

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

\
 
 \ /
  Last update: 2005-03-22 14:03    [from the cache]
©2003-2008