linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [Suspend2][ 00/28] Swapwriter
@ 2006-06-26 22:41 Nigel Cunningham
  2006-06-26 22:41 ` [Suspend2][ 01/28] [Suspend2] Swapwriter.c header Nigel Cunningham
                   ` (27 more replies)
  0 siblings, 28 replies; 29+ messages in thread
From: Nigel Cunningham @ 2006-06-26 22:41 UTC (permalink / raw)
  To: linux-kernel


These patches add the swapwriter, which provides the means by which
an image can be written to one or more swap partitions or files.

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [Suspend2][ 01/28] [Suspend2] Swapwriter.c header.
  2006-06-26 22:41 [Suspend2][ 00/28] Swapwriter Nigel Cunningham
@ 2006-06-26 22:41 ` Nigel Cunningham
  2006-06-26 22:41 ` [Suspend2][ 02/28] [Suspend2] Close a bdev used by the swapwriter Nigel Cunningham
                   ` (26 subsequent siblings)
  27 siblings, 0 replies; 29+ messages in thread
From: Nigel Cunningham @ 2006-06-26 22:41 UTC (permalink / raw)
  To: linux-kernel

Header for kernel/power/suspend_swap.c.

Signed-off-by: Nigel Cunningham <nigel@suspend2.net>

 kernel/power/suspend_swap.c |   89 +++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 89 insertions(+), 0 deletions(-)

diff --git a/kernel/power/suspend_swap.c b/kernel/power/suspend_swap.c
new file mode 100644
index 0000000..7732a75
--- /dev/null
+++ b/kernel/power/suspend_swap.c
@@ -0,0 +1,89 @@
+/*
+ * Swapwriter.c
+ *
+ * Copyright 2004-2006 Nigel Cunningham <nigel@suspend2.net>
+ *
+ * Distributed under GPLv2.
+ * 
+ * This file encapsulates functions for usage of swap space as a
+ * backing store.
+ */
+
+#include <linux/suspend.h>
+#include <linux/module.h>
+#include <linux/blkdev.h>
+#include <linux/swapops.h>
+#include <linux/swap.h>
+
+#include "suspend2.h"
+#include "suspend2_common.h"
+#include "version.h"
+#include "proc.h"
+#include "modules.h"
+#include "io.h"
+#include "ui.h"
+#include "extent.h"
+#include "block_io.h"
+
+static struct suspend_module_ops swapwriterops;
+
+#define SIGNATURE_VER 6
+
+/* --- Struct of pages stored on disk */
+
+union diskpage {
+	union swap_header swh;	/* swh.magic is the only member used */
+};
+
+union p_diskpage {
+	union diskpage *pointer;
+	char *ptr;
+        unsigned long address;
+};
+
+/* Devices used for swap */
+static struct suspend_bdev_info devinfo[MAX_SWAPFILES];
+
+/* Extent chains for swap & blocks */
+struct extent_chain swapextents;
+struct extent_chain block_chain[MAX_SWAPFILES];
+
+static dev_t header_dev_t;
+static struct block_device *header_block_device;
+static unsigned long headerblock;
+
+/* For swapfile automatically swapon/off'd. */
+static char swapfilename[SWAP_FILENAME_MAXLENGTH] = "";
+extern asmlinkage long sys_swapon(const char *specialfile, int swap_flags);
+extern asmlinkage long sys_swapoff(const char *specialfile);
+static int suspend_swapon_status;
+
+/* Header Page Information */
+static int header_pages_allocated;
+
+/* User Specified Parameters. */
+
+static unsigned long resume_firstblock;
+static int resume_blocksize;
+static dev_t resume_dev_t;
+static struct block_device *resume_block_device;
+
+struct sysinfo swapinfo;
+static int swapwriter_invalidate_image(void);
+
+/* Block devices open. */
+struct bdev_opened
+{
+	dev_t device;
+	struct block_device *bdev;
+	int claimed;
+};
+
+/* 
+ * Entry MAX_SWAPFILES is the resume block device, which may
+ * not be a swap device enabled when we suspend.
+ * Entry MAX_SWAPFILES + 1 is the header block device, which
+ * is needed before we find out which slot it occupies.
+ */
+static struct bdev_opened *bdev_info_list[MAX_SWAPFILES + 2];
+       

--
Nigel Cunningham		nigel at suspend2 dot net

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Suspend2][ 02/28] [Suspend2] Close a bdev used by the swapwriter.
  2006-06-26 22:41 [Suspend2][ 00/28] Swapwriter Nigel Cunningham
  2006-06-26 22:41 ` [Suspend2][ 01/28] [Suspend2] Swapwriter.c header Nigel Cunningham
@ 2006-06-26 22:41 ` Nigel Cunningham
  2006-06-26 22:41 ` [Suspend2][ 03/28] [Suspend2] Close bdevs opened " Nigel Cunningham
                   ` (25 subsequent siblings)
  27 siblings, 0 replies; 29+ messages in thread
From: Nigel Cunningham @ 2006-06-26 22:41 UTC (permalink / raw)
  To: linux-kernel

Release a bdev used by the swapwriter.

Signed-off-by: Nigel Cunningham <nigel@suspend2.net>

 kernel/power/suspend_swap.c |   16 ++++++++++++++++
 1 files changed, 16 insertions(+), 0 deletions(-)

diff --git a/kernel/power/suspend_swap.c b/kernel/power/suspend_swap.c
index 7732a75..8a58b12 100644
--- a/kernel/power/suspend_swap.c
+++ b/kernel/power/suspend_swap.c
@@ -87,3 +87,19 @@ struct bdev_opened
  */
 static struct bdev_opened *bdev_info_list[MAX_SWAPFILES + 2];
        
+static void close_bdev(int i)
+{
+	struct bdev_opened *this = bdev_info_list[i];
+
+	if (this->claimed)
+		bd_release(this->bdev);
+
+	/* Release our reference. */
+	blkdev_put(this->bdev);
+
+	/* Free our info. */
+	kfree(this);
+
+	bdev_info_list[i] = NULL;
+}
+

--
Nigel Cunningham		nigel at suspend2 dot net

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Suspend2][ 03/28] [Suspend2] Close bdevs opened by the swapwriter.
  2006-06-26 22:41 [Suspend2][ 00/28] Swapwriter Nigel Cunningham
  2006-06-26 22:41 ` [Suspend2][ 01/28] [Suspend2] Swapwriter.c header Nigel Cunningham
  2006-06-26 22:41 ` [Suspend2][ 02/28] [Suspend2] Close a bdev used by the swapwriter Nigel Cunningham
@ 2006-06-26 22:41 ` Nigel Cunningham
  2006-06-26 22:41 ` [Suspend2][ 04/28] [Suspend2] Open bdev for swapwriter use Nigel Cunningham
                   ` (24 subsequent siblings)
  27 siblings, 0 replies; 29+ messages in thread
From: Nigel Cunningham @ 2006-06-26 22:41 UTC (permalink / raw)
  To: linux-kernel

Close bdevs opened by the swapwriter and clear the resume_block_device and
header_block_device.

Signed-off-by: Nigel Cunningham <nigel@suspend2.net>

 kernel/power/suspend_swap.c |   11 +++++++++++
 1 files changed, 11 insertions(+), 0 deletions(-)

diff --git a/kernel/power/suspend_swap.c b/kernel/power/suspend_swap.c
index 8a58b12..6f87a4a 100644
--- a/kernel/power/suspend_swap.c
+++ b/kernel/power/suspend_swap.c
@@ -103,3 +103,14 @@ static void close_bdev(int i)
 	bdev_info_list[i] = NULL;
 }
 
+static void close_bdevs(void)
+{
+	int i;
+
+	for (i = 0; i < MAX_SWAPFILES; i++)
+		if (bdev_info_list[i])
+			close_bdev(i);
+
+	resume_block_device = header_block_device = NULL;
+}
+

--
Nigel Cunningham		nigel at suspend2 dot net

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Suspend2][ 04/28] [Suspend2] Open bdev for swapwriter use.
  2006-06-26 22:41 [Suspend2][ 00/28] Swapwriter Nigel Cunningham
                   ` (2 preceding siblings ...)
  2006-06-26 22:41 ` [Suspend2][ 03/28] [Suspend2] Close bdevs opened " Nigel Cunningham
@ 2006-06-26 22:41 ` Nigel Cunningham
  2006-06-26 22:41 ` [Suspend2][ 05/28] [Suspend2] Enable/disable swapfile Nigel Cunningham
                   ` (23 subsequent siblings)
  27 siblings, 0 replies; 29+ messages in thread
From: Nigel Cunningham @ 2006-06-26 22:41 UTC (permalink / raw)
  To: linux-kernel

Open (at resume time) a bdev for the swapwriter to read from.

Signed-off-by: Nigel Cunningham <nigel@suspend2.net>

 kernel/power/suspend_swap.c |   37 +++++++++++++++++++++++++++++++++++++
 1 files changed, 37 insertions(+), 0 deletions(-)

diff --git a/kernel/power/suspend_swap.c b/kernel/power/suspend_swap.c
index 6f87a4a..212555f 100644
--- a/kernel/power/suspend_swap.c
+++ b/kernel/power/suspend_swap.c
@@ -114,3 +114,40 @@ static void close_bdevs(void)
 	resume_block_device = header_block_device = NULL;
 }
 
+static struct block_device *open_bdev(int index, dev_t device)
+{
+	struct bdev_opened *this;
+	struct block_device *bdev;
+
+	if (bdev_info_list[index] && (bdev_info_list[index]->device == device)){
+		bdev = bdev_info_list[index]->bdev;
+		return bdev;
+	}
+	
+	if (bdev_info_list[index] && bdev_info_list[index]->device != device)
+		close_bdev(index);
+
+	bdev = open_by_devnum(device, FMODE_READ);
+
+	if (IS_ERR(bdev) || !bdev) {
+		suspend_early_boot_message(1,SUSPEND_CONTINUE_REQ,  
+				"Failed to get access to block device "
+				"%d.\n You could be "
+				"booting with a 2.6 kernel when you "
+				"suspended a 2.4 kernel.", bdev);
+		return ERR_PTR(-EINVAL);
+	}
+
+	this = kmalloc(sizeof(struct bdev_opened), GFP_KERNEL);
+	BUG_ON(!this);
+
+	bdev_info_list[index] = this;
+	this->device = device;
+	this->bdev = bdev;
+
+	if (index < MAX_SWAPFILES)
+		devinfo[index].bdev = bdev;
+
+	return bdev;
+}
+

--
Nigel Cunningham		nigel at suspend2 dot net

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Suspend2][ 05/28] [Suspend2] Enable/disable swapfile.
  2006-06-26 22:41 [Suspend2][ 00/28] Swapwriter Nigel Cunningham
                   ` (3 preceding siblings ...)
  2006-06-26 22:41 ` [Suspend2][ 04/28] [Suspend2] Open bdev for swapwriter use Nigel Cunningham
@ 2006-06-26 22:41 ` Nigel Cunningham
  2006-06-26 22:41 ` [Suspend2][ 06/28] [Suspend2] Try to parse resume2= for swapwriter Nigel Cunningham
                   ` (22 subsequent siblings)
  27 siblings, 0 replies; 29+ messages in thread
