All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH]: Use async I/O when reading compressed hibernation image
@ 2010-11-22  2:03 Bojan Smojver
  2010-11-26 22:03 ` Rafael J. Wysocki
  0 siblings, 1 reply; 3+ messages in thread
From: Bojan Smojver @ 2010-11-22  2:03 UTC (permalink / raw)
  To: Linux-pm mailing list

Hi Rafael,

This is a fix for reading LZO compressed image using async I/O.
Essentially, instead of having just one page into which we keep reading
blocks from swap, we allocate enough of them to cover the largest
compressed size and then let block I/O pick them all up. Once we have
them all (and here we wait), we decompress them, as usual. Obviously,
the very first block we still pick up synchronously, because we need to
know the size of the lot before we pick up the rest.

I guess this can go in 2.6.37 (actually, this is how I _should_ have
done that patch in the first place), because it is essentially a
performance fix.

Also fixed the copyright line, which I've forgotten before.

 kernel/power/swap.c |   53
++++++++++++++++++++++++++++++++++++--------------
 1 files changed, 38 insertions(+), 15 deletions(-)

diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index a0e4a86..baf667b 100644
--- a/kernel/power/swap.c
+++ b/kernel/power/swap.c
@@ -6,6 +6,7 @@
  *
  * Copyright (C) 1998,2001-2005 Pavel Machek <pavel@ucw.cz>
  * Copyright (C) 2006 Rafael J. Wysocki <rjw@sisk.pl>
+ * Copyright (C) 2010 Bojan Smojver <bojan@rexursive.com>
  *
  * This file is released under the GPLv2.
  *
@@ -753,30 +754,43 @@ static int load_image_lzo(struct swap_map_handle
*handle,
 {
 	unsigned int m;
 	int error = 0;
+	struct bio *bio;
 	struct timeval start;
 	struct timeval stop;
 	unsigned nr_pages;
-	size_t off, unc_len, cmp_len;
-	unsigned char *unc, *cmp, *page;
+	size_t i, off, unc_len, cmp_len;
+	unsigned char *unc, *cmp, *page[LZO_CMP_PAGES];
 
-	page = (void *)__get_free_page(__GFP_WAIT | __GFP_HIGH);
-	if (!page) {
-		printk(KERN_ERR "PM: Failed to allocate LZO page\n");
-		return -ENOMEM;
+	for (i = 0; i < LZO_CMP_PAGES; i++) {
+		page[i] = (void *)__get_free_page(__GFP_WAIT | __GFP_HIGH);
+		if (!page[i]) {
+			printk(KERN_ERR "PM: Failed to allocate LZO page\n");
+
+			while (i)
+				free_page((unsigned long)page[--i]);
+
+			return -ENOMEM;
+		}
 	}
 
 	unc = vmalloc(LZO_UNC_SIZE);
 	if (!unc) {
 		printk(KERN_ERR "PM: Failed to allocate LZO uncompressed\n");
-		free_page((unsigned long)page);
+
+		for (i = 0; i < LZO_CMP_PAGES; i++)
+			free_page((unsigned long)page[i]);
+
 		return -ENOMEM;
 	}
 
 	cmp = vmalloc(LZO_CMP_SIZE);
 	if (!cmp) {
 		printk(KERN_ERR "PM: Failed to allocate LZO compressed\n");
+
 		vfree(unc);
-		free_page((unsigned long)page);
+		for (i = 0; i < LZO_CMP_PAGES; i++)
+			free_page((unsigned long)page[i]);
+
 		return -ENOMEM;
 	}
 
@@ -787,6 +801,7 @@ static int load_image_lzo(struct swap_map_handle
*handle,
 	if (!m)
 		m = 1;
 	nr_pages = 0;
+	bio = NULL;
 	do_gettimeofday(&start);
 
 	error = snapshot_write_next(snapshot);
@@ -794,11 +809,11 @@ static int load_image_lzo(struct swap_map_handle
*handle,
 		goto out_finish;
 
 	for (;;) {
-		error = swap_read_page(handle, page, NULL); /* sync */
+		error = swap_read_page(handle, page[0], NULL); /* sync */
 		if (error)
 			break;
 
-		cmp_len = *(size_t *)page;
+		cmp_len = *(size_t *)page[0];
 		if (unlikely(!cmp_len ||
 		             cmp_len > lzo1x_worst_compress(LZO_UNC_SIZE))) {
 			printk(KERN_ERR "PM: Invalid LZO compressed length\n");
@@ -806,13 +821,20 @@ static int load_image_lzo(struct swap_map_handle
*handle,
 			break;
 		}
 
-		memcpy(cmp, page, PAGE_SIZE);
-		for (off = PAGE_SIZE; off < LZO_HEADER + cmp_len; off += PAGE_SIZE) {
-			error = swap_read_page(handle, page, NULL); /* sync */
+		for (off = PAGE_SIZE, i = 1;
+		     off < LZO_HEADER + cmp_len; off += PAGE_SIZE, i++) {
+			error = swap_read_page(handle, page[i], &bio);
 			if (error)
 				goto out_finish;
+		}
 
-			memcpy(cmp + off, page, PAGE_SIZE);
+		error = hib_wait_on_bio_chain(&bio); /* need all data now */
+		if (error)
+			goto out_finish;
+
+		for (off = 0, i = 0;
+		     off < LZO_HEADER + cmp_len; off += PAGE_SIZE, i++) {
+			memcpy(cmp + off, page[i], PAGE_SIZE);
 		}
 
 		unc_len = LZO_UNC_SIZE;
@@ -857,7 +879,8 @@ out_finish:
 
 	vfree(cmp);
 	vfree(unc);
-	free_page((unsigned long)page);
+	for (i = 0; i < LZO_CMP_PAGES; i++)
+		free_page((unsigned long)page[i]);
 
 	return error;
 }


-- 
Bojan

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

* Re: [PATCH]: Use async I/O when reading compressed hibernation image
  2010-11-22  2:03 [PATCH]: Use async I/O when reading compressed hibernation image Bojan Smojver
@ 2010-11-26 22:03 ` Rafael J. Wysocki
  2010-11-27  3:03   ` Bojan Smojver
  0 siblings, 1 reply; 3+ messages in thread
From: Rafael J. Wysocki @ 2010-11-26 22:03 UTC (permalink / raw)
  To: Bojan Smojver; +Cc: linux-pm

On Monday, November 22, 2010, Bojan Smojver wrote:
> Hi Rafael,
> 
> This is a fix for reading LZO compressed image using async I/O.
> Essentially, instead of having just one page into which we keep reading
> blocks from swap, we allocate enough of them to cover the largest
> compressed size and then let block I/O pick them all up. Once we have
> them all (and here we wait), we decompress them, as usual. Obviously,
> the very first block we still pick up synchronously, because we need to
> know the size of the lot before we pick up the rest.
> 
> I guess this can go in 2.6.37 (actually, this is how I _should_ have
> done that patch in the first place), because it is essentially a
> performance fix.
> 
> Also fixed the copyright line, which I've forgotten before.

Applied to suspend-2.6/linux-next.

Thanks,
Rafael


>  kernel/power/swap.c |   53
> ++++++++++++++++++++++++++++++++++++--------------
>  1 files changed, 38 insertions(+), 15 deletions(-)
> 
> diff --git a/kernel/power/swap.c b/kernel/power/swap.c
> index a0e4a86..baf667b 100644
> --- a/kernel/power/swap.c
> +++ b/kernel/power/swap.c
> @@ -6,6 +6,7 @@
>   *
>   * Copyright (C) 1998,2001-2005 Pavel Machek <pavel@ucw.cz>
>   * Copyright (C) 2006 Rafael J. Wysocki <rjw@sisk.pl>
> + * Copyright (C) 2010 Bojan Smojver <bojan@rexursive.com>
>   *
>   * This file is released under the GPLv2.
>   *
> @@ -753,30 +754,43 @@ static int load_image_lzo(struct swap_map_handle
> *handle,
>  {
>  	unsigned int m;
>  	int error = 0;
> +	struct bio *bio;
>  	struct timeval start;
>  	struct timeval stop;
>  	unsigned nr_pages;
> -	size_t off, unc_len, cmp_len;
> -	unsigned char *unc, *cmp, *page;
> +	size_t i, off, unc_len, cmp_len;
> +	unsigned char *unc, *cmp, *page[LZO_CMP_PAGES];
>  
> -	page = (void *)__get_free_page(__GFP_WAIT | __GFP_HIGH);
> -	if (!page) {
> -		printk(KERN_ERR "PM: Failed to allocate LZO page\n");
> -		return -ENOMEM;
> +	for (i = 0; i < LZO_CMP_PAGES; i++) {
> +		page[i] = (void *)__get_free_page(__GFP_WAIT | __GFP_HIGH);
> +		if (!page[i]) {
> +			printk(KERN_ERR "PM: Failed to allocate LZO page\n");
> +
> +			while (i)
> +				free_page((unsigned long)page[--i]);
> +
> +			return -ENOMEM;
> +		}
>  	}
>  
>  	unc = vmalloc(LZO_UNC_SIZE);
>  	if (!unc) {
>  		printk(KERN_ERR "PM: Failed to allocate LZO uncompressed\n");
> -		free_page((unsigned long)page);
> +
> +		for (i = 0; i < LZO_CMP_PAGES; i++)
> +			free_page((unsigned long)page[i]);
> +
>  		return -ENOMEM;
>  	}
>  
>  	cmp = vmalloc(LZO_CMP_SIZE);
>  	if (!cmp) {
>  		printk(KERN_ERR "PM: Failed to allocate LZO compressed\n");
> +
>  		vfree(unc);
> -		free_page((unsigned long)page);
> +		for (i = 0; i < LZO_CMP_PAGES; i++)
> +			free_page((unsigned long)page[i]);
> +
>  		return -ENOMEM;
>  	}
>  
> @@ -787,6 +801,7 @@ static int load_image_lzo(struct swap_map_handle
> *handle,
>  	if (!m)
>  		m = 1;
>  	nr_pages = 0;
> +	bio = NULL;
>  	do_gettimeofday(&start);
>  
>  	error = snapshot_write_next(snapshot);
> @@ -794,11 +809,11 @@ static int load_image_lzo(struct swap_map_handle
> *handle,
>  		goto out_finish;
>  
>  	for (;;) {
> -		error = swap_read_page(handle, page, NULL); /* sync */
> +		error = swap_read_page(handle, page[0], NULL); /* sync */
>  		if (error)
>  			break;
>  
> -		cmp_len = *(size_t *)page;
> +		cmp_len = *(size_t *)page[0];
>  		if (unlikely(!cmp_len ||
>  		             cmp_len > lzo1x_worst_compress(LZO_UNC_SIZE))) {
>  			printk(KERN_ERR "PM: Invalid LZO compressed length\n");
> @@ -806,13 +821,20 @@ static int load_image_lzo(struct swap_map_handle
> *handle,
>  			break;
>  		}
>  
> -		memcpy(cmp, page, PAGE_SIZE);
> -		for (off = PAGE_SIZE; off < LZO_HEADER + cmp_len; off += PAGE_SIZE) {
> -			error = swap_read_page(handle, page, NULL); /* sync */
> +		for (off = PAGE_SIZE, i = 1;
> +		     off < LZO_HEADER + cmp_len; off += PAGE_SIZE, i++) {
> +			error = swap_read_page(handle, page[i], &bio);
>  			if (error)
>  				goto out_finish;
> +		}
>  
> -			memcpy(cmp + off, page, PAGE_SIZE);
> +		error = hib_wait_on_bio_chain(&bio); /* need all data now */
> +		if (error)
> +			goto out_finish;
> +
> +		for (off = 0, i = 0;
> +		     off < LZO_HEADER + cmp_len; off += PAGE_SIZE, i++) {
> +			memcpy(cmp + off, page[i], PAGE_SIZE);
>  		}
>  
>  		unc_len = LZO_UNC_SIZE;
> @@ -857,7 +879,8 @@ out_finish:
>  
>  	vfree(cmp);
>  	vfree(unc);
> -	free_page((unsigned long)page);
> +	for (i = 0; i < LZO_CMP_PAGES; i++)
> +		free_page((unsigned long)page[i]);
>  
>  	return error;
>  }
> 
> 
> 

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

* Re: [PATCH]: Use async I/O when reading compressed hibernation image
  2010-11-26 22:03 ` Rafael J. Wysocki
@ 2010-11-27  3:03   ` Bojan Smojver
  0 siblings, 0 replies; 3+ messages in thread
From: Bojan Smojver @ 2010-11-27  3:03 UTC (permalink / raw)
  To: Rafael J. Wysocki; +Cc: linux-pm

On Fri, 2010-11-26 at 23:03 +0100, Rafael J. Wysocki wrote:
> Applied to suspend-2.6/linux-next.

Thank you.

-- 
Bojan

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

end of thread, other threads:[~2010-11-27  3:03 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-11-22  2:03 [PATCH]: Use async I/O when reading compressed hibernation image Bojan Smojver
2010-11-26 22:03 ` Rafael J. Wysocki
2010-11-27  3:03   ` Bojan Smojver

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.