Home > I O > I O Error Reading Swsusp Image

I O Error Reading Swsusp Image

As far as the files I restored and how they might relate to swsusp, I have no idea. Also, bootin single user mode or even with init=/bin/bash (and then "mount -oremount,rw /") and purge any package related to swsusp ("apt-cachesearch swsusp" gives me only the package uswsusp). But then I did an update and upgrade, and now I am > > getting the same swsusp error I had before and can't boot! > > check in the bootloader prompt the kernel command line. Are you sure that the files you restored arenot responsable for the apparence of swsusp in the boot process?Yes, I'm sure mondorestore doesn't change the partitions (not usingthe nuke option, just restoring files, and I've done that part beforesuccessfully).Post by NN_il_ConfusionarioPost by w***@gmail.comthat point.

After the all of the data pages have been written, the order - * of the swp_map_page structures in the map is reversed so that they - * can be read from swap in the original order. and that's what we want. + * we make the device unusable. Hopefully I won't be back, but I will if swsusp shows up again! - John Reply to: debian-user@lists.debian.org [email protected] (on-list) [email protected] (off-list) References: Re: HELP - Can't boot - I/O error reading swsusp.image From: "[email protected]" Re: HELP - Can't boot - I/O error reading swsusp.image From: NN_il_Confusionario Prev by Date: Re: Clearing SWAP Next by Date: Re: Clearing SWAP Previous by thread: Re: HELP - Can't boot - I/O error reading swsusp.image Next by thread: device names Index(es): Date Thread [email protected] Discussion: HELP - Can't boot - I/O error reading swsusp.image (too old to reply) w***@gmail.com 2008-05-03 21:23:46 UTC PermalinkRaw Message Help! This should be + * corrected eventually when the cases giving rise to this + * are better understood. + */ + if (PageReserved(page)) { + printk("highmem reserved page?!\n"); + continue; } - } - return swp_map; -} - -static inline swp_map_t *reverse_swp_map(swp_map_t *swp_map) -{ - swp_map_t *prev, *next; - - prev = NULL; - while (swp_map) { - next = swp_map->next; - swp_map->next = prev; - prev = swp_map; - swp_map = next; - } - return prev; -} - -/** - * save_swp_map - save the swap map used for tracing the data pages - * stored in swap - */ - -static int save_swp_map(swp_map_t *swp_map, swp_entry_t *start) -{ - swp_entry_t entry = (swp_entry_t){0}; - int error; - - while (swp_map) { - swp_map->next_swp = entry; - if ((error = write_page((unsigned long)swp_map, &entry))) - return error; - swp_map = swp_map->next; - } - *start = entry; - return 0; -} - -static inline void free_swp_map_entries(swp_map_t *swp_map) -{ - while (swp_map) { - if (swp_map->next_swp.val) - swap_free(swp_map->next_swp); - swp_map = swp_map->next; - } -} - -/** - * save_image - save the image data provided by the snapshot-handling - * part to swap. https://lists.debian.org/debian-user/2008/05/msg00269.html

Bios + * finish asynchronously, while we want them to happen synchronously. + * A simple atomic_t, and a wait loop take care of this problem. + */ + +static atomic_t io_done = ATOMIC_INIT(0); + +static int end_io(struct bio * bio, unsigned int num, int err) +{ + if (!test_bit(BIO_UPTODATE, &bio->bi_flags)) + panic("I/O error reading memory image"); + atomic_set(&io_done, 0); + return 0; +} + +static struct block_device * resume_bdev; + +/** + * submit - submit BIO request. + * @rw: READ or WRITE. + * @off physical offset of page. + * @page: page we're reading or writing. + * + * Straight from the textbook - allocate and initialize the bio. + * If we're writing, make sure the page is marked as dirty. + * Then submit it and wait. + */ + +static int submit(int rw, pgoff_t page_off, void * page) +{ + int error = 0; + struct bio * bio; + + bio = bio_alloc(GFP_ATOMIC, 1); + if (!bio) + return -ENOMEM; + bio->bi_sector = page_off * (PAGE_SIZE >> 9); + bio_get(bio); + bio->bi_bdev = resume_bdev; + bio->bi_end_io = end_io; + + if (bio_add_page(bio, virt_to_page(page), PAGE_SIZE, 0) < PAGE_SIZE) { + printk("swsusp: ERROR: adding page to bio at %ld\n",page_off); + error = -EFAULT; + goto Done; + } + + if (rw == WRITE) + bio_set_pages_dirty(bio); + + atomic_set(&io_done, 1); + submit_bio(rw | (1 << BIO_RW_SYNC), bio); + while (atomic_read(&io_done)) + yield(); + + Done: + bio_put(bio); + return error; +} + +static int bio_read_page(pgoff_t page_off, void * page) +{ + return submit(READ, page_off, page); +} + +static int bio_write_page(pgoff_t page_off, void * page) +{ + return submit(WRITE, page_off, page); +} + +/** + * load_image - Load the image and metadata from swap, using the + * snapshot_recv_page() function provided by the snapshot-handling code + * + * We assume that the data has been saved using the swap map handling + * functions above + */ +static int load_image(unsigned nr_pages, swp_entry_t start) +{ + swp_map_t *swp; + void *buf; + unsigned n, k; + unsigned long offset = swp_offset(start); + int error; + unsigned mod = nr_pages / 100; + void *tfm; + + if (!nr_pages || !offset) + return -EINVAL; + + if ((error = crypto_init(0, &tfm))) + return error; + + buf = (void *)get_zeroed_page(GFP_ATOMIC); + if (!buf) { + error = -ENOMEM; + goto Crypto_exit; + } + swp = (swp_map_t *)get_zeroed_page(GFP_ATOMIC); + if (!swp) { + error = -ENOMEM; + goto Free_buf; + } + printk("Loading data from swap (%d pages) ... ", nr_pages); + n = 0; + while (n < nr_pages) { + if ((error = crypto_read(offset, (void *)swp, tfm))) + goto Free; + for (k = 0; k < MAP_PAGE_SIZE && n < nr_pages; k++, n++) { + error = bio_read_page(swp_offset(swp->entries[k]), buf); + if (!error) + error = snapshot_recv_page(buf); + if (error) + goto Free; + if (!(n % mod)) + printk("\b\b\b\b%3d%%", n / mod); + } + offset = swp_offset(swp->next_swp); + } + printk("\b\b\b\bdone\n"); +Free: + free_page((unsigned long)swp); +Free_buf: + free_page((unsigned long)buf); +Crypto_exit: + crypto_exit(tfm); + return error; +} + +/* + * Sanity check if this image makes sense with this kernel/swap context + * I really don't think that it's foolproof but more than nothing.. + */ + +static const char * sanity_check(void) +{ + dump_info(); + if (swsusp_info.version_code != LINUX_VERSION_CODE) + return "kernel version"; + if (swsusp_info.num_physpages != num_physpages) + return "memory size"; + if (strcmp(swsusp_info.uts.sysname,system_utsname.sysname)) + return "system type"; + if (strcmp(swsusp_info.uts.release,system_utsname.release)) + return "kernel release"; + if (strcmp(swsusp_info.uts.version,system_utsname.version)) + return "version"; + if (strcmp(swsusp_info.uts.machine,system_utsname.machine)) + return "machine"; +#if 0 + /* We can't use number of online CPUs when we use hotplug to remove them ;-))) */ + if (swsusp_info.cpus != num_possible_cpus()) + return "number of cpus"; +#endif + return NULL; +} + + +static int check_header(void) +{ + const char * reason = NULL; + int error; + + if ((error = bio_read_page(swp_offset(swsusp_header.swsusp_info), &swsusp_info))) + return error; + + /* Is this same machine? */ + if ((reason = sanity_check())) { + printk(KERN_ERR "swsusp: Resume mismatch: %s\n",reason); + return -EPERM; + } + return error; +} + +static int check_sig(void) +{ + int error; + + memset(&swsusp_header, 0, sizeof(swsusp_header)); + if ((error = bio_read_page(0, &swsusp_header))) + return error; + if (!memcmp(SWSUSP_SIG, swsusp_header.sig, 10)) { + memcpy(swsusp_header.sig, swsusp_header.orig_sig, 10); + memcpy(key_iv, swsusp_header.key_iv, MAXKEY+MAXIV); + memset(swsusp_header.key_iv, 0, MAXKEY+MAXIV); + + /* + * Reset swap signature now. + */ + error = bio_write_page(0, &swsusp_header); + } else { + return -EINVAL; + } + if (!error) + pr_debug("swsusp: Signature found, resuming\n"); + return error; +} + +static int check_suspend_image(void) +{ + int error = 0; + + if ((error = check_sig())) + return error; + + if ((error = check_header())) + return error; + + return 0; +} + +static int read_suspend_image(void) +{ + int error; + + error = snapshot_recv_init(swsusp_info.pages, swsusp_info.image_pages); + if (!error) + error = load_image(swsusp_info.pages, swsusp_info.start); + if (!error) + error = snapshot_finish(); + return error; +} + +/** + * swsusp_check - Check for saved image in swap + */ + +int swsusp_check(void) +{ + int error; + + resume_bdev = open_by_devnum(swsusp_resume_device, FMODE_READ); + if (!IS_ERR(resume_bdev)) { + set_blocksize(resume_bdev, PAGE_SIZE); + error = check_suspend_image(); + if (error) + blkdev_put(resume_bdev); + } else + error = PTR_ERR(resume_bdev); + + if (!error) + pr_debug("swsusp: resume file found\n"); + else + pr_debug("swsusp: Error %d check for resume file\n", error); + return error; +} + +/** + * swsusp_read - Read saved image from swap. + */ + +int swsusp_read(void) +{ + int error; + + if (IS_ERR(resume_bdev)) { + pr_debug("swsusp: block device not initialised\n"); + return PTR_ERR(resume_bdev); + } + + error = read_suspend_image(); + blkdev_put(resume_bdev); + memset(key_iv, 0, MAXKEY+MAXIV); + + if (!error) + pr_debug("swsusp: Reading resume file was successful\n"); + else + pr_debug("swsusp: Error %d resuming\n", error); + return error; +} + +/** + * swsusp_close - close swap device. + */ + +void swsusp_close(void) +{ + if (IS_ERR(resume_bdev)) { + pr_debug("swsusp: block device not initialised\n"); + return; + } + + blkdev_put(resume_bdev); +} + Index: linux-2.6.14-rc5-mm1/kernel/power/snapshot.c =================================================================== --- linux-2.6.14-rc5-mm1.orig/kernel/power/snapshot.c 2005-10-29 13:24:58.000000000 +0200 +++ linux-2.6.14-rc5-mm1/kernel/power/snapshot.c 2005-10-29 13:26:26.000000000 +0200 @@ -39,99 +39,6 @@ static unsigned nr_copy_pages; static unsigned nr_pb_pages; -#ifdef CONFIG_HIGHMEM -struct highmem_page { - char *data; - struct page *page; - struct highmem_page *next; -}; - -static struct highmem_page *highmem_copy; - -static int save_highmem_zone(struct zone *zone) -{ - unsigned long zone_pfn; - mark_free_pages(zone); - for (zone_pfn = 0; zone_pfn < zone->spanned_pages; ++zone_pfn) { - struct page *page; - struct highmem_page *save; - void *kaddr; - unsigned long pfn = zone_pfn + zone->zone_start_pfn; - - if (!(pfn%1000)) - printk("."); - if (!pfn_valid(pfn)) - continue; - page = pfn_to_page(pfn); - /* - * This condition results from rvmalloc() sans vmalloc_32() - * and architectural memory reservations. The memory needed is preallocated- * so that we know in advance if there's enough of it.- *- * The first swap_map_page structure is filled with the swap entries that- * correspond to the first MAP_PAGE_SIZE data pages written to swap and- * so on. Reply to: debian-user@lists.debian.org NN_il_Confusionario (on-list) NN_il_Confusionario (off-list) Follow-Ups: Re: HELP - Can't boot - I/O error reading swsusp.image From: "[email protected]" References: Re: HELP - Can't boot - I/O error reading swsusp.image From: "[email protected]" Prev by Date: Fwd: usb to serial Next by Date: Re: Clearing SWAP Previous by thread: Re: HELP - Can't boot - I/O error reading swsusp.image Next by thread: Re: HELP - Can't boot - I/O error reading swsusp.image Index(es): Date Thread [Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index] Re: HELP - Can't boot - I/O error reading swsusp.image To: [email protected] Subject: Re: HELP - Can't boot - I/O error reading swsusp.image From: "[email protected]" Date: Sun, 4 May 2008 13:16:42 -0400 Message-id: <[🔎][email protected]> Reply-to: [email protected] In-reply-to: <[🔎][email protected]> References: <[🔎][email protected]> <[🔎][email protected]> On 5/4/08, NN_il_Confusionario wrote: > On Sun, May 04, 2008 at 08:29:31AM -0400, [email protected] wrote: > > I did a fresh etch install, then restored some > > mondo backup files using mondorestore. > > I do not use mondo; so I ask: are you sure that mondorestore does not > change the partition table? Digli di smettere.Informatica=arsenico: minime dosi in rari casi patologici, altrimenti letale.Informatica=bomba: intelligente solo per gli stupidi che ci credono.

This is *necessary* for - * devfs, since the resume code can only recognize the form /dev/hda4, - * but the suspend code would see the long name.) - */ -static int is_resume_device(const struct swap_info_struct *swap_info) -{ - struct file *file = swap_info->swap_file; - struct inode *inode = file->f_dentry->d_inode; - - return S_ISBLK(inode->i_mode) && - swsusp_resume_device == MKDEV(imajor(inode), iminor(inode)); -} - -static int swsusp_swap_check(void) /* This is called before saving image */ -{ - int i, len; - - len=strlen(resume_file); - root_swap = 0xFFFF; - - spin_lock(&swap_lock); - for (i=0; iimage_pages;- error = load_image(&handle, &snapshot, nr_pages);- }- release_swap_map_reader(&handle);-- blkdev_put(resume_bdev);-- if (!error)- pr_debug("swsusp: Reading resume file was successful\n");- else- pr_debug("swsusp: Error %d resuming\n", error);- return error;-}--/**- * swsusp_check - Check for swsusp signature in the resume device- */--int swsusp_check(void)-{- int error;-- resume_bdev = open_by_devnum(swsusp_resume_device, FMODE_READ);- if (!IS_ERR(resume_bdev)) {- set_blocksize(resume_bdev, PAGE_SIZE);- memset(&swsusp_header, 0, sizeof(swsusp_header));- if ((error = bio_read_page(0, &swsusp_header)))- return error;- if (!memcmp(SWSUSP_SIG, swsusp_header.sig, 10)) {- memcpy(swsusp_header.sig, swsusp_header.orig_sig, 10);- /* Reset swap signature now */- error = bio_write_page(0, &swsusp_header);- } else {- return -EINVAL;- }- if (error)- blkdev_put(resume_bdev);- else- pr_debug("swsusp: Signature found, resuming\n");- } else {- error = PTR_ERR(resume_bdev);- }-- if (error)- pr_debug("swsusp: Error %d check for resume file\n", error);-- return error;-}--/**- * swsusp_close - close swap device.- */--void swsusp_close(void)-{- if (IS_ERR(resume_bdev)) {- pr_debug("swsusp: block device not initialised\n");- return;- }-- blkdev_put(resume_bdev);-}-To unsubscribe from this list: send the line "unsubscribe linux-kernel" inthe body of a message to majordomo@vger.kernel.orgMore majordomo info at http://vger.kernel.org/majordomo-info.htmlPlease read the FAQ at http://www.tux.org/lkml/        Last update: 2005-12-28 01:45    [W:0.095 / U:9.076 seconds]©2003-2016 Jasper Spaans. Bios+ * finish asynchronously, while we want them to happen synchronously.+ * A simple atomic_t, and a wait loop take care of this problem.+ */++static atomic_t io_done = ATOMIC_INIT(0);++static int end_io(struct bio *bio, unsigned int num, int err)+{+ if (!test_bit(BIO_UPTODATE, &bio->bi_flags))+ panic("I/O error reading memory image");+ atomic_set(&io_done, 0);+ return 0;+}++static struct block_device *resume_bdev;++/**+ * submit - submit BIO request.+ * @rw: READ or WRITE.+ * @off physical offset of page.+ * @page: page we're reading or writing.+ *+ * Straight from the textbook - allocate and initialize the bio.+ * If we're writing, make sure the page is marked as dirty.+ * Then submit it and wait.+ */++static int submit(int rw, pgoff_t page_off, void *page)+{+ int error = 0;+ struct bio *bio;++ bio = bio_alloc(GFP_ATOMIC, 1);+ if (!bio)+ return -ENOMEM;+ bio->bi_sector = page_off * (PAGE_SIZE >> 9);+ bio_get(bio);+ bio->bi_bdev = resume_bdev;+ bio->bi_end_io = end_io;++ if (bio_add_page(bio, virt_to_page(page), PAGE_SIZE, 0) < PAGE_SIZE) {+ printk("swsusp: ERROR: adding page to bio at %ld\n",page_off);+ error = -EFAULT;+ goto Done;+ }++ if (rw == WRITE)+ bio_set_pages_dirty(bio);++ atomic_set(&io_done, 1);+ submit_bio(rw | (1 << BIO_RW_SYNC), bio);+ while (atomic_read(&io_done))+ yield();++ Done:+ bio_put(bio);+ return error;+}++static int bio_read_page(pgoff_t page_off, void *page)+{+ return submit(READ, page_off, page);+}++static int bio_write_page(pgoff_t page_off, void *page)+{+ return submit(WRITE, page_off, page);+}++/**+ * The following functions allow us to read data using a swap map+ * in a file-alike way+ */++static inline void release_swap_map_reader(struct swap_map_handle *handle)+{+ if (handle->cur)+ free_page((unsigned long)handle->cur);+ handle->cur = NULL;+}++static inline int get_swap_map_reader(struct swap_map_handle *handle,+ swp_entry_t start)+{+ int error;++ if (!swp_offset(start))+ return -EINVAL;+ handle->cur = (struct swap_map_page *)get_zeroed_page(GFP_ATOMIC);+ if (!handle->cur)+ return -ENOMEM;+ error = bio_read_page(swp_offset(start), handle->cur);+ if (error) {+ release_swap_map_reader(handle);+ return error;+ }+ handle->k = 0;+ return 0;+}++static inline int swap_map_read_page(struct swap_map_handle *handle, void *buf)+{+ unsigned long offset;+ int error;++ if (!handle->cur)+ return -EINVAL;+ offset = swp_offset(handle->cur->entries[handle->k]);+ if (!offset)+ return -EFAULT;+ error = bio_read_page(offset, buf);+ if (error)+ return error;+ if (++handle->k >= MAP_PAGE_SIZE) {+ handle->k = 0;+ offset = swp_offset(handle->cur->next_swap);+ if (!offset)+ release_swap_map_reader(handle);+ else+ error = bio_read_page(offset, handle->cur);+ }+ return error;+}++/**+ * load_image - load the image using the swap map handle+ * @handle and the snapshot handle @snapshot+ * (assume there are @nr_pages pages to load)+ */++static int load_image(struct swap_map_handle *handle,+ struct snapshot_handle *snapshot,+ unsigned int nr_pages)+{+ unsigned int m;+ int ret;+ int error = 0;++ printk("Loading image data pages (%u pages) ... ", nr_pages);+ m = nr_pages / 100;+ if (!m)+ m = 1;+ nr_pages = 0;+ do {+ ret = snapshot_write_next(snapshot, PAGE_SIZE);+ if (ret > 0) {+ error = swap_map_read_page(handle, data_of(*snapshot));+ if (error)+ break;+ if (!(nr_pages % m))+ printk("\b\b\b\b%3d%%", nr_pages / m);+ nr_pages++;+ }+ } while (ret > 0);+ if (!error)+ printk("\b\b\b\bdone\n");+ if (!snapshot_image_ready(snapshot))+ error = -ENODATA;+ return error;+}++int swsusp_read(void)+{+ int error;+ struct swap_map_handle handle;+ struct snapshot_handle snapshot;+ struct swsusp_info *header;+ unsigned int nr_pages;++ if (IS_ERR(resume_bdev)) {+ pr_debug("swsusp: block device not initialised\n");+ return PTR_ERR(resume_bdev);+ }++ memset(&snapshot, 0, sizeof(struct snapshot_handle));+ error = snapshot_write_next(&snapshot, PAGE_SIZE);+ if (error < PAGE_SIZE)+ return error < 0 ?