From: Nigel Cunningham @ 2006-06-26 22:41 UTC (permalink / raw)
  To: linux-kernel

Routines to enable and disable a swap file specifically for suspending. The
swapon is called after userspace is frozen and the swapoff is done prior to
restarting userspace. We can't completely remove the possibility of it
being used by the vm. We're just doing the best we can.

Signed-off-by: Nigel Cunningham <nigel@suspend2.net>

 kernel/power/suspend_swap.c |   45 +++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 45 insertions(+), 0 deletions(-)

diff --git a/kernel/power/suspend_swap.c b/kernel/power/suspend_swap.c
index 212555f..13ad8d7 100644
--- a/kernel/power/suspend_swap.c
+++ b/kernel/power/suspend_swap.c
@@ -151,3 +151,48 @@ static struct block_device *open_bdev(in
 	return bdev;
 }
 
+/* Must be silent - might be called from cat /proc/suspend/debug_info
+ * Returns 0 if was off, -EBUSY if was on, error value otherwise.
+ */
+static int enable_swapfile(void)
+{
+	int activateswapresult = -EINVAL;
+
+	if (suspend_swapon_status)
+		return 0;
+
+	if (swapfilename[0]) {
+		/* Attempt to swap on with maximum priority */
+		activateswapresult = sys_swapon(swapfilename, 0xFFFF);
+		if ((activateswapresult) && (activateswapresult != -EBUSY))
+			printk(name_suspend
+				"The swapfile/partition specified by "
+				"/proc/suspend/swapfile (%s) could not"
+				" be turned on (error %d). Attempting "
+				"to continue.\n",
+				swapfilename, activateswapresult);
+		if (!activateswapresult)
+			suspend_swapon_status = 1;
+	}
+	return activateswapresult;
+}
+
+/* Returns 0 if was on, -EINVAL if was off, error value otherwise */
+static int disable_swapfile(void)
+{
+	int result = -EINVAL;
+	
+	if (!suspend_swapon_status)
+		return 0;
+
+	if (swapfilename[0]) {
+		result = sys_swapoff(swapfilename);
+		if (result == -EINVAL)
+	 		return 0;	/* Wasn't on */
+		if (!result)
+			suspend_swapon_status = 0;
+	}
+
+	return result;
+}
+

--
Nigel Cunningham		nigel at suspend2 dot net

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Suspend2][ 06/28] [Suspend2] Try to parse resume2= for swapwriter.
  2006-06-26 22:41 [Suspend2][ 00/28] Swapwriter Nigel Cunningham
                   ` (4 preceding siblings ...)
  2006-06-26 22:41 ` [Suspend2][ 05/28] [Suspend2] Enable/disable swapfile Nigel Cunningham
@ 2006-06-26 22:41 ` Nigel Cunningham
  2006-06-26 22:41 ` [Suspend2][ 07/28] [Suspend2] Reset swapwriter when not resuming Nigel Cunningham
                   ` (21 subsequent siblings)
  27 siblings, 0 replies; 29+ messages in thread
From: Nigel Cunningham @ 2006-06-26 22:41 UTC (permalink / raw)
  To: linux-kernel

Check whether resume2= is a swapwriter target (swap: prefix or swapwriter
is the only writer), whether we can access the device, and whether we find
a valid signature.

Signed-off-by: Nigel Cunningham <nigel@suspend2.net>

 kernel/power/suspend_swap.c |   37 +++++++++++++++++++++++++++++++++++++
 1 files changed, 37 insertions(+), 0 deletions(-)

diff --git a/kernel/power/suspend_swap.c b/kernel/power/suspend_swap.c
index 13ad8d7..66bb556 100644
--- a/kernel/power/suspend_swap.c
+++ b/kernel/power/suspend_swap.c
@@ -196,3 +196,40 @@ static int disable_swapfile(void)
 	return result;
 }
 
+static int try_to_parse_resume_device(char *commandline)
+{
+	struct kstat stat;
+	int error;
+
+	resume_dev_t = name_to_dev_t(commandline);
+
+	if (!resume_dev_t) {
+		error = vfs_stat(commandline, &stat);
+		if (!error)
+			resume_dev_t = stat.rdev;
+	}
+
+	if (!resume_dev_t) {
+		if (test_suspend_state(SUSPEND_TRYING_TO_RESUME))
+			suspend_early_boot_message(1, SUSPEND_CONTINUE_REQ,
+			  "Failed to translate \"%s\" into a device id.\n",
+			  commandline);
+		else
+			printk(name_suspend
+			  "Can't translate \"%s\" into a device id yet.\n",
+			  commandline);
+		return 1;
+	}
+
+	if (IS_ERR(resume_block_device =
+	     open_bdev(MAX_SWAPFILES, resume_dev_t))) {
+		suspend_early_boot_message(1, SUSPEND_CONTINUE_REQ,
+			"Failed to get access to \"%s\", where"
+			" the swap header should be found.",
+			commandline);
+		return 1;
+	}
+
+	return 0;
+}
+

--
Nigel Cunningham		nigel at suspend2 dot net

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Suspend2][ 07/28] [Suspend2] Reset swapwriter when not resuming.
  2006-06-26 22:41 [Suspend2][ 00/28] Swapwriter Nigel Cunningham
                   ` (5 preceding siblings ...)
  2006-06-26 22:41 ` [Suspend2][ 06/28] [Suspend2] Try to parse resume2= for swapwriter Nigel Cunningham
@ 2006-06-26 22:41 ` Nigel Cunningham
  2006-06-26 22:41 ` [Suspend2][ 08/28] [Suspend2] Parse swapwriter signature Nigel Cunningham
                   ` (20 subsequent siblings)
  27 siblings, 0 replies; 29+ messages in thread
From: Nigel Cunningham @ 2006-06-26 22:41 UTC (permalink / raw)
  To: linux-kernel

Reset the device info and close bdevs when we set up when preparing to
resume. This might happen because of a problem, or because noresume2 was
given on the command line and we needed first to invalidate the image.

Signed-off-by: Nigel Cunningham <nigel@suspend2.net>

 kernel/power/suspend_swap.c |   10 ++++++++++
 1 files changed, 10 insertions(+), 0 deletions(-)

diff --git a/kernel/power/suspend_swap.c b/kernel/power/suspend_swap.c
index 66bb556..a014103 100644
--- a/kernel/power/suspend_swap.c
+++ b/kernel/power/suspend_swap.c
@@ -233,3 +233,13 @@ static int try_to_parse_resume_device(ch
 	return 0;
 }
 
+/* 
+ * If we have read part of the image, we might have filled  memory with
+ * data that should be zeroed out.
+ */
+static void swapwriter_noresume_reset(void)
+{
+	memset((char *) &devinfo, 0, sizeof(devinfo));
+	close_bdevs();
+}
+

--
Nigel Cunningham		nigel at suspend2 dot net

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Suspend2][ 08/28] [Suspend2] Parse swapwriter signature.
  2006-06-26 22:41 [Suspend2][ 00/28] Swapwriter Nigel Cunningham
                   ` (6 preceding siblings ...)
  2006-06-26 22:41 ` [Suspend2][ 07/28] [Suspend2] Reset swapwriter when not resuming Nigel Cunningham
@ 2006-06-26 22:41 ` Nigel Cunningham
  2006-06-26 22:41 ` [Suspend2][ 09/28] [Suspend2] Prepare " Nigel Cunningham
                   ` (19 subsequent siblings)
  27 siblings, 0 replies; 29+ messages in thread
From: Nigel Cunningham @ 2006-06-26 22:41 UTC (permalink / raw)
  To: linux-kernel

Parse a signature. It may reflect a normal swapheader of type 1 or 2, a
swsusp header or a Suspend2 header.

Signed-off-by: Nigel Cunningham <nigel@suspend2.net>

 kernel/power/suspend_swap.c |   50 +++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 50 insertions(+), 0 deletions(-)

diff --git a/kernel/power/suspend_swap.c b/kernel/power/suspend_swap.c
index a014103..08c4f86 100644
--- a/kernel/power/suspend_swap.c
+++ b/kernel/power/suspend_swap.c
@@ -243,3 +243,53 @@ static void swapwriter_noresume_reset(vo
 	close_bdevs();
 }
 
+static int parse_signature(char *header, int restore)
+{
+	int type = -1;
+	
+	if (!memcmp("SWAP-SPACE",header,10))
+		return 0;
+	else if (!memcmp("SWAPSPACE2",header,10))
+		return 1;
+
+	else if (!memcmp("S1SUSP",header,6))
+		type = 4;
+	else if (!memcmp("S2SUSP",header,6))
+		type = 5;
+	
+	else if (!memcmp("z",header,1))
+		type = 12;
+	else if (!memcmp("Z",header,1))
+		type = 13;
+	
+	/* 
+	 * Put bdev of suspend header in last byte of swap header
+	 * (unsigned short)
+	 */
+	if (type > 11) {
+		dev_t *header_ptr = (dev_t *) &header[1];
+		unsigned char *headerblocksize_ptr =
+			(unsigned char *) &header[5];
+		u32 *headerblock_ptr = (u32 *) &header[6];
+		header_dev_t = *header_ptr;
+		/* 
+		 * We are now using the highest bit of the char to indicate
+		 * whether we have attempted to resume from this image before.
+		 */
+		clear_suspend_state(SUSPEND_RESUMED_BEFORE);
+		if (((int) *headerblocksize_ptr) & 0x80)
+			set_suspend_state(SUSPEND_RESUMED_BEFORE);
+		headerblock = (unsigned long) *headerblock_ptr;
+	}
+
+	if ((restore) && (type > 5)) {
+		/* We only reset our own signatures */
+		if (type & 1)
+			memcpy(header,"SWAPSPACE2",10);
+		else
+			memcpy(header,"SWAP-SPACE",10);
+	}
+
+	return type;
+}
+

--
Nigel Cunningham		nigel at suspend2 dot net

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Suspend2][ 09/28] [Suspend2] Prepare swapwriter signature.
  2006-06-26 22:41 [Suspend2][ 00/28] Swapwriter Nigel Cunningham
                   ` (7 preceding siblings ...)
  2006-06-26 22:41 ` [Suspend2][ 08/28] [Suspend2] Parse swapwriter signature Nigel Cunningham
@ 2006-06-26 22:41 ` Nigel Cunningham
  2006-06-26 22:41 ` [Suspend2][ 10/28] [Suspend2] Allocate swapwriter header space Nigel Cunningham
                   ` (18 subsequent siblings)
  27 siblings, 0 replies; 29+ messages in thread
