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