This causes the data+ * pages to be loaded in exactly the same order in which they have been+ * saved.+ *+ * During resume we only need to use one swap_map_page structure+ * at a time, which means that we only need to use two memory pages for+ * reading the image - one for reading the swap_map_page structures+ * and the second for reading the data pages from swap.+ */++#define MAP_PAGE_SIZE ((PAGE_SIZE - sizeof(swp_entry_t) - sizeof(void *)) \+ / sizeof(swp_entry_t))++struct swap_map_page {+ swp_entry_t entries[MAP_PAGE_SIZE];+ swp_entry_t next_swap;+ struct swap_map_page *next;+};++static inline void free_swap_map(struct swap_map_page *swap_map)+{+ struct swap_map_page *swp;++ while (swap_map) {+ swp = swap_map->next;+ free_page((unsigned long)swap_map);+ swap_map = swp;+ }+}++static struct swap_map_page *alloc_swap_map(unsigned int nr_pages)+{+ struct swap_map_page *swap_map, *swp;+ unsigned n = 0;++ if (!nr_pages)+ return NULL;++ pr_debug("alloc_swap_map(): nr_pages = %d\n", nr_pages);+ swap_map = (struct swap_map_page *)get_zeroed_page(GFP_ATOMIC);+ swp = swap_map;+ for (n = MAP_PAGE_SIZE; n < nr_pages; n += MAP_PAGE_SIZE) {+ swp->next = (struct swap_map_page *)get_zeroed_page(GFP_ATOMIC);+ swp = swp->next;+ if (!swp) {+ free_swap_map(swap_map);+ return NULL;+ }+ }+ return swap_map;+}++/**+ * reverse_swap_map - reverse the order of pages in the swap map+ * @swap_map+ */++static inline struct swap_map_page *reverse_swap_map(struct swap_map_page *swap_map)+{+ struct swap_map_page *prev, *next;++ prev = NULL;+ while (swap_map) {+ next = swap_map->next;+ swap_map->next = prev;+ prev = swap_map;+ swap_map = next;+ }+ return prev;+}++/**+ * free_swap_map_entries - free the swap entries allocated to store+ * the swap map @swap_map (this is only called in case of an error)+ */+static inline void free_swap_map_entries(struct swap_map_page *swap_map)+{+ while (swap_map) {+ if (swap_map->next_swap.val)+ swap_free(swap_map->next_swap);+ swap_map = swap_map->next;+ }+}++/**+ * save_swap_map - save the swap map used for tracing the data pages+ * stored in the swap+ */++static int save_swap_map(struct swap_map_page *swap_map, swp_entry_t *start)+{+ swp_entry_t entry = (swp_entry_t){0};+ int error;++ while (swap_map) {+ swap_map->next_swap = entry;+ if ((error = write_page(swap_map, &entry)))+ return error;+ swap_map = swap_map->next;+ }+ *start = entry;+ return 0;+}++/**+ * free_image_entries - free the swap entries allocated to store+ * the image data pages (this is only called in case of an error)+ */++static inline void free_image_entries(struct swap_map_page *swp)+{+ unsigned k;++ while (swp) {+ for (k = 0; k < MAP_PAGE_SIZE; k++)+ if (swp->entries[k].val)+ swap_free(swp->entries[k]);+ swp = swp->next;+ }+}++/**+ * The swap_map_handle structure is used for handling the swap map in+ * a file-alike way+ */++struct swap_map_handle {+ struct swap_map_page *cur;+ unsigned int k;+};++static inline void init_swap_map_handle(struct swap_map_handle *handle,+ struct swap_map_page *map)+{+ handle->cur = map;+ handle->k = 0;+}++static inline int swap_map_write_page(struct swap_map_handle *handle, void *buf)+{+ int error;++ error = write_page(buf, handle->cur->entries + handle->k);+ if (error)+ return error;+ if (++handle->k >= MAP_PAGE_SIZE) {+ handle->cur = handle->cur->next;+ handle->k = 0;+ }+ return 0;+}++/**+ * save_image - save the suspend image data+ */++static int save_image(struct swap_map_handle *handle,+ struct snapshot_handle *snapshot,+ unsigned int nr_pages)+{+ unsigned int m;+ int ret;+ int error = 0;++ printk("Saving image data pages (%u pages) ... ", nr_pages);+ m = nr_pages / 100;+ if (!m)+ m = 1;+ nr_pages = 0;+ do {+ ret = snapshot_read_next(snapshot, PAGE_SIZE);+ if (ret > 0) {+ error = swap_map_write_page(handle, data_of(*snapshot));+ if (error)+ break;+ if (!(nr_pages % m))+ printk("\b\b\b\b%3d%%", nr_pages / m);+ nr_pages++;+ }+ } while (ret > 0);+ if (!error)+ printk("\b\b\b\bdone\n");+ return error;+}++/**+ * enough_swap - Make sure we have enough swap to save the image.+ *+ * Returns TRUE or FALSE after checking the total amount of swap+ * space avaiable from the resume partition.+ */++static int enough_swap(unsigned int nr_pages)+{+ unsigned int free_swap = swsusp_available_swap(root_swap);++ pr_debug("swsusp: free swap pages: %u\n", free_swap);+ return free_swap > (nr_pages + PAGES_FOR_IO ++ (nr_pages + PBES_PER_PAGE - 1) / PBES_PER_PAGE);+}++/**+ * swsusp_write - Write entire image and metadata.+ *+ * It is important _NOT_ to umount filesystems at this point. Thekernel sitll has in memory (and in /proc/partitions) the OLD startingand ending points of the partition, so mkswap, mkfs*, whatever still usethe "old geometry".Then you reboot, and at the reboot the kernel reads the new partitiontable ...This is a killer - I did a fresh etch install, then restored somemondo backup files using mondorestore. I should only have one ext3 and a swap partition, butthere is an additional partition that I don't understand at all.Anyway, I am starting over this time. http://debian-user.debian.narkive.com/WCfCTNV1/help-can-t-boot-i-o-error-reading-swsusp-image This causes the data - * pages to be loaded in exactly the same order in which they have been - * saved. - * - * During resume we only need to use one swp_map_page structure - * at a time, which means that we only need to use two memory pages for - * reading the image - one for reading the swp_map_page structures - * and the second for reading the data pages from swap. - */ - -#define MAP_PAGE_SIZE ((PAGE_SIZE - sizeof(swp_entry_t) - sizeof(void *)) \ - / sizeof(swp_entry_t)) - -struct swp_map_page { - swp_entry_t entries[MAP_PAGE_SIZE]; - swp_entry_t next_swp; - struct swp_map_page *next; +#ifdef CONFIG_HIGHMEM +struct highmem_page { + char *data; + struct page *page; + struct highmem_page *next; }; -typedef struct swp_map_page swp_map_t; - -static inline void free_swp_map(swp_map_t *swp_map) -{ - swp_map_t *swp; - - while (swp_map) { - swp = swp_map->next; - free_page((unsigned long)swp_map); - swp_map = swp; - } -} +static struct highmem_page *highmem_copy; -static swp_map_t *alloc_swp_map(unsigned nr_pages) +static int save_highmem_zone(struct zone *zone) { - swp_map_t *swp_map, *swp; - unsigned n = 0; - - if (!nr_pages) - return NULL; - - pr_debug("alloc_swp_map(): nr_pages = %d\n", nr_pages); - swp_map = (swp_map_t *)get_zeroed_page(GFP_ATOMIC); - swp = swp_map; - for (n = MAP_PAGE_SIZE; n < nr_pages; n += MAP_PAGE_SIZE) { - swp->next = (swp_map_t *)get_zeroed_page(GFP_ATOMIC); - swp = swp->next; - if (!swp) { - free_swp_map(swp_map); - return NULL; + unsigned long zone_pfn; + mark_free_pages(zone); + for (zone_pfn = 0; zone_pfn < zone->spanned_pages; ++zone_pfn) { + struct page *page; + struct highmem_page *save; + void *kaddr; + unsigned long pfn = zone_pfn + zone->zone_start_pfn; + + if (!(pfn%1000)) + printk("."); + if (!pfn_valid(pfn)) + continue; + page = pfn_to_page(pfn); + /* + * This condition results from rvmalloc() sans vmalloc_32() + * and architectural memory reservations.