From: Nigel Cunningham @ 2006-06-26 22:41 UTC (permalink / raw)
  To: linux-kernel

Set the swapwriter signature to reflect that we have an image and point to
the device and sector where the header proper begins.

Signed-off-by: Nigel Cunningham <nigel@suspend2.net>

 kernel/power/suspend_swap.c |   36 ++++++++++++++++++++++++++++++++++++
 1 files changed, 36 insertions(+), 0 deletions(-)

diff --git a/kernel/power/suspend_swap.c b/kernel/power/suspend_swap.c
index 08c4f86..7f16bea 100644
--- a/kernel/power/suspend_swap.c
+++ b/kernel/power/suspend_swap.c
@@ -293,3 +293,39 @@ static int parse_signature(char *header,
 	return type;
 }
 
+/*
+ * prepare_signature
+ */
+
+static int prepare_signature(dev_t bdev, unsigned long block,
+		char *current_header)
+{
+	int current_type = parse_signature(current_header, 0);
+	dev_t *header_ptr = (dev_t *) (&current_header[1]);
+	unsigned long *headerblock_ptr =
+		(unsigned long *) (&current_header[6]);
+
+	if ((current_type > 1) && (current_type < 6))
+		return 1;
+
+	/* At the moment, I don't have a way to handle the block being
+	 * > 32 bits. Not enough room in the signature and no way to
+	 * safely put the data elsewhere. */
+
+	if (BITS_PER_LONG == 64 && ffs(block) > 31) {
+		suspend_prepare_status(DONT_CLEAR_BAR,
+			"Header sector requires 33+ bits. "
+			"Would not be able to resume.");
+		return 1;
+	}
+
+	if (current_type & 1)
+		current_header[0] = 'Z';
+	else
+		current_header[0] = 'z';
+	*header_ptr = bdev;
+	/* prev is the first/last swap page of the resume area */
+	*headerblock_ptr = (unsigned long) block; 
+	return 0;
+}
+

--
Nigel Cunningham		nigel at suspend2 dot net

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Suspend2][ 10/28] [Suspend2] Allocate swapwriter header space.
  2006-06-26 22:41 [Suspend2][ 00/28] Swapwriter Nigel Cunningham
                   ` (8 preceding siblings ...)
  2006-06-26 22:41 ` [Suspend2][ 09/28] [Suspend2] Prepare " Nigel Cunningham
@ 2006-06-26 22:41 ` Nigel Cunningham
  2006-06-26 22:41 ` [Suspend2][ 11/28] [Suspend2] Get block chains for swapwriter Nigel Cunningham
                   ` (17 subsequent siblings)
  27 siblings, 0 replies; 29+ messages in thread
From: Nigel Cunningham @ 2006-06-26 22:41 UTC (permalink / raw)
  To: linux-kernel

Allocate space in the allocated storage for the header of the image.

Signed-off-by: Nigel Cunningham <nigel@suspend2.net>

 kernel/power/suspend_swap.c |   31 +++++++++++++++++++++++++++++++
 1 files changed, 31 insertions(+), 0 deletions(-)

diff --git a/kernel/power/suspend_swap.c b/kernel/power/suspend_swap.c
index 7f16bea..8e4221d 100644
--- a/kernel/power/suspend_swap.c
+++ b/kernel/power/suspend_swap.c
@@ -329,3 +329,34 @@ static int prepare_signature(dev_t bdev,
 	return 0;
 }
 
+static int swapwriter_allocate_storage(int space_requested);
+
+static int swapwriter_allocate_header_space(int space_requested)
+{
+	int i;
+
+	if (!swapextents.size)
+		swapwriter_allocate_storage(space_requested);
+
+	suspend_extent_state_goto_start(&suspend_writer_posn);
+	suspend_bio_ops.forward_one_page(); /* To first page */
+	
+	for (i = 0; i < space_requested; i++) {
+		if (suspend_bio_ops.forward_one_page()) {
+			printk("Out of space while seeking to allocate "
+					"header pages,\n");
+			header_pages_allocated = i;
+			return -ENOSPC;
+		}
+
+	}
+
+	header_pages_allocated = space_requested;
+
+	/* The end of header pages will be the start of pageset 2;
+	 * we are now sitting on the first pageset2 page. */
+	suspend_extent_state_save(&suspend_writer_posn,
+			&suspend_writer_posn_save[2]);
+	return 0;
+}
+

--
Nigel Cunningham		nigel at suspend2 dot net

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Suspend2][ 11/28] [Suspend2] Get block chains for swapwriter.
  2006-06-26 22:41 [Suspend2][ 00/28] Swapwriter Nigel Cunningham
                   ` (9 preceding siblings ...)
  2006-06-26 22:41 ` [Suspend2][ 10/28] [Suspend2] Allocate swapwriter header space Nigel Cunningham
@ 2006-06-26 22:41 ` Nigel Cunningham
  2006-06-26 22:41 ` [Suspend2][ 12/28] [Suspend2] Swapwriter storage allocated and available Nigel Cunningham
                   ` (16 subsequent siblings)
  27 siblings, 0 replies; 29+ messages in thread
From: Nigel Cunningham @ 2006-06-26 22:41 UTC (permalink / raw)
  To: linux-kernel

Given the (previously allocated) swap entries, get the sectors for each
device to which we'll be writing the image.

Signed-off-by: Nigel Cunningham <nigel@suspend2.net>

 kernel/power/suspend_swap.c |   58 +++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 58 insertions(+), 0 deletions(-)

diff --git a/kernel/power/suspend_swap.c b/kernel/power/suspend_swap.c
index 8e4221d..af6640f 100644
--- a/kernel/power/suspend_swap.c
+++ b/kernel/power/suspend_swap.c
@@ -360,3 +360,61 @@ static int swapwriter_allocate_header_sp
 	return 0;
 }
 
+static void get_main_pool_phys_params(void)
+{
+	struct extent *extentpointer = NULL;
+	unsigned long address;
+	int i, extent_min = -1, extent_max = -1, last_chain = -1;
+	int prev_header_pages_allocated;
+
+	for (i = 0; i < MAX_SWAPFILES; i++)
+		if (block_chain[i].first)
+			suspend_put_extent_chain(&block_chain[i]);
+
+	suspend_extent_for_each(&swapextents, extentpointer, address) {
+		swp_entry_t swap_address = extent_val_to_swap_entry(address);
+		pgoff_t offset = swp_offset(swap_address);
+		unsigned swapfilenum = swp_type(swap_address);
+		struct swap_info_struct *sis = get_swap_info_struct(swapfilenum);
+		sector_t new_sector = map_swap_page(sis, offset);
+
+		if ((new_sector == extent_max + 1) &&
+		    (last_chain == swapfilenum))
+			extent_max++;
+		else {
+			if (extent_min > -1) {
+				if (test_action_state(SUSPEND_TEST_BIO))
+					printk("Adding extent chain %d %d-%d.\n",
+						swapfilenum,
+						extent_min <<
+						 devinfo[last_chain].bmap_shift,
+						extent_max <<
+						 devinfo[last_chain].bmap_shift);
+						
+				suspend_add_to_extent_chain(
+					&block_chain[last_chain],
+					extent_min, extent_max);
+			}
+			extent_min = extent_max = new_sector;
+			last_chain = swapfilenum;
+		}
+	}
+
+	if (extent_min > -1) {
+		if (test_action_state(SUSPEND_TEST_BIO))
+			printk("Adding extent chain %d %d-%d.\n",
+				last_chain,
+				extent_min <<
+					devinfo[last_chain].bmap_shift,
+				extent_max <<
+					devinfo[last_chain].bmap_shift);
+		suspend_add_to_extent_chain(
+			&block_chain[last_chain],
+			extent_min, extent_max);
+	}
+
+	prev_header_pages_allocated = header_pages_allocated;
+	header_pages_allocated = 0;
+	swapwriter_allocate_header_space(prev_header_pages_allocated);
+}
+

--
Nigel Cunningham		nigel at suspend2 dot net

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Suspend2][ 12/28] [Suspend2] Swapwriter storage allocated and available.
  2006-06-26 22:41 [Suspend2][ 00/28] Swapwriter Nigel Cunningham
                   ` (10 preceding siblings ...)
  2006-06-26 22:41 ` [Suspend2][ 11/28] [Suspend2] Get block chains for swapwriter Nigel Cunningham
@ 2006-06-26 22:41 ` Nigel Cunningham
  2006-06-26 22:41 ` [Suspend2][ 13/28] [Suspend2] Initialise/cleanup swapwriter Nigel Cunningham
                   ` (15 subsequent siblings)
  27 siblings, 0 replies; 29+ messages in thread
From: Nigel Cunningham @ 2006-06-26 22:41 UTC (permalink / raw)
  To: linux-kernel

Return the amount of storage available and llocated for swapwriter use.

Signed-off-by: Nigel Cunningham <nigel@suspend2.net>

 kernel/power/suspend_swap.c |   11 +++++++++++
 1 files changed, 11 insertions(+), 0 deletions(-)

diff --git a/kernel/power/suspend_swap.c b/kernel/power/suspend_swap.c
index af6640f..792bcc8 100644
--- a/kernel/power/suspend_swap.c
+++ b/kernel/power/suspend_swap.c
@@ -418,3 +418,14 @@ static void get_main_pool_phys_params(vo
 	swapwriter_allocate_header_space(prev_header_pages_allocated);
 }
 
+static int swapwriter_storage_allocated(void)
+{
+	return swapextents.size;
+}
+
+static int swapwriter_storage_available(void)
+{
+	si_swapinfo(&swapinfo);
+	return swapinfo.freeswap + swapwriter_storage_allocated();
+}
+

--
Nigel Cunningham		nigel at suspend2 dot net

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Suspend2][ 13/28] [Suspend2] Initialise/cleanup swapwriter
  2006-06-26 22:41 [Suspend2][ 00/28] Swapwriter Nigel Cunningham
                   ` (11 preceding siblings ...)
  2006-06-26 22:41 ` [Suspend2][ 12/28] [Suspend2] Swapwriter storage allocated and available Nigel Cunningham
@ 2006-06-26 22:41 ` Nigel Cunningham
  2006-06-26 22:41 ` [Suspend2][ 14/28] [Suspend2] Release swapwriter storage Nigel Cunningham
                   ` (14 subsequent siblings)
  27 siblings, 0 replies; 29+ messages in thread
From: Nigel Cunningham @ 2006-06-26 22:41 UTC (permalink / raw)
  To: linux-kernel

Initialise and cleanup routines, called when we're going to do something.
It may be just modifying a setting, but some of these result in I/O being
done to (eg) check whether an image exists.

Signed-off-by: Nigel Cunningham <nigel@suspend2.net>

 kernel/power/suspend_swap.c |   23 +++++++++++++++++++++++
 1 files changed, 23 insertions(+), 0 deletions(-)

