Re: [PATCH]: Use async I/O when reading compressed hibernation image

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxx>
>   * Copyright (C) 2006 Rafael J. Wysocki <rjw@xxxxxxx>
> + * Copyright (C) 2010 Bojan Smojver <bojan@xxxxxxxxxxxxx>
>   *
>   * 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;
>  }
> 
> 
> 

_______________________________________________
linux-pm mailing list
linux-pm@xxxxxxxxxxxxxxxxxxxxxxxxxx
https://lists.linux-foundation.org/mailman/listinfo/linux-pm


[Index of Archives]     [Linux ACPI]     [Netdev]     [Ethernet Bridging]     [Linux Wireless]     [CPU Freq]     [Kernel Newbies]     [Fedora Kernel]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux