Use the ioctl defined in the previous patch to support the suspend to/resume
from swap files.

Introduce an additional configuration parameter "resume offset" that will
allow us to specify the offset (in <PAGE_SIZE> units) at which the swap
file's header is located.  At the same time the "resume device" parameter
must point to the partition device which holds the swap file.

To determine the location of the swap header of a swap file we'll need a
special application using the FIBMAP ioctl to bmap the file and find the
header.  There's no such application currently available, but I'm going to
write (simple) one.

Nonetheless the patches have been tested on i386 and x86_64.

---
 resume.c  |    8 +++++++-
 suspend.c |   31 +++++++++++++++++++++++++------
 swsusp.h  |   12 +++++++++---
 3 files changed, 41 insertions(+), 10 deletions(-)

Index: suspend/suspend.c
===================================================================
--- suspend.orig/suspend.c
+++ suspend/suspend.c
@@ -45,6 +45,7 @@
 
 static char snapshot_dev_name[MAX_STR_LEN] = SNAPSHOT_DEVICE;
 static char resume_dev_name[MAX_STR_LEN] = RESUME_DEVICE;
+static loff_t resume_offset;
 static unsigned long pref_image_size = IMAGE_SIZE;
 static int suspend_loglevel = SUSPEND_LOGLEVEL;
 static char compute_checksum;