diff --git a/kernel/power/suspend_swap.c b/kernel/power/suspend_swap.c
index 792bcc8..ae0dfad 100644
--- a/kernel/power/suspend_swap.c
+++ b/kernel/power/suspend_swap.c
@@ -429,3 +429,26 @@ static int swapwriter_storage_available(
 	return swapinfo.freeswap + swapwriter_storage_allocated();
 }
 
+static int swapwriter_initialise(int starting_cycle)
+{
+	if (!starting_cycle)
+		return 0;
+
+	enable_swapfile();
+
+	if (resume_dev_t && !resume_block_device &&
+	    IS_ERR(resume_block_device =
+	    		open_bdev(MAX_SWAPFILES, resume_dev_t)))
+		return 1;
+	
+	return 0;
+}
+
+static void swapwriter_cleanup(int ending_cycle)
+{
+	if (ending_cycle)
+		disable_swapfile();
+	
+	close_bdevs();
+}
+

--
Nigel Cunningham		nigel at suspend2 dot net

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Suspend2][ 14/28] [Suspend2] Release swapwriter storage.
  2006-06-26 22:41 [Suspend2][ 00/28] Swapwriter Nigel Cunningham
                   ` (12 preceding siblings ...)
  2006-06-26 22:41 ` [Suspend2][ 13/28] [Suspend2] Initialise/cleanup swapwriter Nigel Cunningham
@ 2006-06-26 22:41 ` Nigel Cunningham
  2006-06-26 22:41 ` [Suspend2][ 15/28] [Suspend2] Allocate " Nigel Cunningham
                   ` (13 subsequent siblings)
  27 siblings, 0 replies; 29+ messages in thread
From: Nigel Cunningham @ 2006-06-26 22:41 UTC (permalink / raw)
  To: linux-kernel

Free storage that has been allocated and also clear out the extent chains
that record the sectors.

Signed-off-by: Nigel Cunningham <nigel@suspend2.net>

 kernel/power/suspend_swap.c |   31 +++++++++++++++++++++++++++++++
 1 files changed, 31 insertions(+), 0 deletions(-)

diff --git a/kernel/power/suspend_swap.c b/kernel/power/suspend_swap.c
index ae0dfad..ae33a4e 100644
--- a/kernel/power/suspend_swap.c
+++ b/kernel/power/suspend_swap.c
@@ -452,3 +452,34 @@ static void swapwriter_cleanup(int endin
 	close_bdevs();
 }
 
+static int swapwriter_release_storage(void)
+{
+	int i = 0;
+
+	if (test_action_state(SUSPEND_KEEP_IMAGE) &&
+	    test_suspend_state(SUSPEND_NOW_RESUMING))
+		return 0;
+
+	header_pages_allocated = 0;
+	
+	if (swapextents.first) {
+		/* Free swap entries */
+		struct extent *extentpointer;
+		unsigned long extentvalue;
+		swp_entry_t entry;
+		suspend_extent_for_each(&swapextents, extentpointer, 
+				extentvalue) {
+			entry = extent_val_to_swap_entry(extentvalue);
+			swap_free(entry);
+		}
+
+		suspend_put_extent_chain(&swapextents);
+		
+		for (i = 0; i < MAX_SWAPFILES; i++)
+			if (block_chain[i].first)
+				suspend_put_extent_chain(&block_chain[i]);
+	}
+	
+	return 0;
+}
+

--
Nigel Cunningham		nigel at suspend2 dot net

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Suspend2][ 15/28] [Suspend2] Allocate swapwriter storage.
  2006-06-26 22:41 [Suspend2][ 00/28] Swapwriter Nigel Cunningham
                   ` (13 preceding siblings ...)
  2006-06-26 22:41 ` [Suspend2][ 14/28] [Suspend2] Release swapwriter storage Nigel Cunningham
@ 2006-06-26 22:41 ` Nigel Cunningham
  2006-06-26 22:42 ` [Suspend2][ 16/28] [Suspend2] Initialise/cleanup writing the header Nigel Cunningham
                   ` (12 subsequent siblings)
  27 siblings, 0 replies; 29+ messages in thread
From: Nigel Cunningham @ 2006-06-26 22:41 UTC (permalink / raw)
  To: linux-kernel

Allocate swap for the swapwriter to use. We support any number of swap
devices, of both types (partitions and files). After allocating the swap,
update the list of sectors that the entries map to.

Signed-off-by: Nigel Cunningham <nigel@suspend2.net>

 kernel/power/suspend_swap.c |   70 +++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 66 insertions(+), 4 deletions(-)

diff --git a/kernel/power/suspend_swap.c b/kernel/power/suspend_swap.c
index ae33a4e..efd08ca 100644
--- a/kernel/power/suspend_swap.c
+++ b/kernel/power/suspend_swap.c
@@ -365,7 +365,6 @@ static void get_main_pool_phys_params(vo
 	struct extent *extentpointer = NULL;
 	unsigned long address;
 	int i, extent_min = -1, extent_max = -1, last_chain = -1;
-	int prev_header_pages_allocated;
 
 	for (i = 0; i < MAX_SWAPFILES; i++)
 		if (block_chain[i].first)
@@ -413,9 +412,7 @@ static void get_main_pool_phys_params(vo
 			extent_min, extent_max);
 	}
 
-	prev_header_pages_allocated = header_pages_allocated;
-	header_pages_allocated = 0;
-	swapwriter_allocate_header_space(prev_header_pages_allocated);
+	swapwriter_allocate_header_space(header_pages_allocated);
 }
 
 static int swapwriter_storage_allocated(void)
@@ -483,3 +480,68 @@ static int swapwriter_release_storage(vo
 	return 0;
 }
 
+/* 
+ * Round robin allocation (where swap storage has the same priority).
+ * could make this very inefficient, so we track extents allocated on
+ * a per-swapfiles basis.
+ */
+static int swapwriter_allocate_storage(int space_requested)
+{
+	int i, result = 0, first[MAX_SWAPFILES];
+	int pages_to_get = space_requested - swapextents.size;
+	unsigned long extent_min[MAX_SWAPFILES], extent_max[MAX_SWAPFILES];
+	
+	if (pages_to_get < 1)
+		return 0;
+
+	for (i=0; i < MAX_SWAPFILES; i++) {
+		struct swap_info_struct *si = get_swap_info_struct(i);
+		if ((devinfo[i].bdev = si->bdev))
+			devinfo[i].dev_t = si->bdev->bd_dev;
+		devinfo[i].bmap_shift = 3;
+		devinfo[i].blocks_per_page = 1;
+		first[i] = 1;
+	}
+
+	for(i=0; i < pages_to_get; i++) {
+		swp_entry_t entry;
+		unsigned long new_value;
+		unsigned swapfilenum;
+
+		entry = get_swap_page();
+		if (!entry.val) {
+			printk("Failed to get a swap page.\n");
+			result = -ENOSPC;
+			break;
+		}
+		
+		swapfilenum = swp_type(entry);
+		new_value = swap_entry_to_extent_val(entry);
+		if (first[swapfilenum]) {
+			first[swapfilenum] = 0;
+			extent_min[swapfilenum] = extent_max[swapfilenum] =
+				new_value;
+		} else {
+			if (new_value == extent_max[swapfilenum] + 1)
+				extent_max[swapfilenum]++;
+			else {
+				suspend_add_to_extent_chain(
+					&swapextents,
+					extent_min[swapfilenum],
+					extent_max[swapfilenum]);
+				extent_min[swapfilenum] =
+					extent_max[swapfilenum] = new_value;
+			}
+		}
+	}
+
+	for (i = 0; i < MAX_SWAPFILES; i++)
+		if (!first[i])
+			suspend_add_to_extent_chain(
+				&swapextents,
+				extent_min[i], extent_max[i]);
+
+	get_main_pool_phys_params();
+	return result;
+}
+

--
Nigel Cunningham		nigel at suspend2 dot net

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Suspend2][ 16/28] [Suspend2] Initialise/cleanup writing the header.
  2006-06-26 22:41 [Suspend2][ 00/28] Swapwriter Nigel Cunningham
                   ` (14 preceding siblings ...)
  2006-06-26 22:41 ` [Suspend2][ 15/28] [Suspend2] Allocate " Nigel Cunningham
@ 2006-06-26 22:42 ` Nigel Cunningham
  2006-06-26 22:42 ` [Suspend2][ 17/28] [Suspend2] Swapwriter read image header init/cleanup Nigel Cunningham
                   ` (11 subsequent siblings)
  27 siblings, 0 replies; 29+ messages in thread
From: Nigel Cunningham @ 2006-06-26 22:42 UTC (permalink / raw)
  To: linux-kernel

Initialisation and cleanup routines used when writing the image header.

Signed-off-by: Nigel Cunningham <nigel@suspend2.net>

 kernel/power/suspend_swap.c |   89 +++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 89 insertions(+), 0 deletions(-)

diff --git a/kernel/power/suspend_swap.c b/kernel/power/suspend_swap.c
index efd08ca..b005f8b 100644
--- a/kernel/power/suspend_swap.c
+++ b/kernel/power/suspend_swap.c
@@ -545,3 +545,92 @@ static int swapwriter_allocate_storage(i
 	return result;
 }
 
+static int swapwriter_write_header_init(void)
+{
+	int i, result;
+	struct swap_info_struct *si;
+
+	suspend_header_bytes_used = 0;
+	
+	suspend_extent_state_goto_start(&suspend_writer_posn);
+	/* Forward one page will be done prior to the read */
+
+	for (i = 0; i < MAX_SWAPFILES; i++) {
+		si = get_swap_info_struct(i);
+		if (si->swap_file)
+			devinfo[i].dev_t = si->bdev->bd_dev;
+		else
+			devinfo[i].dev_t = (dev_t) 0;
+	}
+
+	suspend_writer_buffer = (char *) get_zeroed_page(GFP_ATOMIC);
+	if (!suspend_writer_buffer) {
+		printk("Failed to get swapwriter buffer.\n");
+		return -ENOMEM;
+	}
+
+	suspend_writer_buffer_posn = 0;
+
+	/* Info needed to bootstrap goes at the start of the header.
+	 * First we save the positions and devinfo, including the number
+	 * of header pages. Then we save the structs containing data needed
+	 * for reading the header pages back.
+	 * Note that even if header pages take more than one page, when we
+	 * read back the info, we will have restored the location of the
+	 * next header page by the time we go to use it.
+	 */
+
+	if ((result = suspend_bio_ops.rw_header_chunk(WRITE,
+			&swapwriterops,
+			(char *) &suspend_writer_posn_save, 
+			sizeof(suspend_writer_posn_save))))
+		return result;
+
+	if ((result = suspend_bio_ops.rw_header_chunk(WRITE,
+			&swapwriterops,
+			(char *) &devinfo, sizeof(devinfo))))
+		return result;
+
+	for (i=0; i < MAX_SWAPFILES; i++)
+		suspend_serialise_extent_chain(&swapwriterops, &block_chain[i]);
+
+	return 0;
+}
+
+static int swapwriter_write_header_cleanup(void)
+{
+	int result;
+	struct swap_info_struct *si;
+
+	/* Write any unsaved data */
+	if (suspend_writer_buffer_posn)
+		suspend_bio_ops.write_header_chunk_finish();
+
+	suspend_bio_ops.finish_all_io();
+
+	suspend_extent_state_goto_start(&suspend_writer_posn);
+	suspend_bio_ops.forward_one_page();
+
+	/* Adjust swap header */
+	suspend_bio_ops.bdev_page_io(READ, resume_block_device,
+			resume_firstblock,
+			virt_to_page(suspend_writer_buffer));
+
+	si = get_swap_info_struct(suspend_writer_posn.current_chain);
+	result = prepare_signature(si->bdev->bd_dev,
+			suspend_writer_posn.current_offset,
+		((union swap_header *) suspend_writer_buffer)->magic.magic);
+		
+	if (!result)
+		suspend_bio_ops.bdev_page_io(WRITE, resume_block_device,
+			resume_firstblock,
+			virt_to_page(suspend_writer_buffer));
+
+	free_page((unsigned long) suspend_writer_buffer);
+	suspend_writer_buffer = NULL;
+	
+	suspend_bio_ops.finish_all_io();
+
+	return result;
+}
+

--
Nigel Cunningham		nigel at suspend2 dot net

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Suspend2][ 17/28] [Suspend2] Swapwriter read image header init/cleanup.
  2006-06-26 22:41 [Suspend2][ 00/28] Swapwriter Nigel Cunningham
                   ` (15 preceding siblings ...)
  2006-06-26 22:42 ` [Suspend2][ 16/28] [Suspend2] Initialise/cleanup writing the header Nigel Cunningham
@ 2006-06-26 22:42 ` Nigel Cunningham
  2006-06-26 22:42 ` [Suspend2][ 18/28] [Suspend2] Invalidate swapwriter image Nigel Cunningham
                   ` (10 subsequent siblings)
  27 siblings, 0 replies; 29+ messages in thread