It should NOT have been related to a file I restored anyway. Also, bootin single user mode or even with init=/bin/bash (and then "mount -oremount,rw /") and purge any package related to swsusp ("apt-cachesearch swsusp" gives me only the package uswsusp). It consists of many swap_map_page + * structures that contain each an array of MAP_PAGE_SIZE swap entries. + * These structures are stored on the swap and linked together with the + * help of the .next_swap member. + * + * The swap map is created during suspend. It did not - * check the return of rw_swap_page_sync() at all, since most pages - * written back to swap would return -EIO. - * This is a partial improvement, since we will at least return other - * errors, though we need to eventually fix the damn code. - */ -static int write_page(unsigned long addr, swp_entry_t * loc) -{ - swp_entry_t entry; - int error = 0; - - entry = get_swap_page(); - if (swp_offset(entry) && - swapfile_used[swp_type(entry)] == SWAPFILE_SUSPEND) { - error = rw_swap_page_sync(WRITE, entry, - virt_to_page(addr)); - if (error == -EIO) - error = 0; - if (!error) - *loc = entry; - } else - error = -ENOSPC; - return error; -} - -static void dump_info(void) -{ - pr_debug(" swsusp: Version: %u\n",swsusp_info.version_code); - pr_debug(" swsusp: Num Pages: %ld\n",swsusp_info.num_physpages); - pr_debug(" swsusp: UTS Sys: %s\n",swsusp_info.uts.sysname); - pr_debug(" swsusp: UTS Node: %s\n",swsusp_info.uts.nodename); - pr_debug(" swsusp: UTS Release: %s\n",swsusp_info.uts.release); - pr_debug(" swsusp: UTS Version: %s\n",swsusp_info.uts.version); - pr_debug(" swsusp: UTS Machine: %s\n",swsusp_info.uts.machine); - pr_debug(" swsusp: UTS Domain: %s\n",swsusp_info.uts.domainname); - pr_debug(" swsusp: CPUs: %d\n",swsusp_info.cpus); - pr_debug(" swsusp: Image: %ld Pages\n",swsusp_info.image_pages); - pr_debug(" swsusp: Total: %ld Pages\n", swsusp_info.pages); -} - -static void init_header(unsigned nr_pages, unsigned img_pages) -{ - memset(&swsusp_info, 0, sizeof(swsusp_info)); - swsusp_info.version_code = LINUX_VERSION_CODE; - swsusp_info.num_physpages = num_physpages; - memcpy(&swsusp_info.uts, &system_utsname, sizeof(system_utsname)); - - swsusp_info.cpus = num_online_cpus(); - swsusp_info.image_pages = img_pages; - swsusp_info.pages = nr_pages; -} - -static int close_swap(void) -{ - swp_entry_t entry; - int error; - - dump_info(); - error = write_page((unsigned long)&swsusp_info, &entry); - if (!error) { - printk( "S" ); - error = mark_swapfiles(entry); - printk( "|\n" ); - } - return error; -} - -/** - * Swap map handling functions - * - * The swap map is a data structure used for keeping track of each page - * written to the swap.

Note we discard -EIO + * errors. https://groups.google.com/d/topic/linux.debian.user/27Y1p_6566c Then again, I never need to suspend.Doug.Thanks. You can say /dev/hda4 - * instead of /dev/ide/host0/bus0/target0/lun0/part4 [eg. Willkommen!

We want + * them synced (in case something goes wrong) but we DO not want to mark + * filesystem clean: it is not. (And it does not matter, if we resume + * correctly, we'll mark system clean, anyway.) + */ +int swsusp_write(void) +{ + int error; + + if ((error = swsusp_swap_check())) { + printk(KERN_ERR "swsusp: cannot find swap device, try swapon -a.\n"); + return error; + } + lock_swapdevices(); + error = write_suspend_image(); + /* This will unlock ignored swap devices since writing is finished */ + lock_swapdevices(); + return error; +} + +/** + * Using bio to read from swap. + * This code requires a bit more work than just using buffer heads + * but, it is the recommended way for 2.5/2.6. + * The following are to signal the beginning and end of I/O. The partition table is definately messed up. for devfs] - * and they'll be considered the same device. As far as the files I restored and how they might relate toswsusp, I have no idea.

TuttyPost by w***@gmail.comHelp! Signed-off-by: Pavel Machek Signed-off-by: Rafael J. Signed-off-by: Rafael J. We want- * them synced (in case something goes wrong) but we DO not want to mark- * filesystem clean: it is not. (And it does not matter, if we resume- * correctly, we'll mark system clean, anyway.)- */--int swsusp_write(void)-{- struct swap_map_page *swap_map;- struct swap_map_handle handle;- struct snapshot_handle snapshot;- struct swsusp_info *header;- unsigned int nr_pages;- swp_entry_t start;- int error;-- if ((error = swsusp_swap_check())) {- printk(KERN_ERR "swsusp: Cannot find swap device, try swapon -a.\n");- return error;- }- memset(&snapshot, 0, sizeof(struct snapshot_handle));- error = snapshot_read_next(&snapshot, PAGE_SIZE);- if (error < PAGE_SIZE)- return error < 0 ?

Unfortunately, I don't know the key thing that happened. Wysocki + * + * This file is released under the GPLv2. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "power.h" + +extern char resume_file[]; + +#define SWSUSP_SIG "S1SUSPEND" + +static struct swsusp_header { + char reserved[PAGE_SIZE - 20 - sizeof(swp_entry_t)]; + swp_entry_t image; + char orig_sig[10]; + char sig[10]; +} __attribute__((packed, aligned(PAGE_SIZE))) swsusp_header; + +/* + * Saving part... + */ + +static unsigned short root_swap = 0xffff; + +/** + * mark_swapfiles - change the signature of the resume partition + * and store the swap address of given entry in the partition's + * header (the entry should point to the first image page in the + * swap) + */ + +static int mark_swapfiles(swp_entry_t start) +{ + int error; + + rw_swap_page_sync(READ, + swp_entry(root_swap, 0), + virt_to_page((unsigned long)&swsusp_header)); + if (!memcmp("SWAP-SPACE",swsusp_header.sig, 10) || + !memcmp("SWAPSPACE2",swsusp_header.sig, 10)) { + memcpy(swsusp_header.orig_sig,swsusp_header.sig, 10); + memcpy(swsusp_header.sig,SWSUSP_SIG, 10); + swsusp_header.image = start; + error = rw_swap_page_sync(WRITE, + swp_entry(root_swap, 0), + virt_to_page((unsigned long) + &swsusp_header)); + } else { + pr_debug("swsusp: Partition is not swap space.\n"); + error = -ENODEV; + } + return error; +} + +/** + * swsusp_swap_check - check if the resume partition is available + */ + +static int swsusp_swap_check(void) /* This is called before saving image */ +{ + int res = swsusp_get_swap_index(); + + if (res >= 0) { + root_swap = res; + return 0; + } + return res; +} + +/** + * write_page - Write one page to given swap location. + * @buf: Address we're writing. + * @offset: Offset of the swap page we're writing to. + */ + +static int write_page(void *buf, unsigned long offset) +{ + swp_entry_t entry; + int error = -ENOSPC; + + if (offset) { + entry = swp_entry(root_swap, offset); + error = rw_swap_page_sync(WRITE, entry, virt_to_page(buf)); + } + return error; +} + +/* + * The swap map is a data structure used for keeping track of each page + * written to a swap partition. That is an artifact left over from swsusp.

Wysocki + * + * This file is released under the GPLv2, and is based on swsusp.c. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "power.h" + +#define CIPHER "aes" +#define MAXKEY 32 +#define MAXIV 32 + +extern char resume_file[]; + + +#define SWSUSP_SIG "S1SUSPEND" + +static struct swsusp_header { + char reserved[PAGE_SIZE - 20 - MAXKEY - MAXIV - sizeof(swp_entry_t)]; + u8 key_iv[MAXKEY+MAXIV]; + swp_entry_t swsusp_info; + char orig_sig[10]; + char sig[10]; +} __attribute__((packed, aligned(PAGE_SIZE))) swsusp_header; + +static struct swsusp_info swsusp_info; + +/* + * Saving part... + */ + +/* We memorize in swapfile_used what swap devices are used for suspension */ +#define SWAPFILE_UNUSED 0 +#define SWAPFILE_SUSPEND 1 /* This is the suspending device */ +#define SWAPFILE_IGNORED 2 /* Those are other swap devices ignored for suspension */ + +static unsigned short swapfile_used[MAX_SWAPFILES]; +static unsigned short root_swap; + +static int write_page(unsigned long addr, swp_entry_t * loc); +static int bio_read_page(pgoff_t page_off, void * page); + +static u8 key_iv[MAXKEY+MAXIV]; + +#ifdef CONFIG_SWSUSP_ENCRYPT + +static int crypto_init(int mode, void **mem) +{ + int error = 0; + int len; + char *modemsg; + struct crypto_tfm *tfm; + + modemsg = mode ? "suspend not possible" : "resume not possible"; + + tfm = crypto_alloc_tfm(CIPHER, CRYPTO_TFM_MODE_CBC); + if(!tfm) { + printk(KERN_ERR "swsusp: no tfm, %s\n", modemsg); + error = -EINVAL; + goto out; + } + + if(MAXKEY < crypto_tfm_alg_min_keysize(tfm)) { + printk(KERN_ERR "swsusp: key buffer too small, %s\n", modemsg); + error = -ENOKEY; + goto fail; + } + + if (mode) + get_random_bytes(key_iv, MAXKEY+MAXIV); + + len = crypto_tfm_alg_max_keysize(tfm); + if (len > MAXKEY) + len = MAXKEY; + + if (crypto_cipher_setkey(tfm, key_iv, len)) { + printk(KERN_ERR "swsusp: key setup failure, %s\n", modemsg); + error = -EKEYREJECTED; + goto fail; + } + + len = crypto_tfm_alg_ivsize(tfm); + + if (MAXIV < len) { + printk(KERN_ERR "swsusp: iv buffer too small, %s\n", modemsg); + error = -EOVERFLOW; + goto fail; + } + + crypto_cipher_set_iv(tfm, key_iv+MAXKEY, len); + + *mem=(void *)tfm; + + goto out; + +fail: crypto_free_tfm(tfm); +out: return error; +} + +static __inline__ void crypto_exit(void *mem) +{ + crypto_free_tfm((struct crypto_tfm *)mem); +} + +static __inline__ int crypto_write(unsigned long addr, swp_entry_t *entry, void *mem) +{ + int error = 0; + struct scatterlist src, dst; + + src.page = virt_to_page((void *)addr); + src.offset = 0; + src.length = PAGE_SIZE; + dst.page = virt_to_page((void *)&swsusp_header); + dst.offset = 0; + dst.length = PAGE_SIZE; + + error = crypto_cipher_encrypt((struct crypto_tfm *)mem, &dst, &src, + PAGE_SIZE); + + if (!error) + error = write_page((unsigned long)&swsusp_header, entry); + return error; +} + +static __inline__ int crypto_read(unsigned long offset, void *buf, void *mem) +{ + int error = 0; + struct scatterlist src, dst; + + error = bio_read_page(offset, buf); + if (!error) { + src.offset = 0; + src.length = PAGE_SIZE; + dst.offset = 0; + dst.length = PAGE_SIZE; + src.page = dst.page = virt_to_page(buf); + + error = crypto_cipher_decrypt((struct crypto_tfm *)mem, &dst, + &src, PAGE_SIZE); + } + return error; +} +#else +static __inline__ int crypto_init(int mode, void *mem) +{ + return 0; +} + +static __inline__ void crypto_exit(void *mem) +{ +} + +static __inline__ int crypto_write(unsigned long addr, swp_entry_t *entry, void *mem) +{ + return write_page(addr, entry); +} + +static __inline__ int crypto_read(unsigned long offset, void *buf, void *mem) +{ + return bio_read_page(offset, buf); +} +#endif + +static int mark_swapfiles(swp_entry_t prev) +{ + int error; + + rw_swap_page_sync(READ, + swp_entry(root_swap, 0), + virt_to_page((unsigned long)&swsusp_header)); + if (!memcmp("SWAP-SPACE",swsusp_header.sig, 10) || + !memcmp("SWAPSPACE2",swsusp_header.sig, 10)) { + memcpy(swsusp_header.orig_sig,swsusp_header.sig, 10); + memcpy(swsusp_header.sig,SWSUSP_SIG, 10); + memcpy(swsusp_header.key_iv, key_iv, MAXKEY+MAXIV); + swsusp_header.swsusp_info = prev; + error = rw_swap_page_sync(WRITE, + swp_entry(root_swap, 0), + virt_to_page((unsigned long) + &swsusp_header)); + } else { + pr_debug("swsusp: Partition is not swap space.\n"); + error = -ENODEV; + } + return error; +} + +/* + * Check whether the swap device is the specified resume + * device, irrespective of whether they are specified by + * identical names. + * + * (Thus, device inode aliasing is allowed.

w***@gmail.com 2008-05-04 17:16:42 UTC PermalinkRaw Message Post by NN_il_ConfusionarioPost by w***@gmail.comI did a fresh etch install, then restored somemondo backup files using mondorestore.I do not use mondo; so I ask: are you sure that mondorestore does notchange the partition table? If all seems to fail,boot with a live cd (or the debian installation cd in rescue mode),mount your disk, chroot where the disc is mounted, purge uswsusp, editthe boot loader configuration (possibly menu.lst in /boot/grub/, but itdepends upon your boot loader), reinstall the kernel (to recreate theinitrd) and the boot loaderThere is absolutely NO need to reinstall once again (unless you haveseverely messed up your partition table and filesysetems, or things likethat).--Chi usa software non libero avvelena anche te. Tutty 2008-05-04 01:41:10 UTC PermalinkRaw Message Post by w***@gmail.comHelp! If there issomething related to resuming a suspended session, delete it.

Tutty 7. 2008-05-03 HELP - Can't boot - I/O error reading swsusp.image debian-us wa9als Configure | About | News | Addalist | SponsoredbyKoreLogic [linux-pm] [RFC][PATCH 5/6] swsusp: move swap-handling functions to separate file Rafael J. Bios - * finish asynchronously, while we want them to happen synchronously. - * A simple atomic_t, and a wait loop take care of this problem. - */ - -static atomic_t io_done = ATOMIC_INIT(0); - -static int end_io(struct bio * bio, unsigned int num, int err) -{ - if (!test_bit(BIO_UPTODATE, &bio->bi_flags)) - panic("I/O error reading memory image"); - atomic_set(&io_done, 0); - return 0; -} - -static struct block_device * resume_bdev; - -/** - * submit - submit BIO request. - * @rw: READ or WRITE. - * @off physical offset of page. - * @page: page we're reading or writing. - * - * Straight from the textbook - allocate and initialize the bio. - * If we're writing, make sure the page is marked as dirty. - * Then submit it and wait. - */ - -static int submit(int rw, pgoff_t page_off, void * page) -{ - int error = 0; - struct bio * bio; - - bio = bio_alloc(GFP_ATOMIC, 1); - if (!bio) - return -ENOMEM; - bio->bi_sector = page_off * (PAGE_SIZE >> 9); - bio_get(bio); - bio->bi_bdev = resume_bdev; - bio->bi_end_io = end_io; - - if (bio_add_page(bio, virt_to_page(page), PAGE_SIZE, 0) < PAGE_SIZE) { - printk("swsusp: ERROR: adding page to bio at %ld\n",page_off); - error = -EFAULT; - goto Done; - } - - if (rw == WRITE) - bio_set_pages_dirty(bio); - - atomic_set(&io_done, 1); - submit_bio(rw | (1 << BIO_RW_SYNC), bio); - while (atomic_read(&io_done)) - yield(); - - Done: - bio_put(bio); - return error; -} - -static int bio_read_page(pgoff_t page_off, void * page) -{ - return submit(READ, page_off, page); -} - -static int bio_write_page(pgoff_t page_off, void * page) -{ - return submit(WRITE, page_off, page); -} - -/** - * load_image - Load the image and metadata from swap, using the - * snapshot_recv_page() function provided by the snapshot-handling code - * - * We assume that the data has been saved using the swap map handling - * functions above - */ -static int load_image(unsigned nr_pages, swp_entry_t start) -{ - swp_map_t *swp; - void *buf; - unsigned n, k; - unsigned long offset = swp_offset(start); - int error; - unsigned mod = nr_pages / 100; - void *tfm; - - if (!nr_pages || !offset) - return -EINVAL; - - if ((error = crypto_init(0, &tfm))) - return error; - - buf = (void *)get_zeroed_page(GFP_ATOMIC); - if (!buf) { - error = -ENOMEM; - goto Crypto_exit; - } - swp = (swp_map_t *)get_zeroed_page(GFP_ATOMIC); - if (!swp) { - error = -ENOMEM; - goto Free_buf; - } - printk("Loading data from swap (%d pages) ... ", nr_pages); - n = 0; - while (n < nr_pages) { - if ((error = crypto_read(offset, (void *)swp, tfm))) - goto Free; - for (k = 0; k < MAP_PAGE_SIZE && n < nr_pages; k++, n++) { - error = bio_read_page(swp_offset(swp->entries[k]), buf); - if (!error) - error = snapshot_recv_page(buf); - if (error) - goto Free; - if (!(n % mod)) - printk("\b\b\b\b%3d%%", n / mod); - } - offset = swp_offset(swp->next_swp); - } - printk("\b\b\b\bdone\n"); -Free: - free_page((unsigned long)swp); -Free_buf: - free_page((unsigned long)buf); -Crypto_exit: - crypto_exit(tfm); - return error; -} - -/* - * Sanity check if this image makes sense with this kernel/swap context - * I really don't think that it's foolproof but more than nothing.. - */ - -static const char * sanity_check(void) -{ - dump_info(); - if (swsusp_info.version_code != LINUX_VERSION_CODE) - return "kernel version"; - if (swsusp_info.num_physpages != num_physpages) - return "memory size"; - if (strcmp(swsusp_info.uts.sysname,system_utsname.sysname)) - return "system type"; - if (strcmp(swsusp_info.uts.release,system_utsname.release)) - return "kernel release"; - if (strcmp(swsusp_info.uts.version,system_utsname.version)) - return "version"; - if (strcmp(swsusp_info.uts.machine,system_utsname.machine)) - return "machine"; -#if 0 - /* We can't use number of online CPUs when we use hotplug to remove them ;-))) */ - if (swsusp_info.cpus != num_possible_cpus()) - return "number of cpus"; -#endif - return NULL; -} - - -static int check_header(void) -{ - const char * reason = NULL; - int error; - - if ((error = bio_read_page(swp_offset(swsusp_header.swsusp_info), &swsusp_info))) - return error; - - /* Is this same machine? */ - if ((reason = sanity_check())) { - printk(KERN_ERR "swsusp: Resume mismatch: %s\n",reason); - return -EPERM; - } - return error; -} - -static int check_sig(void) -{ - int error; - - memset(&swsusp_header, 0, sizeof(swsusp_header)); - if ((error = bio_read_page(0, &swsusp_header))) - return error; - if (!memcmp(SWSUSP_SIG, swsusp_header.sig, 10)) { - memcpy(swsusp_header.sig, swsusp_header.orig_sig, 10); - memcpy(key_iv, swsusp_header.key_iv, MAXKEY+MAXIV); - memset(swsusp_header.key_iv, 0, MAXKEY+MAXIV); - - /* - * Reset swap signature now. - */ - error = bio_write_page(0, &swsusp_header); - } else { - return -EINVAL; - } - if (!error) - pr_debug("swsusp: Signature found, resuming\n"); - return error; -} - -static int check_suspend_image(void) -{ - int error = 0; - - if ((error = check_sig())) - return error; - - if ((error = check_header())) - return error; - - return 0; -} - -static int read_suspend_image(void) -{ - int error; - - error = snapshot_recv_init(swsusp_info.pages, swsusp_info.image_pages); - if (!error) - error = load_image(swsusp_info.pages, swsusp_info.start); - if (!error) - error = snapshot_finish(); - return error; -} - -/** - * swsusp_check - Check for saved image in swap - */ - -int swsusp_check(void) -{ - int error; - - resume_bdev = open_by_devnum(swsusp_resume_device, FMODE_READ); - if (!IS_ERR(resume_bdev)) { - set_blocksize(resume_bdev, PAGE_SIZE); - error = check_suspend_image(); - if (error) - blkdev_put(resume_bdev); - } else - error = PTR_ERR(resume_bdev); - - if (!error) - pr_debug("swsusp: resume file found\n"); - else - pr_debug("swsusp: Error %d check for resume file\n", error); - return error; -} - -/** - * swsusp_read - Read saved image from swap. - */ - -int swsusp_read(void) -{ - int error; - - if (IS_ERR(resume_bdev)) { - pr_debug("swsusp: block device not initialised\n"); - return PTR_ERR(resume_bdev); - } - - error = read_suspend_image(); - blkdev_put(resume_bdev); - memset(key_iv, 0, MAXKEY+MAXIV); - - if (!error) - pr_debug("swsusp: Reading resume file was successful\n"); - else - pr_debug("swsusp: Error %d resuming\n", error); - return error; -} - -/** - * swsusp_close - close swap device. - */ - -void swsusp_close(void) -{ - if (IS_ERR(resume_bdev)) { - pr_debug("swsusp: block device not initialised\n"); - return; - } - - blkdev_put(resume_bdev); -} Previous message: [linux-pm] Re: [RFC][PATCH 4/6] swsusp: move swap check out of swsusp_suspend Next message: [linux-pm] Re: [RFC][PATCH 5/6] swsusp: move swap-handling functions to separate file Messages sorted by: [ date ] [ thread ] [ subject ] [ author ] More information about the linux-pm mailing list zur Navigation debianforum.de die deutschsprachige Supportwebseite rund um das Debian-Projekt Zum Inhalt Foren-Übersicht Information Das von dir ausgewählte Thema existiert nicht. You can say /dev/hda4 - * instead of /dev/ide/host0/bus0/target0/lun0/part4 [if using devfs] - * and they'll be considered the same device. It did not + * check the return of rw_swap_page_sync() at all, since most pages + * written back to swap would return -EIO. + * This is a partial improvement, since we will at least return other + * errors, though we need to eventually fix the damn code. + */ +static int write_page(unsigned long addr, swp_entry_t * loc) +{ + swp_entry_t entry; + int error = 0; + + entry = get_swap_page(); + if (swp_offset(entry) && + swapfile_used[swp_type(entry)] == SWAPFILE_SUSPEND) { + error = rw_swap_page_sync(WRITE, entry, + virt_to_page(addr)); + if (error == -EIO) + error = 0; + if (!error) + *loc = entry; + } else + error = -ENOSPC; + return error; +} + +static void dump_info(void) +{ + pr_debug(" swsusp: Version: %u\n",swsusp_info.version_code); + pr_debug(" swsusp: Num Pages: %ld\n",swsusp_info.num_physpages); + pr_debug(" swsusp: UTS Sys: %s\n",swsusp_info.uts.sysname); + pr_debug(" swsusp: UTS Node: %s\n",swsusp_info.uts.nodename); + pr_debug(" swsusp: UTS Release: %s\n",swsusp_info.uts.release); + pr_debug(" swsusp: UTS Version: %s\n",swsusp_info.uts.version); + pr_debug(" swsusp: UTS Machine: %s\n",swsusp_info.uts.machine); + pr_debug(" swsusp: UTS Domain: %s\n",swsusp_info.uts.domainname); + pr_debug(" swsusp: CPUs: %d\n",swsusp_info.cpus); + pr_debug(" swsusp: Image: %ld Pages\n",swsusp_info.image_pages); + pr_debug(" swsusp: Total: %ld Pages\n", swsusp_info.pages); +} + +static void init_header(unsigned nr_pages, unsigned img_pages) +{ + memset(&swsusp_info, 0, sizeof(swsusp_info)); + swsusp_info.version_code = LINUX_VERSION_CODE; + swsusp_info.num_physpages = num_physpages; + memcpy(&swsusp_info.uts, &system_utsname, sizeof(system_utsname)); + + swsusp_info.cpus = num_online_cpus(); + swsusp_info.image_pages = img_pages; + swsusp_info.pages = nr_pages; +} + +static int close_swap(void) +{ + swp_entry_t entry; + int error; + + dump_info(); + error = write_page((unsigned long)&swsusp_info, &entry); + if (!error) { + printk( "S" ); + error = mark_swapfiles(entry); + printk( "|\n" ); + } + return error; +} + +/** + * Swap map handling functions + * + * The swap map is a data structure used for keeping track of each page + * written to the swap.

error : -EFAULT; + header = (struct swsusp_info *)data_of(snapshot); + error = get_swap_reader(&handle, swsusp_header.image); + if (!error) + error = swap_read_page(&handle, header); + if (!error) { + nr_pages = header->image_pages; + error = load_image(&handle, &snapshot, nr_pages); + } + release_swap_reader(&handle); + + blkdev_put(resume_bdev); + + if (!error) + pr_debug("swsusp: Reading resume file was successful\n"); + else + pr_debug("swsusp: Error %d resuming\n", error); + return error; +} + +/** + * swsusp_check - Check for swsusp signature in the resume device + */ + +int swsusp_check(void) +{ + int error; + + resume_bdev = open_by_devnum(swsusp_resume_device, FMODE_READ); + if (!IS_ERR(resume_bdev)) { + set_blocksize(resume_bdev, PAGE_SIZE); + memset(&swsusp_header, 0, sizeof(swsusp_header)); + if ((error = bio_read_page(0, &swsusp_header))) + return error; + if (!memcmp(SWSUSP_SIG, swsusp_header.sig, 10)) { + memcpy(swsusp_header.sig, swsusp_header.orig_sig, 10); + /* Reset swap signature now */ + error = bio_write_page(0, &swsusp_header); + } else { + return -EINVAL; + } + if (error) + blkdev_put(resume_bdev); + else + pr_debug("swsusp: Signature found, resuming\n"); + } else { + error = PTR_ERR(resume_bdev); + } + + if (error) + pr_debug("swsusp: Error %d check for resume file\n", error); + + return error; +} + +/** + * swsusp_close - close swap device. + */ + +void swsusp_close(void) +{ + if (IS_ERR(resume_bdev)) { + pr_debug("swsusp: block device not initialised\n"); + return; + } + + blkdev_put(resume_bdev); +} Index: linux-2.6.15-mm1/kernel/power/swsusp.c =================================================================== --- linux-2.6.15-mm1.orig/kernel/power/swsusp.c 2006-01-06 23:24:18.000000000 +0100 +++ linux-2.6.15-mm1/kernel/power/swsusp.c 2006-01-06 23:27:19.000000000 +0100 @@ -31,41 +31,24 @@ * Fixed runaway init * * Rafael J. Beiträge aktive Themen Zum Seitenanfang Diese Webseite ist keine offizielle Webseite des Debian Projekts. The memory needed is preallocated+ * so that we know in advance if there's enough of it.+ *+ * The first swap_map_page structure is filled with the swap entries that+ * correspond to the first MAP_PAGE_SIZE data pages written to swap and+ * so on. Anyway, I am starting over this time.