@@ -89,6 +90,11 @@ static struct config_par parameters[PARA
                .len = MAX_STR_LEN
        },
        {
+               .name = "resume offset",
+               .fmt = "%llu",
+               .ptr = &resume_offset,
+       },
+       {
                .name = "image size",
                .fmt = "%lu",
                .ptr = &pref_image_size,
@@ -185,9 +191,18 @@ static inline int free_swap_pages(int de
        return ioctl(dev, SNAPSHOT_FREE_SWAP_PAGES, 0);
 }
 
-static inline int set_swap_file(int dev, dev_t blkdev)
+static inline int set_swap_file(int dev, dev_t blkdev, loff_t offset)
 {
-       return ioctl(dev, SNAPSHOT_SET_SWAP_FILE, blkdev);
+       struct resume_swap_area swap;
+       int error;
+
+       swap.dev = blkdev;
+       swap.offset = offset;
+       error = ioctl(dev, SNAPSHOT_SET_SWAP_AREA, &swap);
+       if (error && !offset)
+               error = ioctl(dev, SNAPSHOT_SET_SWAP_DEV, blkdev);
+
+       return error;
 }
 
 /**
@@ -236,7 +251,8 @@ struct swap_map_handle {
 #endif
 };
 
-static int init_swap_writer(struct swap_map_handle *handle, int dev, int fd, 
void *buf)
+static int
+init_swap_writer(struct swap_map_handle *handle, int dev, int fd, void *buf)
 {
        if (!buf)
                return -EINVAL;
@@ -477,12 +493,14 @@ static int mark_swap(int fd, loff_t star
 {
        int error = 0;
        unsigned int size = sizeof(struct swsusp_header);
-       unsigned int shift = page_size - size;
+       unsigned int shift = (resume_offset + 1) * page_size - size;
 
        if (lseek(fd, shift, SEEK_SET) != shift)
                return -EIO;
+
        if (read(fd, &swsusp_header, size) < size)
                return -EIO;
+
        if (!memcmp("SWAP-SPACE", swsusp_header.sig, 10) ||
            !memcmp("SWAPSPACE2", swsusp_header.sig, 10)) {
                memcpy(swsusp_header.orig_sig, swsusp_header.sig, 10);
@@ -490,6 +508,7 @@ static int mark_swap(int fd, loff_t star
                swsusp_header.image = start;
                if (lseek(fd, shift, SEEK_SET) != shift)
                        return -EIO;
+
                if (write(fd, &swsusp_header, size) < size)
                        error = -EIO;
        } else {
@@ -620,7 +639,7 @@ static int reset_signature(int fd)
 {
        int ret, error = 0;
        unsigned int size = sizeof(struct swsusp_header);
-       unsigned int shift = page_size - size;
+       unsigned int shift = (resume_offset + 1) * page_size - size;
 
        if (lseek(fd, shift, SEEK_SET) != shift)
                return -EIO;
@@ -1244,7 +1263,7 @@ int main(int argc, char *argv[])
                goto Close_resume_fd;
        }
 
-       if (set_swap_file(snapshot_fd, resume_dev)) {
+       if (set_swap_file(snapshot_fd, resume_dev, resume_offset)) {
                ret = errno;
                fprintf(stderr, "suspend: Could not use the resume device "
                        "(try swapon -a)\n");
Index: suspend/swsusp.h
===================================================================
--- suspend.orig/swsusp.h
+++ suspend/swsusp.h
@@ -24,10 +24,16 @@
 #define SNAPSHOT_AVAIL_SWAP            _IOR(SNAPSHOT_IOC_MAGIC, 7, void *)
 #define SNAPSHOT_GET_SWAP_PAGE         _IOR(SNAPSHOT_IOC_MAGIC, 8, void *)
 #define SNAPSHOT_FREE_SWAP_PAGES       _IO(SNAPSHOT_IOC_MAGIC, 9)
-#define SNAPSHOT_SET_SWAP_FILE         _IOW(SNAPSHOT_IOC_MAGIC, 10, unsigned 
int)
+#define SNAPSHOT_SET_SWAP_DEV          _IOW(SNAPSHOT_IOC_MAGIC, 10, unsigned 
int)
 #define SNAPSHOT_S2RAM                 _IO(SNAPSHOT_IOC_MAGIC, 11)
 #define SNAPSHOT_PMOPS                 _IOW(SNAPSHOT_IOC_MAGIC, 12, unsigned 
int)
-#define SNAPSHOT_IOC_MAXNR     12
+#define SNAPSHOT_SET_SWAP_AREA         _IOW(SNAPSHOT_IOC_MAGIC, 13, void *)
+#define SNAPSHOT_IOC_MAXNR     13
+
+struct resume_swap_area {
+       u_int16_t dev;
+       loff_t offset;
+} __attribute__((packed));
 
 #define PMOPS_PREPARE  1
 #define PMOPS_ENTER    2
@@ -190,7 +196,7 @@ struct buf_block {
 
 #define SUSPEND_SWAPPINESS     100
 
-#define GEN_PARAM      9
+#define GEN_PARAM      10
 
 #ifdef CONFIG_COMPRESS
 #define COMPRESS_PARAM 1
Index: suspend/resume.c
===================================================================
--- suspend.orig/resume.c
+++ suspend/resume.c
@@ -37,6 +37,7 @@
 
 static char snapshot_dev_name[MAX_STR_LEN] = SNAPSHOT_DEVICE;
 static char resume_dev_name[MAX_STR_LEN] = RESUME_DEVICE;
+static loff_t resume_offset;
 static int suspend_loglevel = SUSPEND_LOGLEVEL;
 static int max_loglevel = MAX_LOGLEVEL;
 static char verify_checksum;
@@ -68,6 +69,11 @@ static struct config_par parameters[PARA
                .len = MAX_STR_LEN
        },
        {
+               .name = "resume offset",
+               .fmt = "%llu",
+               .ptr = &resume_offset,
+       },
+       {
                .name = "suspend loglevel",
                .fmt = "%d",
                .ptr = &suspend_loglevel,
@@ -532,7 +538,7 @@ static int read_image(int dev, char *res
        char *buffer = (char *)mem_pool + page_size;
        unsigned int nr_pages;
        unsigned int size = sizeof(struct swsusp_header);
-       unsigned int shift = page_size - size;
+       unsigned int shift = (resume_offset + 1) * page_size - size;
        char c;
 
        fd = open(resume_dev_name, O_RDWR);

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys -- and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
Suspend-devel mailing list
Suspend-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/suspend-devel

Reply via email to