From: Nigel Cunningham @ 2006-06-26 22:42 UTC (permalink / raw)
  To: linux-kernel

Initialisation and clean up routines for reading the image header.

Signed-off-by: Nigel Cunningham <nigel@suspend2.net>

 kernel/power/suspend_swap.c |  116 +++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 116 insertions(+), 0 deletions(-)

diff --git a/kernel/power/suspend_swap.c b/kernel/power/suspend_swap.c
index b005f8b..9d806a5 100644
--- a/kernel/power/suspend_swap.c
+++ b/kernel/power/suspend_swap.c
@@ -634,3 +634,119 @@ static int swapwriter_write_header_clean
 	return result;
 }
 
+/* ------------------------- HEADER READING ------------------------- */
+
+/*
+ * read_header_init()
+ * 
+ * Description:
+ * 1. Attempt to read the device specified with resume2=.
+ * 2. Check the contents of the swap header for our signature.
+ * 3. Warn, ignore, reset and/or continue as appropriate.
+ * 4. If continuing, read the swapwriter configuration section
+ *    of the header and set up block device info so we can read
+ *    the rest of the header & image.
+ *
+ * Returns:
+ * May not return if user choose to reboot at a warning.
+ * -EINVAL if cannot resume at this time. Booting should continue
+ * normally.
+ */
+
+static int swapwriter_read_header_init(void)
+{
+	int i;
+	
+	BUG_ON(!resume_block_device);
+	BUG_ON(!resume_dev_t);
+
+	suspend_header_bytes_used = 0;
+
+	suspend_writer_buffer = (char *) get_zeroed_page(GFP_ATOMIC);
+
+	BUG_ON(!suspend_writer_buffer);
+
+	if (!header_dev_t) {
+		printk("read_header_init called when we haven't "
+				"verified there is an image!\n");
+		return -EINVAL;
+	}
+
+	/* 
+	 * If the header is not on the resume_dev_t, get the resume device first.
+	 */
+	if (header_dev_t != resume_dev_t) {
+		header_block_device = open_bdev(MAX_SWAPFILES + 1,
+				header_dev_t);
+
+		if (IS_ERR(header_block_device))
+			return PTR_ERR(header_block_device);
+	} else
+		header_block_device = resume_block_device;
+
+	/* 
+	 * Read swapwriter configuration.
+	 * Headerblock size taken into account already.
+	 */
+	suspend_bio_ops.bdev_page_io(READ, header_block_device,
+			headerblock << 3,
+			virt_to_page((unsigned long) suspend_writer_buffer));
+	
+	memcpy(&suspend_writer_posn_save, suspend_writer_buffer, 3 * sizeof(struct extent_iterate_saved_state));
+	
+	suspend_writer_buffer_posn = 3 * sizeof(struct extent_iterate_saved_state);
+	suspend_header_bytes_used += 3 * sizeof(struct extent_iterate_saved_state);
+	
+	memcpy(&devinfo, suspend_writer_buffer + suspend_writer_buffer_posn, sizeof(devinfo));
+	
+	suspend_writer_buffer_posn += sizeof(devinfo);
+	suspend_header_bytes_used += sizeof(devinfo);
+
+	/* Restore device info */
+	for (i = 0; i < MAX_SWAPFILES; i++) {
+		dev_t thisdevice = devinfo[i].dev_t;
+		struct block_device *result;
+
+		devinfo[i].bdev = NULL;
+
+		if (!thisdevice)
+			continue;
+
+		if (thisdevice == resume_dev_t) {
+			devinfo[i].bdev = resume_block_device;
+			bdev_info_list[i] = bdev_info_list[MAX_SWAPFILES];
+			BUG_ON(!bdev_info_list[i]);
+			bdev_info_list[MAX_SWAPFILES] = NULL;
+			continue;
+		}
+
+		if (thisdevice == header_dev_t) {
+			devinfo[i].bdev = header_block_device;
+			bdev_info_list[i] = bdev_info_list[MAX_SWAPFILES + 1];
+			BUG_ON(!bdev_info_list[i]);
+			bdev_info_list[MAX_SWAPFILES + 1] = NULL;
+			continue;
+		}
+
+		result = open_bdev(i, thisdevice);
+		if (IS_ERR(result)) {
+			close_bdevs();
+			return PTR_ERR(result);
+		}
+	}
+
+	suspend_extent_state_goto_start(&suspend_writer_posn);
+	suspend_bio_ops.set_extra_page_forward();
+
+	for (i = 0; i < MAX_SWAPFILES; i++)
+		suspend_load_extent_chain(&block_chain[i]);
+
+	return 0;
+}
+
+static int swapwriter_read_header_cleanup(void)
+{
+	free_page((unsigned long) suspend_writer_buffer);
+	return 0;
+}
+

--
Nigel Cunningham		nigel at suspend2 dot net

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Suspend2][ 18/28] [Suspend2] Invalidate swapwriter image.
  2006-06-26 22:41 [Suspend2][ 00/28] Swapwriter Nigel Cunningham
                   ` (16 preceding siblings ...)
  2006-06-26 22:42 ` [Suspend2][ 17/28] [Suspend2] Swapwriter read image header init/cleanup Nigel Cunningham
@ 2006-06-26 22:42 ` Nigel Cunningham
  2006-06-26 22:42 ` [Suspend2][ 19/28] [Suspend2] Swapwriter memory needed Nigel Cunningham
                   ` (9 subsequent siblings)
  27 siblings, 0 replies; 29+ messages in thread
From: Nigel Cunningham @ 2006-06-26 22:42 UTC (permalink / raw)
  To: linux-kernel

Invalidate an image stored on swap.

Signed-off-by: Nigel Cunningham <nigel@suspend2.net>

 kernel/power/suspend_swap.c |   55 +++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 55 insertions(+), 0 deletions(-)

diff --git a/kernel/power/suspend_swap.c b/kernel/power/suspend_swap.c
index 9d806a5..ba1761b 100644
--- a/kernel/power/suspend_swap.c
+++ b/kernel/power/suspend_swap.c
@@ -750,3 +750,58 @@ static int swapwriter_read_header_cleanu
 	return 0;
 }
 
+/* swapwriter_invalidate_image
+ * 
+ */
+static int swapwriter_invalidate_image(void)
+{
+	union p_diskpage cur;
+	int result = 0;
+	char newsig[11];
+	
+	cur.address = get_zeroed_page(GFP_ATOMIC);
+	if (!cur.address) {
+		printk("Unable to allocate a page for restoring the swap signature.\n");
+		return -ENOMEM;
+	}
+
+	/*
+	 * If nr_suspends == 0, we must be booting, so no swap pages
+	 * will be recorded as used yet.
+	 */
+
+	if (nr_suspends > 0)
+		swapwriter_release_storage();
+
+	/* 
+	 * We don't do a sanity check here: we want to restore the swap 
+	 * whatever version of kernel made the suspend image.
+	 * 
+	 * We need to write swap, but swap may not be enabled so
+	 * we write the device directly
+	 */
+	
+	suspend_bio_ops.bdev_page_io(READ, resume_block_device,
+			resume_firstblock,
+			virt_to_page(cur.pointer));
+
+	result = parse_signature(cur.pointer->swh.magic.magic, 1);
+		
+	if (result < 4)
+		goto out;
+
+	strncpy(newsig, cur.pointer->swh.magic.magic, 10);
+	newsig[10] = 0;
+
+	suspend_bio_ops.bdev_page_io(WRITE, resume_block_device,
+			resume_firstblock,
+			virt_to_page(cur.pointer));
+
+	if (!nr_suspends)
+		printk(KERN_WARNING name_suspend "Image invalidated.\n");
+out:
+	suspend_bio_ops.finish_all_io();
+	free_page(cur.address);
+	return 0;
+}
+

--
Nigel Cunningham		nigel at suspend2 dot net

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Suspend2][ 19/28] [Suspend2] Swapwriter memory needed.
  2006-06-26 22:41 [Suspend2][ 00/28] Swapwriter Nigel Cunningham
                   ` (17 preceding siblings ...)
  2006-06-26 22:42 ` [Suspend2][ 18/28] [Suspend2] Invalidate swapwriter image Nigel Cunningham
@ 2006-06-26 22:42 ` Nigel Cunningham
  2006-06-26 22:42 ` [Suspend2][ 20/28] [Suspend2] Get swapwriter debug info Nigel Cunningham
                   ` (8 subsequent siblings)
  27 siblings, 0 replies; 29+ messages in thread
From: Nigel Cunningham @ 2006-06-26 22:42 UTC (permalink / raw)
  To: linux-kernel

Return the number of pages needed by the swapwriter itself. This doesn't
include the block i/o code, which has its own routine.

Signed-off-by: Nigel Cunningham <nigel@suspend2.net>

 kernel/power/suspend_swap.c |   14 ++++++++++++++
 1 files changed, 14 insertions(+), 0 deletions(-)