error : -EFAULT;+ header = (struct swsusp_info *)data_of(snapshot);+ nr_pages = header->image_pages;+ if (!enough_swap(nr_pages)) {+ printk(KERN_ERR "swsusp: Not enough free swap\n");+ return -ENOSPC;+ }+ swap_map = alloc_swap_map(header->pages);+ if (!swap_map)+ return -ENOMEM;+ init_swap_map_handle(&handle, swap_map);++ error = swap_map_write_page(&handle, header);+ if (!error)+ error = save_image(&handle, &snapshot, nr_pages);+ if (error)+ goto Free_image_entries;++ swap_map = reverse_swap_map(swap_map);+ error = save_swap_map(swap_map, &start);+ if (error)+ goto Free_map_entries;++ printk( "S" );+ error = mark_swapfiles(start);+ printk( "|\n" );+ if (error)+ goto Free_map_entries;++Free_swap_map:+ free_swap_map(swap_map);+ return error;++Free_map_entries:+ free_swap_map_entries(swap_map);+Free_image_entries:+ free_image_entries(swap_map);+ goto Free_swap_map;+}++/*+ * Using bio to read from swap.+ * This code requires a bit more work than just using buffer heads+ * but, it is the recommended way for 2.5/2.6.+ * The following are to signal the beginning and end of I/O. I rebooted my Etch server (was not having problems prior), and it stops early with: Begin: Running /scripts/local-premount . . . Wysocki - * Added the swap map data structure and reworked the handling of swap + * Reworked the handling of swap and added the user interface * * More state savers are welcome. but do not OOM-kill anyone @@ -654,254 +361,3 @@ int swsusp_resume(void) local_irq_enable(); return error; } - -/* - * Using bio to read from swap. - * This code requires a bit more work than just using buffer heads - * but, it is the recommended way for 2.5/2.6. - * The following are to signal the beginning and end of I/O.

Tutty Re: HELP - Can't boot - I/O error reading sws... [EMAIL PROTECTED] Re: HELP - Can't boot - I/O error reading swsusp.... It consists of many swap_map_page structures- * that contain each an array of MAP_PAGE_SIZE swap entries.- * These structures are linked together with the help of either the- * .next (in memory) or the .next_swap (in swap) member.- *- * The swap map is created during suspend. error : -EFAULT; - header = (struct swsusp_info *)data_of(snapshot); - if (!enough_swap(header->pages)) { - printk(KERN_ERR "swsusp: Not enough free swap\n"); - return -ENOSPC; - } - error = get_swap_writer(&handle); - if (!error) { - start = handle.cur_swap; - error = swap_write_page(&handle, header); - } - if (!error) - error = save_image(&handle, &snapshot, header->pages - 1); - if (!error) { - flush_swap_writer(&handle); - printk("S"); - error = mark_swapfiles(swp_entry(root_swap, start)); - printk("|\n"); - } - if (error) - free_all_swap_pages(root_swap, handle.bitmap); - release_swap_writer(&handle); - return error; -} - -/** * swsusp_shrink_memory - Try to free as much memory as needed * * ... for devfs] + * and they'll be considered the same device.

Wysocki + *+ * This file is released under the GPLv2.+ *+ */++#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include ++#include "power.h"++extern int swsusp_get_swap_index(void);+extern unsigned int swsusp_available_swap(unsigned int swap);++extern char resume_file[];++#define SWSUSP_SIG "S1SUSPEND"++static struct swsusp_header {+ char reserved[PAGE_SIZE - 20 - sizeof(swp_entry_t)];+ swp_entry_t image;+ char orig_sig[10];+ char sig[10];+} __attribute__((packed, aligned(PAGE_SIZE))) swsusp_header;++/*+ * Saving part...+ */++static unsigned short root_swap = 0xffff;++static int mark_swapfiles(swp_entry_t start)+{+ int error;++ rw_swap_page_sync(READ,+ swp_entry(root_swap, 0),+ virt_to_page((unsigned long)&swsusp_header));+ if (!memcmp("SWAP-SPACE",swsusp_header.sig, 10) ||+ !memcmp("SWAPSPACE2",swsusp_header.sig, 10)) {+ memcpy(swsusp_header.orig_sig,swsusp_header.sig, 10);+ memcpy(swsusp_header.sig,SWSUSP_SIG, 10);+ swsusp_header.image = start;+ error = rw_swap_page_sync(WRITE,+ swp_entry(root_swap, 0),+ virt_to_page((unsigned long)+ &swsusp_header));+ } else {+ pr_debug("swsusp: Partition is not swap space.\n");+ error = -ENODEV;+ }+ return error;+}++static int swsusp_swap_check(void) /* This is called before saving image */+{+ int res = swsusp_get_swap_index();++ if (res >= 0) {+ root_swap = res;+ return 0;+ }+ return res;+}++/**+ * write_page - Write one page to a fresh swap location.+ * @buf: Address we're writing.+ * @loc: Place to store the entry we used.+ */++static int write_page(void *buf, swp_entry_t *loc)+{+ swp_entry_t entry;+ int error = -ENOSPC;++ entry = get_swap_page_of_type(root_swap);+ if (swp_offset(entry)) {+ error = rw_swap_page_sync(WRITE, entry, virt_to_page(buf));+ if (!error)+ *loc = entry;+ else+ swap_free(entry);+ }+ return error;+}++/**+ * Swap map-handling functions+ *+ * The swap map is a data structure used for keeping track of each page+ * written to the swap. This should be - * corrected eventually when the cases giving rise to this - * are better understood. - */ - if (PageReserved(page)) { - printk("highmem reserved page?!\n"); - continue; - } - BUG_ON(PageNosave(page)); - if (PageNosaveFree(page)) - continue; - save = kmalloc(sizeof(struct highmem_page), GFP_ATOMIC); - if (!save) - return -ENOMEM; - save->next = highmem_copy; - save->page = page; - save->data = (void *) get_zeroed_page(GFP_ATOMIC); - if (!save->data) { - kfree(save); - return -ENOMEM; - } - kaddr = kmap_atomic(page, KM_USER0); - memcpy(save->data, kaddr, PAGE_SIZE); - kunmap_atomic(kaddr, KM_USER0); - highmem_copy = save; - } - return 0; -} - - -int save_highmem(void) -{ - struct zone *zone; - int res = 0; - - pr_debug("swsusp: Saving Highmem\n"); - for_each_zone (zone) { - if (is_highmem(zone)) - res = save_highmem_zone(zone); - if (res) - return res; - } - return 0; -} - -int restore_highmem(void) -{ - printk("swsusp: Restoring Highmem\n"); - while (highmem_copy) { - struct highmem_page *save = highmem_copy; - void *kaddr; - highmem_copy = save->next; - - kaddr = kmap_atomic(save->page, KM_USER0); - memcpy(kaddr, save->data, PAGE_SIZE); - kunmap_atomic(kaddr, KM_USER0); - free_page((long) save->data); - kfree(save); - } - return 0; -} -#else -int save_highmem(void) { return 0; } -int restore_highmem(void) { return 0; } -#endif /* CONFIG_HIGHMEM */ - - static int pfn_is_nosave(unsigned long pfn) { unsigned long nosave_begin_pfn = __pa(&__nosave_begin) >> PAGE_SHIFT; Index: linux-2.6.14-rc5-mm1/kernel/power/swsusp.c =================================================================== --- linux-2.6.14-rc5-mm1.orig/kernel/power/swsusp.c 2005-10-29 13:25:41.000000000 +0200 +++ linux-2.6.14-rc5-mm1/kernel/power/swsusp.c 2005-10-29 13:26:26.000000000 +0200 @@ -76,586 +76,96 @@ #include "power.h" -#define CIPHER "aes" -#define MAXKEY 32 -#define MAXIV 32 - -extern char resume_file[]; - - -#define SWSUSP_SIG "S1SUSPEND" - -static struct swsusp_header { - char reserved[PAGE_SIZE - 20 - MAXKEY - MAXIV - sizeof(swp_entry_t)]; - u8 key_iv[MAXKEY+MAXIV]; - swp_entry_t swsusp_info; - char orig_sig[10]; - char sig[10]; -} __attribute__((packed, aligned(PAGE_SIZE))) swsusp_header; - -static struct swsusp_info swsusp_info; - -/* - * Saving part... - */ - -/* We memorize in swapfile_used what swap devices are used for suspension */ -#define SWAPFILE_UNUSED 0 -#define SWAPFILE_SUSPEND 1 /* This is the suspending device */ -#define SWAPFILE_IGNORED 2 /* Those are other swap devices ignored for suspension */ - -static unsigned short swapfile_used[MAX_SWAPFILES]; -static unsigned short root_swap; - -static int write_page(unsigned long addr, swp_entry_t * loc); -static int bio_read_page(pgoff_t page_off, void * page); - -static u8 key_iv[MAXKEY+MAXIV]; - -#ifdef CONFIG_SWSUSP_ENCRYPT - -static int crypto_init(int mode, void **mem) -{ - int error = 0; - int len; - char *modemsg; - struct crypto_tfm *tfm; - - modemsg = mode ? "suspend not possible" : "resume not possible"; - - tfm = crypto_alloc_tfm(CIPHER, CRYPTO_TFM_MODE_CBC); - if(!tfm) { - printk(KERN_ERR "swsusp: no tfm, %s\n", modemsg); - error = -EINVAL; - goto out; - } - - if(MAXKEY < crypto_tfm_alg_min_keysize(tfm)) { - printk(KERN_ERR "swsusp: key buffer too small, %s\n", modemsg); - error = -ENOKEY; - goto fail; - } - - if (mode) - get_random_bytes(key_iv, MAXKEY+MAXIV); - - len = crypto_tfm_alg_max_keysize(tfm); - if (len > MAXKEY) - len = MAXKEY; - - if (crypto_cipher_setkey(tfm, key_iv, len)) { - printk(KERN_ERR "swsusp: key setup failure, %s\n", modemsg); - error = -EKEYREJECTED; - goto fail; - } - - len = crypto_tfm_alg_ivsize(tfm); - - if (MAXIV < len) { - printk(KERN_ERR "swsusp: iv buffer too small, %s\n", modemsg); - error = -EOVERFLOW; - goto fail; - } - - crypto_cipher_set_iv(tfm, key_iv+MAXKEY, len); - - *mem=(void *)tfm; - - goto out; - -fail: crypto_free_tfm(tfm); -out: return error; -} - -static __inline__ void crypto_exit(void *mem) -{ - crypto_free_tfm((struct crypto_tfm *)mem); -} - -static __inline__ int crypto_write(unsigned long addr, swp_entry_t *entry, void *mem) -{ - int error = 0; - struct scatterlist src, dst; - - src.page = virt_to_page((void *)addr); - src.offset = 0; - src.length = PAGE_SIZE; - dst.page = virt_to_page((void *)&swsusp_header); - dst.offset = 0; - dst.length = PAGE_SIZE; - - error = crypto_cipher_encrypt((struct crypto_tfm *)mem, &dst, &src, - PAGE_SIZE); - - if (!error) - error = write_page((unsigned long)&swsusp_header, entry); - return error; -} - -static __inline__ int crypto_read(unsigned long offset, void *buf, void *mem) -{ - int error = 0; - struct scatterlist src, dst; - - error = bio_read_page(offset, buf); - if (!error) { - src.offset = 0; - src.length = PAGE_SIZE; - dst.offset = 0; - dst.length = PAGE_SIZE; - src.page = dst.page = virt_to_page(buf); - - error = crypto_cipher_decrypt((struct crypto_tfm *)mem, &dst, - &src, PAGE_SIZE); - } - return error; -} -#else -static __inline__ int crypto_init(int mode, void *mem) -{ - return 0; -} - -static __inline__ void crypto_exit(void *mem) -{ -} - -static __inline__ int crypto_write(unsigned long addr, swp_entry_t *entry, void *mem) -{ - return write_page(addr, entry); -} - -static __inline__ int crypto_read(unsigned long offset, void *buf, void *mem) -{ - return bio_read_page(offset, buf); -} -#endif - -static int mark_swapfiles(swp_entry_t prev) -{ - int error; - - rw_swap_page_sync(READ, - swp_entry(root_swap, 0), - virt_to_page((unsigned long)&swsusp_header)); - if (!memcmp("SWAP-SPACE",swsusp_header.sig, 10) || - !memcmp("SWAPSPACE2",swsusp_header.sig, 10)) { - memcpy(swsusp_header.orig_sig,swsusp_header.sig, 10); - memcpy(swsusp_header.sig,SWSUSP_SIG, 10); - memcpy(swsusp_header.key_iv, key_iv, MAXKEY+MAXIV); - swsusp_header.swsusp_info = prev; - error = rw_swap_page_sync(WRITE, - swp_entry(root_swap, 0), - virt_to_page((unsigned long) - &swsusp_header)); - } else { - pr_debug("swsusp: Partition is not swap space.\n"); - error = -ENODEV; - } - return error; -} - -/* - * Check whether the swap device is the specified resume - * device, irrespective of whether they are specified by - * identical names. - * - * (Thus, device inode aliasing is allowed.