diff --git a/kernel/power/suspend_swap.c b/kernel/power/suspend_swap.c
index ba1761b..f2940ea 100644
--- a/kernel/power/suspend_swap.c
+++ b/kernel/power/suspend_swap.c
@@ -805,3 +805,17 @@ out:
 	return 0;
 }
 
+/*
+ * workspace_size
+ *
+ * Description:
+ * Returns the number of bytes of RAM needed for this
+ * code to do its work. (Used when calculating whether
+ * we have enough memory to be able to suspend & resume).
+ *
+ */
+static unsigned long swapwriter_memory_needed(void)
+{
+	return 1;
+}
+

--
Nigel Cunningham		nigel at suspend2 dot net

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Suspend2][ 20/28] [Suspend2] Get swapwriter debug info.
  2006-06-26 22:41 [Suspend2][ 00/28] Swapwriter Nigel Cunningham
                   ` (18 preceding siblings ...)
  2006-06-26 22:42 ` [Suspend2][ 19/28] [Suspend2] Swapwriter memory needed Nigel Cunningham
@ 2006-06-26 22:42 ` Nigel Cunningham
  2006-06-26 22:42 ` [Suspend2][ 21/28] [Suspend2] Get swapwriter image storage needed Nigel Cunningham
                   ` (7 subsequent siblings)
  27 siblings, 0 replies; 29+ messages in thread
From: Nigel Cunningham @ 2006-06-26 22:42 UTC (permalink / raw)
  To: linux-kernel

Fill a buffer with debug info for the swapwriter.

Signed-off-by: Nigel Cunningham <nigel@suspend2.net>

 kernel/power/suspend_swap.c |   28 ++++++++++++++++++++++++++++
 1 files changed, 28 insertions(+), 0 deletions(-)

diff --git a/kernel/power/suspend_swap.c b/kernel/power/suspend_swap.c
index f2940ea..3589b63 100644
--- a/kernel/power/suspend_swap.c
+++ b/kernel/power/suspend_swap.c
@@ -819,3 +819,31 @@ static unsigned long swapwriter_memory_n
 	return 1;
 }
 
+/* Print debug info
+ *
+ * Description:
+ */
+
+static int swapwriter_print_debug_stats(char *buffer, int size)
+{
+	int len = 0;
+	struct sysinfo sysinfo;
+	
+	if (suspend_active_writer != &swapwriterops) {
+		len = snprintf_used(buffer, size, "- Swapwriter inactive.\n");
+		return len;
+	}
+
+	len = snprintf_used(buffer, size, "- Swapwriter active.\n");
+	if (swapfilename[0])
+		len+= snprintf_used(buffer+len, size-len,
+			"  Attempting to automatically swapon: %s.\n", swapfilename);
+
+	si_swapinfo(&sysinfo);
+	
+	len+= snprintf_used(buffer+len, size-len, "  Swap available for image: %ld pages.\n",
+			sysinfo.freeswap + swapwriter_storage_allocated());
+
+	return len;
+}
+

--
Nigel Cunningham		nigel at suspend2 dot net

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Suspend2][ 21/28] [Suspend2] Get swapwriter image storage needed.
  2006-06-26 22:41 [Suspend2][ 00/28] Swapwriter Nigel Cunningham
                   ` (19 preceding siblings ...)
  2006-06-26 22:42 ` [Suspend2][ 20/28] [Suspend2] Get swapwriter debug info Nigel Cunningham
@ 2006-06-26 22:42 ` Nigel Cunningham
  2006-06-26 22:42 ` [Suspend2][ 22/28] [Suspend2] Does a swapwriter image exist? Nigel Cunningham
                   ` (6 subsequent siblings)
  27 siblings, 0 replies; 29+ messages in thread
From: Nigel Cunningham @ 2006-06-26 22:42 UTC (permalink / raw)
  To: linux-kernel

Return the amount of space in the image header needed for swapwriter
configuration info.

Signed-off-by: Nigel Cunningham <nigel@suspend2.net>

 kernel/power/suspend_swap.c |   25 +++++++++++++++++++++++++
 1 files changed, 25 insertions(+), 0 deletions(-)

diff --git a/kernel/power/suspend_swap.c b/kernel/power/suspend_swap.c
index 3589b63..ba6ed75 100644
--- a/kernel/power/suspend_swap.c
+++ b/kernel/power/suspend_swap.c
@@ -847,3 +847,28 @@ static int swapwriter_print_debug_stats(
 	return len;
 }
 
+/*
+ * Storage needed
+ *
+ * Returns amount of space in the swap header required
+ * for the swapwriter's data. This ignores the links between
+ * pages, which we factor in when allocating the space.
+ *
+ * We ensure the space is allocated, but actually save the
+ * data from write_header_init and therefore don't also define a
+ * save_config_info routine.
+ */
+static unsigned long swapwriter_storage_needed(void)
+{
+	int i, result;
+	result = sizeof(suspend_writer_posn_save) + sizeof(devinfo);
+
+	for (i = 0; i < MAX_SWAPFILES; i++) {
+		result += 3 * sizeof(int);
+		result += (2 * sizeof(unsigned long) * 
+			(block_chain[i].allocs - block_chain[i].frees));
+	}
+
+	return result;
+}
+

--
Nigel Cunningham		nigel at suspend2 dot net

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Suspend2][ 22/28] [Suspend2] Does a swapwriter image exist?
  2006-06-26 22:41 [Suspend2][ 00/28] Swapwriter Nigel Cunningham
                   ` (20 preceding siblings ...)
  2006-06-26 22:42 ` [Suspend2][ 21/28] [Suspend2] Get swapwriter image storage needed Nigel Cunningham
@ 2006-06-26 22:42 ` Nigel Cunningham
  2006-06-26 22:42 ` [Suspend2][ 23/28] [Suspend2] Swapwriter mark resume attempted Nigel Cunningham
                   ` (5 subsequent siblings)
  27 siblings, 0 replies; 29+ messages in thread
From: Nigel Cunningham @ 2006-06-26 22:42 UTC (permalink / raw)
  To: linux-kernel

Return whether there is an image at the location currently pointed to by
resume2=.

Signed-off-by: Nigel Cunningham <nigel@suspend2.net>

 kernel/power/suspend_swap.c |   54 +++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 54 insertions(+), 0 deletions(-)

diff --git a/kernel/power/suspend_swap.c b/kernel/power/suspend_swap.c
index ba6ed75..7342cb2 100644
--- a/kernel/power/suspend_swap.c
+++ b/kernel/power/suspend_swap.c
@@ -872,3 +872,57 @@ static unsigned long swapwriter_storage_
 	return result;
 }
 
+/*
+ * Image_exists
+ */
+
+static int swapwriter_image_exists(void)
+{
+	int signature_found;
+	union p_diskpage diskpage;
+	
+	if (!resume_dev_t) {
+		printk("Not even trying to read header "
+				"because resume_dev_t is not set.\n");
+		return 0;
+	}
+	
+	if (!resume_block_device &&
+	    IS_ERR(resume_block_device = open_bdev(MAX_SWAPFILES, resume_dev_t)))
+		return 0;
+
+	diskpage.address = get_zeroed_page(GFP_ATOMIC);
+
+	suspend_bio_ops.bdev_page_io(READ, resume_block_device,
+			resume_firstblock,
+			virt_to_page(diskpage.ptr));
+	suspend_bio_ops.finish_all_io();
+
+	signature_found = parse_signature(diskpage.pointer->swh.magic.magic, 0);
+	free_page(diskpage.address);
+
+	if (signature_found < 2) {
+		return 0;	/* Normal swap space */
+	} else if (signature_found == -1) {
+		printk(KERN_ERR name_suspend
+			"Unable to find a signature. Could you have moved "
+			"a swap file?\n");
+		return 0;
+	} else if (signature_found < 6) {
+		if ((!(test_suspend_state(SUSPEND_NORESUME_SPECIFIED)))
+				&& suspend_early_boot_message(1,
+				SUSPEND_CONTINUE_REQ,
+				"Detected the signature of an alternate "
+				"implementation.\n"))
+			set_suspend_state(SUSPEND_NORESUME_SPECIFIED);
+		return 0;
+	} else if ((signature_found >> 1) != SIGNATURE_VER) {
+		if ((!(test_suspend_state(SUSPEND_NORESUME_SPECIFIED))) &&
+			suspend_early_boot_message(1, SUSPEND_CONTINUE_REQ,
+			 "Found a different style suspend image signature."))
+			set_suspend_state(SUSPEND_NORESUME_SPECIFIED);
+	}
+
+	return 1;
+}
+

--
Nigel Cunningham		nigel at suspend2 dot net

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Suspend2][ 23/28] [Suspend2] Swapwriter mark resume attempted.
  2006-06-26 22:41 [Suspend2][ 00/28] Swapwriter Nigel Cunningham
                   ` (21 preceding siblings ...)
  2006-06-26 22:42 ` [Suspend2][ 22/28] [Suspend2] Does a swapwriter image exist? Nigel Cunningham
@ 2006-06-26 22:42 ` Nigel Cunningham
  2006-06-26 22:42 ` [Suspend2][ 24/28] [Suspend2] Swapwriter parse resume2= Nigel Cunningham
                   ` (4 subsequent siblings)
  27 siblings, 0 replies; 29+ messages in thread
From: Nigel Cunningham @ 2006-06-26 22:42 UTC (permalink / raw)
  To: linux-kernel

Mark in the signature of a swap image that we've attempted to resume from
this image before.

Signed-off-by: Nigel Cunningham <nigel@suspend2.net>

 kernel/power/suspend_swap.c |   41 +++++++++++++++++++++++++++++++++++++++++
 1 files changed, 41 insertions(+), 0 deletions(-)

diff --git a/kernel/power/suspend_swap.c b/kernel/power/suspend_swap.c
index 7342cb2..683797a 100644
--- a/kernel/power/suspend_swap.c
+++ b/kernel/power/suspend_swap.c
@@ -926,3 +926,44 @@ static int swapwriter_image_exists(void)
 	return 1;
 }
 
+/*
+ * Mark resume attempted.
+ *
+ * Record that we tried to resume from this image.
+ */
+
+static void swapwriter_mark_resume_attempted(void)
+{
+	union p_diskpage diskpage;
+	int signature_found;
+	
+	if (!resume_dev_t) {
+		printk("Not even trying to record attempt at resuming"
+				" because resume_dev_t is not set.\n");
+		return;
+	}
+	
+	diskpage.address = get_zeroed_page(GFP_ATOMIC);
+
+	suspend_bio_ops.bdev_page_io(READ, resume_block_device,
+			resume_firstblock,
+			virt_to_page(diskpage.ptr));
+	signature_found = parse_signature(diskpage.pointer->swh.magic.magic, 0);
+
+	switch (signature_found) {
+		case 12:
+		case 13:
+			diskpage.pointer->swh.magic.magic[5] |= 0x80;
+			break;
+	}
+	
+	suspend_bio_ops.bdev_page_io(WRITE, resume_block_device,
+			resume_firstblock,
+			virt_to_page(diskpage.ptr));
+	suspend_bio_ops.finish_all_io();
+	free_page(diskpage.address);
+	
+	close_bdevs();
+	return;
+}
+

--
Nigel Cunningham		nigel at suspend2 dot net

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Suspend2][ 24/28] [Suspend2] Swapwriter parse resume2=
  2006-06-26 22:41 [Suspend2][ 00/28] Swapwriter Nigel Cunningham
                   ` (22 preceding siblings ...)
  2006-06-26 22:42 ` [Suspend2][ 23/28] [Suspend2] Swapwriter mark resume attempted Nigel Cunningham
@ 2006-06-26 22:42 ` Nigel Cunningham
  2006-06-26 22:42 ` [Suspend2][ 25/28] [Suspend2] Read resume2= values for currently enabled swap Nigel Cunningham
                   ` (3 subsequent siblings)
  27 siblings, 0 replies; 29+ messages in thread
From: Nigel Cunningham @ 2006-06-26 22:42 UTC (permalink / raw)
  To: linux-kernel

Attempt to parse the resume2= value as a swapwriter target, checking that
the device can be accessed and that the header is recognised.

Signed-off-by: Nigel Cunningham <nigel@suspend2.net>

 kernel/power/suspend_swap.c |  113 +++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 113 insertions(+), 0 deletions(-)

diff --git a/kernel/power/suspend_swap.c b/kernel/power/suspend_swap.c
index 683797a..eb14e3e 100644
--- a/kernel/power/suspend_swap.c
+++ b/kernel/power/suspend_swap.c
@@ -967,3 +967,116 @@ static void swapwriter_mark_resume_attem
 	return;
 }
 
+/*
+ * Parse Image Location
+ *
+ * Attempt to parse a resume2= parameter.
+ * Swap Writer accepts:
+ * resume2=swap:DEVNAME[:FIRSTBLOCK][@BLOCKSIZE]
+ *
+ * Where:
+ * DEVNAME is convertable to a dev_t by name_to_dev_t
+ * FIRSTBLOCK is the location of the first block in the swap file
+ * (specifying for a swap partition is nonsensical but not prohibited).
+ * Data is validated by attempting to read a swap header from the
+ * location given. Failure will result in swapwriter refusing to
+ * save an image, and a reboot with correct parameters will be
+ * necessary.
+ */
+
+static int swapwriter_parse_sig_location(char *commandline, int only_writer)
+{
+	char *thischar, *devstart, *colon = NULL, *at_symbol = NULL;
+	union p_diskpage diskpage;
+	int signature_found, result = -EINVAL, temp_result;
+
+	if (strncmp(commandline, "swap:", 5)) {
+		if (!only_writer)
+			return 1;
+	} else
+		commandline += 5;
+
+	devstart = thischar = commandline;
+	while ((*thischar != ':') && (*thischar != '@') &&
+		((thischar - commandline) < 250) && (*thischar))
+		thischar++;
+
+	if (*thischar == ':') {
+		colon = thischar;
+		*colon = 0;
+		thischar++;
+	}
+
+	while ((*thischar != '@') && ((thischar - commandline) < 250) && (*thischar))
+		thischar++;
+
+	if (*thischar == '@') {
+		at_symbol = thischar;
+		*at_symbol = 0;
+	}
+	
+	if (colon)
+		resume_firstblock = (int) simple_strtoul(colon + 1, NULL, 0);
+	else
+		resume_firstblock = 0;
+
+	clear_suspend_state(SUSPEND_CAN_SUSPEND);
+	clear_suspend_state(SUSPEND_CAN_RESUME);
+	
+	/* Legacy */
+	if (at_symbol) {
+		resume_blocksize = (int) simple_strtoul(at_symbol + 1, NULL, 0);
+		if (resume_blocksize & (SECTOR_SIZE - 1)) {
+			printk("Swapwriter: Blocksizes are multiples of %d!\n", SECTOR_SIZE);
+			return -EINVAL;
+		}
+		resume_firstblock = resume_firstblock * (resume_blocksize / SECTOR_SIZE);
+	}
+	
+	temp_result = try_to_parse_resume_device(devstart);
+
+	if (colon)
+		*colon = ':';
+	if (at_symbol)
+		*at_symbol = '@';
+
+	if (temp_result)
+		return -EINVAL;
+
+	diskpage.address = get_zeroed_page(GFP_ATOMIC);
+	if (!diskpage.address) {
+		printk(KERN_ERR name_suspend "Swapwriter: Failed to allocate a diskpage for I/O.\n");
+		return -ENOMEM;
+	}
+
+	temp_result = suspend_bio_ops.bdev_page_io(READ,
+			resume_block_device,
+			resume_firstblock,
+			virt_to_page(diskpage.ptr));
+
+	suspend_bio_ops.finish_all_io();
+	
+	if (temp_result) {
+		printk(KERN_ERR name_suspend "Swapwriter: Failed to submit I/O.\n");
+		goto invalid;
+	}
+	
+	signature_found = parse_signature(diskpage.pointer->swh.magic.magic, 0);
+
+	if (signature_found != -1) {
+		printk(name_suspend "Swapwriter: Signature found.\n");
+		result = 0;
+
+		suspend_bio_ops.set_devinfo(devinfo);
+		suspend_writer_posn.chains = &block_chain[0];
+		suspend_writer_posn.num_chains = MAX_SWAPFILES;
+		set_suspend_state(SUSPEND_CAN_SUSPEND);
+		set_suspend_state(SUSPEND_CAN_RESUME);
+	} else
+		printk(KERN_ERR name_suspend "Swapwriter: No swap signature found at specified location.\n");
+invalid:
+	free_page((unsigned long) diskpage.address);
+	return result;
+
+}
+

--
Nigel Cunningham		nigel at suspend2 dot net

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Suspend2][ 25/28] [Suspend2] Read resume2= values for currently enabled swap.
  2006-06-26 22:41 [Suspend2][ 00/28] Swapwriter Nigel Cunningham
                   ` (23 preceding siblings ...)
  2006-06-26 22:42 ` [Suspend2][ 24/28] [Suspend2] Swapwriter parse resume2= Nigel Cunningham
@ 2006-06-26 22:42 ` Nigel Cunningham
  2006-06-26 22:42 ` [Suspend2][ 26/28] [Suspend2] Swapwriter proc entries Nigel Cunningham
                   ` (2 subsequent siblings)
  27 siblings, 0 replies; 29+ messages in thread
From: Nigel Cunningham @ 2006-06-26 22:42 UTC (permalink / raw)
  To: linux-kernel

Get the values to use for resume2= for swap that is currently enabled.
Particularly useful for files, where we need the device and block offset.

Signed-off-by: Nigel Cunningham <nigel@suspend2.net>

 kernel/power/suspend_swap.c |   60 +++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 60 insertions(+), 0 deletions(-)

diff --git a/kernel/power/suspend_swap.c b/kernel/power/suspend_swap.c
index eb14e3e..ee7c36b 100644
--- a/kernel/power/suspend_swap.c
+++ b/kernel/power/suspend_swap.c
@@ -1080,3 +1080,63 @@ invalid:
 
 }
 
+static int header_locations_read_proc(char *page, char **start, off_t off, int count,
+		int *eof, void *data)
+{
+	int i, printedpartitionsmessage = 0, len = 0, haveswap = 0;
+	struct inode *swapf = 0;
+	int zone;
+	char *path_page = (char *) __get_free_page(GFP_KERNEL);
+	char *path;
+	int path_len;
+	
+	*eof = 1;
+	if (!page)
+		return 0;
+
+	for (i = 0; i < MAX_SWAPFILES; i++) {
+		struct swap_info_struct *si =  get_swap_info_struct(i);
+
+		if (!si->swap_file)
+			continue;
+		
+		if (S_ISBLK(si->swap_file->f_mapping->host->i_mode)) {
+			haveswap = 1;
+			if (!printedpartitionsmessage) {
+				len += sprintf(page + len, 
+					"For swap partitions, simply use the format: resume2=swap:/dev/hda1.\n");
+				printedpartitionsmessage = 1;
+			}
+		} else {
+			path_len = 0;
+			
+			path = d_path(si->swap_file->f_dentry,
+				si->swap_file->f_vfsmnt,
+				path_page,
+				PAGE_SIZE);
+			path_len = snprintf(path_page, 31, "%s", path);
+			
+			haveswap = 1;
+			swapf = si->swap_file->f_mapping->host;
+			if (!(zone = bmap(swapf,0))) {
+				len+= sprintf(page + len, 
+					"Swapfile %s has been corrupted. Reuse mkswap on it and try again.\n",
+					path_page);
+			} else {
+				char name_buffer[255];
+				len+= sprintf(page + len, "For swapfile `%s`, use resume2=swap:/dev/%s:0x%x.\n",
+						path_page,
+						bdevname(si->bdev, name_buffer),
+						zone << (swapf->i_blkbits - 9));
+			}
+
+		}
+	}
+	
+	if (!haveswap)
+		len = sprintf(page, "You need to turn on swap partitions before examining this file.\n");
+
+	free_page((unsigned long) path_page);
+	return len;
+}
+

--
Nigel Cunningham		nigel at suspend2 dot net

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Suspend2][ 26/28] [Suspend2] Swapwriter proc entries.
  2006-06-26 22:41 [Suspend2][ 00/28] Swapwriter Nigel Cunningham
                   ` (24 preceding siblings ...)
  2006-06-26 22:42 ` [Suspend2][ 25/28] [Suspend2] Read resume2= values for currently enabled swap Nigel Cunningham
@ 2006-06-26 22:42 ` Nigel Cunningham
  2006-06-26 22:42 ` [Suspend2][ 27/28] [Suspend2] Swapwriter ops Nigel Cunningham
  2006-06-26 22:42 ` [Suspend2][ 28/28] [Suspend2] Swapwriter load and unload routines Nigel Cunningham
  27 siblings, 0 replies; 29+ messages in thread
From: Nigel Cunningham @ 2006-06-26 22:42 UTC (permalink / raw)
  To: linux-kernel

Definitions the for the proc entries provided by the swapwriter.

Signed-off-by: Nigel Cunningham <nigel@suspend2.net>

 kernel/power/suspend_swap.c |   38 ++++++++++++++++++++++++++++++++++++++
 1 files changed, 38 insertions(+), 0 deletions(-)

diff --git a/kernel/power/suspend_swap.c b/kernel/power/suspend_swap.c
index ee7c36b..e210241 100644
--- a/kernel/power/suspend_swap.c
+++ b/kernel/power/suspend_swap.c
@@ -1140,3 +1140,41 @@ static int header_locations_read_proc(ch
 	return len;
 }
 
+static struct suspend_proc_data swapwriter_proc_data[] = {
+	{
+	 .filename			= "swapfilename",
+	 .permissions			= PROC_RW,
+	 .type				= SUSPEND_PROC_DATA_STRING,
+	 .data = {
+		.string = {
+			.variable	= swapfilename,
+			.max_length	= 255,
+		}
+	 }
+	},
+
+	{
+	 .filename			= "headerlocations",
+	 .permissions			= PROC_READONLY,
+	 .type				= SUSPEND_PROC_DATA_CUSTOM,
+	 .data = {
+		 .special = {
+			.read_proc 	= header_locations_read_proc,
+		}
+	 }
+	},
+
+	{ .filename			= "disable_swapwriter",
+	  .permissions			= PROC_RW,
+	  .type				= SUSPEND_PROC_DATA_INTEGER,
+	  .data = {
+		.integer = {
+			.variable	= &swapwriterops.disabled,
+			.minimum	= 0,
+			.maximum	= 1,
+		}
+	  },
+	  .write_proc			= attempt_to_parse_resume_device2,
+	}
+};
+

--
Nigel Cunningham		nigel at suspend2 dot net

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Suspend2][ 27/28] [Suspend2] Swapwriter ops.
  2006-06-26 22:41 [Suspend2][ 00/28] Swapwriter Nigel Cunningham
                   ` (25 preceding siblings ...)
  2006-06-26 22:42 ` [Suspend2][ 26/28] [Suspend2] Swapwriter proc entries Nigel Cunningham
@ 2006-06-26 22:42 ` Nigel Cunningham
  2006-06-26 22:42 ` [Suspend2][ 28/28] [Suspend2] Swapwriter load and unload routines Nigel Cunningham
  27 siblings, 0 replies; 29+ messages in thread
From: Nigel Cunningham @ 2006-06-26 22:42 UTC (permalink / raw)
  To: linux-kernel

Structure defining the swapwriter operations exported for use by the core.

Signed-off-by: Nigel Cunningham <nigel@suspend2.net>

 kernel/power/suspend_swap.c |   26 ++++++++++++++++++++++++++
 1 files changed, 26 insertions(+), 0 deletions(-)

diff --git a/kernel/power/suspend_swap.c b/kernel/power/suspend_swap.c
index e210241..b04e2f3 100644
--- a/kernel/power/suspend_swap.c
+++ b/kernel/power/suspend_swap.c
@@ -1178,3 +1178,29 @@ static struct suspend_proc_data swapwrit
 	}
 };
 
+static struct suspend_module_ops swapwriterops = {
+	.type					= WRITER_MODULE,
+	.name					= "Swap Writer",
+	.module					= THIS_MODULE,
+	.memory_needed				= swapwriter_memory_needed,
+	.print_debug_info			= swapwriter_print_debug_stats,
+	.storage_needed				= swapwriter_storage_needed,
+	.initialise				= swapwriter_initialise,
+	.cleanup				= swapwriter_cleanup,
+
+	.noresume_reset	= swapwriter_noresume_reset,
+	.storage_available 	= swapwriter_storage_available,
+	.storage_allocated	= swapwriter_storage_allocated,
+	.release_storage	= swapwriter_release_storage,
+	.allocate_header_space	= swapwriter_allocate_header_space,
+	.allocate_storage	= swapwriter_allocate_storage,
+	.image_exists		= swapwriter_image_exists,
+	.mark_resume_attempted	= swapwriter_mark_resume_attempted,
+	.write_header_init	= swapwriter_write_header_init,
+	.write_header_cleanup	= swapwriter_write_header_cleanup,
+	.read_header_init	= swapwriter_read_header_init,
+	.read_header_cleanup	= swapwriter_read_header_cleanup,
+	.invalidate_image	= swapwriter_invalidate_image,
+	.parse_sig_location	= swapwriter_parse_sig_location,
+};
+       

--
Nigel Cunningham		nigel at suspend2 dot net

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Suspend2][ 28/28] [Suspend2] Swapwriter load and unload routines.
  2006-06-26 22:41 [Suspend2][ 00/28] Swapwriter Nigel Cunningham
                   ` (26 preceding siblings ...)
  2006-06-26 22:42 ` [Suspend2][ 27/28] [Suspend2] Swapwriter ops Nigel Cunningham
@ 2006-06-26 22:42 ` Nigel Cunningham
  27 siblings, 0 replies; 29+ messages in thread
From: Nigel Cunningham @ 2006-06-26 22:42 UTC (permalink / raw)
  To: linux-kernel

Routines invoked with the swapwriter is loaded or unloaded.

Signed-off-by: Nigel Cunningham <nigel@suspend2.net>

 kernel/power/suspend_swap.c |   43 +++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 43 insertions(+), 0 deletions(-)

diff --git a/kernel/power/suspend_swap.c b/kernel/power/suspend_swap.c
index b04e2f3..7939ad2 100644
--- a/kernel/power/suspend_swap.c
+++ b/kernel/power/suspend_swap.c
@@ -1204,3 +1204,46 @@ static struct suspend_module_ops swapwri
 	.parse_sig_location	= swapwriter_parse_sig_location,
 };
        
+/* ---- Registration ---- */
+static __init int swapwriter_load(void)
+{
+	int result;
+	int i, numfiles = sizeof(swapwriter_proc_data) / sizeof(struct suspend_proc_data);
+	
+	printk("Suspend2 Swap Writer loading.\n");
+
+	swapwriterops.rw_init = suspend_bio_ops.rw_init;
+	swapwriterops.rw_cleanup = suspend_bio_ops.rw_cleanup;
+	swapwriterops.read_chunk = suspend_bio_ops.read_chunk;
+	swapwriterops.write_chunk = suspend_bio_ops.write_chunk;
+	swapwriterops.rw_header_chunk = suspend_bio_ops.rw_header_chunk;
+
+	if (!(result = suspend_register_module(&swapwriterops))) {
+
+		for (i=0; i< numfiles; i++)
+			suspend_register_procfile(&swapwriter_proc_data[i]);
+	} else
+		printk("Suspend2 Swap Writer unable to register!\n");
+	return result;
+}
+
+#ifdef MODULE
+static __exit void swapwriter_unload(void)
+{
+	int i, numfiles = sizeof(swapwriter_proc_data) / sizeof(struct suspend_proc_data);
+
+	printk("Suspend2 Swap Writer unloading.\n");
+
+	for (i=0; i< numfiles; i++)
+		suspend_unregister_procfile(&swapwriter_proc_data[i]);
+	suspend_unregister_module(&swapwriterops);
+}
+
+module_init(swapwriter_load);
+module_exit(swapwriter_unload);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Nigel Cunningham");
+MODULE_DESCRIPTION("Suspend2 swap writer");
+#else
+late_initcall(swapwriter_load);
+#endif

--
Nigel Cunningham		nigel at suspend2 dot net

^ permalink raw reply related	[flat|nested] 29+ messages in thread

end of thread, other threads:[~2006-06-26 22:54 UTC | newest]

Thread overview: 29+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-06-26 22:41 [Suspend2][ 00/28] Swapwriter Nigel Cunningham
2006-06-26 22:41 ` [Suspend2][ 01/28] [Suspend2] Swapwriter.c header Nigel Cunningham
2006-06-26 22:41 ` [Suspend2][ 02/28] [Suspend2] Close a bdev used by the swapwriter Nigel Cunningham
2006-06-26 22:41 ` [Suspend2][ 03/28] [Suspend2] Close bdevs opened " Nigel Cunningham
2006-06-26 22:41 ` [Suspend2][ 04/28] [Suspend2] Open bdev for swapwriter use Nigel Cunningham
2006-06-26 22:41 ` [Suspend2][ 05/28] [Suspend2] Enable/disable swapfile Nigel Cunningham
2006-06-26 22:41 ` [Suspend2][ 06/28] [Suspend2] Try to parse resume2= for swapwriter Nigel Cunningham
2006-06-26 22:41 ` [Suspend2][ 07/28] [Suspend2] Reset swapwriter when not resuming Nigel Cunningham
2006-06-26 22:41 ` [Suspend2][ 08/28] [Suspend2] Parse swapwriter signature Nigel Cunningham
2006-06-26 22:41 ` [Suspend2][ 09/28] [Suspend2] Prepare " Nigel Cunningham
2006-06-26 22:41 ` [Suspend2][ 10/28] [Suspend2] Allocate swapwriter header space Nigel Cunningham
2006-06-26 22:41 ` [Suspend2][ 11/28] [Suspend2] Get block chains for swapwriter Nigel Cunningham
2006-06-26 22:41 ` [Suspend2][ 12/28] [Suspend2] Swapwriter storage allocated and available Nigel Cunningham
2006-06-26 22:41 ` [Suspend2][ 13/28] [Suspend2] Initialise/cleanup swapwriter Nigel Cunningham
2006-06-26 22:41 ` [Suspend2][ 14/28] [Suspend2] Release swapwriter storage Nigel Cunningham
2006-06-26 22:41 ` [Suspend2][ 15/28] [Suspend2] Allocate " Nigel Cunningham
2006-06-26 22:42 ` [Suspend2][ 16/28] [Suspend2] Initialise/cleanup writing the header Nigel Cunningham
2006-06-26 22:42 ` [Suspend2][ 17/28] [Suspend2] Swapwriter read image header init/cleanup Nigel Cunningham
2006-06-26 22:42 ` [Suspend2][ 18/28] [Suspend2] Invalidate swapwriter image Nigel Cunningham
2006-06-26 22:42 ` [Suspend2][ 19/28] [Suspend2] Swapwriter memory needed Nigel Cunningham
2006-06-26 22:42 ` [Suspend2][ 20/28] [Suspend2] Get swapwriter debug info Nigel Cunningham
2006-06-26 22:42 ` [Suspend2][ 21/28] [Suspend2] Get swapwriter image storage needed Nigel Cunningham
2006-06-26 22:42 ` [Suspend2][ 22/28] [Suspend2] Does a swapwriter image exist? Nigel Cunningham
2006-06-26 22:42 ` [Suspend2][ 23/28] [Suspend2] Swapwriter mark resume attempted Nigel Cunningham
2006-06-26 22:42 ` [Suspend2][ 24/28] [Suspend2] Swapwriter parse resume2= Nigel Cunningham
2006-06-26 22:42 ` [Suspend2][ 25/28] [Suspend2] Read resume2= values for currently enabled swap Nigel Cunningham
2006-06-26 22:42 ` [Suspend2][ 26/28] [Suspend2] Swapwriter proc entries Nigel Cunningham
2006-06-26 22:42 ` [Suspend2][ 27/28] [Suspend2] Swapwriter ops Nigel Cunningham
2006-06-26 22:42 ` [Suspend2][ 28/28] [Suspend2] Swapwriter load and unload routines Nigel Cunningham

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).