All of lore.kernel.org
 help / color / mirror / Atom feed
From: Nigel Cunningham <nigel@tuxonice.net>
To: Bojan Smojver <bojan@rexursive.com>
Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>,
	linux-kernel@vger.kernel.org
Subject: Re: [PATCH]: Compress hibernation image with LZO (in-kernel)
Date: Wed, 04 Aug 2010 12:42:56 +1000	[thread overview]
Message-ID: <4C58D3B0.10602@tuxonice.net> (raw)
In-Reply-To: <1280802642.2627.2.camel@shrek.rexursive.com>

Hi again.

On 03/08/10 12:30, Bojan Smojver wrote:
> On Tue, 2010-08-03 at 11:59 +1000, Bojan Smojver wrote:
>> PS. I also enhanced the patch to use overlapping compression in order
>> to save memory. Looks like that's causing it to be slower on
>> compression (we go down from 130 - 150 MB/s to around 105 - 110 MB/s),
>> but still over 3 times faster than regular swsusp code. Decompression
>> remains roughly the same around 100+ MB/s (this is double the speed of
>> current swsusp code). I will post this a bit later on.
>
> As promised.

Round here, people generally like to see improvements split up into 
small patches that change just one thing. I'd therefore suggest 
splitting the removal of sync_read from the rest of the patch. Is it 
standalone? I'm not seeing the relationship between the two parts at the 
moment.

> diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
> index ca6066a..cb57eb9 100644
> --- a/kernel/power/Kconfig
> +++ b/kernel/power/Kconfig
> @@ -137,6 +137,8 @@ config SUSPEND_FREEZER
>   config HIBERNATION
>   	bool "Hibernation (aka 'suspend to disk')"
>   	depends on PM&&  SWAP&&  ARCH_HIBERNATION_POSSIBLE
> +	select LZO_COMPRESS
> +	select LZO_DECOMPRESS
>   	select SUSPEND_NVS if HAS_IOMEM
>   	---help---
>   	  Enable the suspend to disk (STD) functionality, which is usually
> diff --git a/kernel/power/power.h b/kernel/power/power.h
> index 006270f..a760cf8 100644
> --- a/kernel/power/power.h
> +++ b/kernel/power/power.h
> @@ -103,10 +103,6 @@ struct snapshot_handle {
>   	void		*buffer;	/* address of the block to read from
>   					 * or write to
>   					 */
> -	int		sync_read;	/* Set to one to notify the caller of
> -					 * snapshot_write_next() that it may
> -					 * need to call wait_on_bio_chain()
> -					 */
>   };
>
>   /* This macro returns the address from/to which the caller of
> diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c
> index 25ce010..f24ee24 100644
> --- a/kernel/power/snapshot.c
> +++ b/kernel/power/snapshot.c
> @@ -2135,8 +2135,6 @@ int snapshot_write_next(struct snapshot_handle *handle)
>   	if (handle->cur>  1&&  handle->cur>  nr_meta_pages + nr_copy_pages)
>   		return 0;
>
> -	handle->sync_read = 1;
> -
>   	if (!handle->cur) {
>   		if (!buffer)
>   			/* This makes the buffer be freed by swsusp_free() */
> @@ -2169,7 +2167,6 @@ int snapshot_write_next(struct snapshot_handle *handle)
>   			memory_bm_position_reset(&orig_bm);
>   			restore_pblist = NULL;
>   			handle->buffer = get_buffer(&orig_bm,&ca);
> -			handle->sync_read = 0;
>   			if (IS_ERR(handle->buffer))
>   				return PTR_ERR(handle->buffer);
>   		}
> @@ -2178,8 +2175,6 @@ int snapshot_write_next(struct snapshot_handle *handle)
>   		handle->buffer = get_buffer(&orig_bm,&ca);
>   		if (IS_ERR(handle->buffer))
>   			return PTR_ERR(handle->buffer);
> -		if (handle->buffer != buffer)
> -			handle->sync_read = 0;
>   	}
>   	handle->cur++;
>   	return PAGE_SIZE;
> diff --git a/kernel/power/swap.c b/kernel/power/swap.c
> index b0bb217..5a83fd3 100644
> --- a/kernel/power/swap.c
> +++ b/kernel/power/swap.c
> @@ -24,6 +24,7 @@
>   #include<linux/swapops.h>
>   #include<linux/pm.h>
>   #include<linux/slab.h>
> +#include<linux/lzo.h>
>
>   #include "power.h"
>
> @@ -357,6 +358,18 @@ static int swap_writer_finish(struct swap_map_handle *handle,
>   	return error;
>   }
>
> +#define LZO_HEADER	sizeof(size_t)
> +#define LZO_UNC_PAGES	64
> +#define LZO_UNC_SIZE	(LZO_UNC_PAGES * PAGE_SIZE)
> +#define LZO_CMP_PAGES	DIV_ROUND_UP(lzo1x_worst_compress(LZO_UNC_SIZE) + \
> +			             LZO_HEADER, PAGE_SIZE)
> +#define LZO_CMP_SIZE	(LZO_CMP_PAGES * PAGE_SIZE)
> +#define LZO_OVH_PAGES	DIV_ROUND_UP((LZO_UNC_SIZE > 0xBFFF ? \
> +			              0xBFFF : LZO_UNC_SIZE) + \
> +			             LZO_UNC_SIZE / 16 + 64 + 3 + \
> +			             LZO_HEADER, PAGE_SIZE)
> +#define LZO_OVH_SIZE	(LZO_OVH_PAGES + PAGE_SIZE)
> +

Some commenting for these #defines would be good, especially the 'magic' 
numbers 0xBFF, 16, 64 and 3. It's all a bit unreadable, too :) Maybe 
something like (untested...):

#define LZO_HEADER	sizeof(size_t)
#define LZO_UNC_PAGES	64
#define LZO_UNC_SIZE	(LZO_UNC_PAGES * PAGE_SIZE)
#define LZO_CMP_PAGES	\
   DIV_ROUND_UP(lzo1x_worst_compress(LZO_UNC_SIZE) + LZO_HEADER,
		PAGE_SIZE)
#define LZO_CMP_SIZE	(LZO_CMP_PAGES * PAGE_SIZE)
#define LZO_MAGIC_1 0xBFFF /* Rename to whatever this is */
#define LZO_MAGIC_2 16 /* Rename */
#define LZO_MAGIC_3 (64 + 3) /* Rename */
#define LZO_OVH_PAGES
   DIV_ROUND_UP(min(LZO_UNC_SIZE, LZO_MAGIC_1) + \
		LZO_UNC_SIZE / LZO_MAGIC2 + \
		LZO_MAGIC_3 + \
		LZO_HEADER,
		PAGE_SIZE)
#define LZO_OVH_SIZE	(LZO_OVH_PAGES + PAGE_SIZE)


>   /**
>    *	save_image - save the suspend image data
>    */
> @@ -372,6 +385,29 @@ static int save_image(struct swap_map_handle *handle,
>   	struct bio *bio;
>   	struct timeval start;
>   	struct timeval stop;
> +	size_t ul, cl;

rename to bytes_in and bytes_out? I can guess they mean 
uncompressed/compressed length, but it's a little cryptic.

> +	unsigned char *buf, *wrk, *page;
> +
> +	page = (void *)__get_free_page(__GFP_WAIT | __GFP_HIGH);
> +	if (!page) {
> +		printk(KERN_ERR "PM: Failed to allocate LZO page\n");
> +		return -ENOMEM;
> +	}
> +
> +	wrk = vmalloc(LZO1X_1_MEM_COMPRESS);
> +	if (!wrk) {
> +		printk(KERN_ERR "PM: Failed to allocate LZO workspace\n");
> +		free_page((unsigned long)page);
> +		return -ENOMEM;
> +	}
> +
> +	buf = vmalloc(LZO_UNC_SIZE + LZO_OVH_SIZE);
> +	if (!buf) {
> +		printk(KERN_ERR "PM: Failed to allocate LZO buffer\n");
> +		vfree(wrk);
> +		free_page((unsigned long)page);
> +		return -ENOMEM;
> +	}
>
>   	printk(KERN_INFO "PM: Saving image data pages (%u pages) ...     ",
>   		nr_to_write);
> @@ -382,16 +418,50 @@ static int save_image(struct swap_map_handle *handle,
>   	bio = NULL;
>   	do_gettimeofday(&start);
>   	while (1) {
> -		ret = snapshot_read_next(snapshot);
> -		if (ret<= 0)
> +		for (ul = 0; ul<  LZO_UNC_SIZE; ul += PAGE_SIZE) {
> +			ret = snapshot_read_next(snapshot);
> +			if (ret<  0)

Not sure why my email client (Thunderbird) is shifting your comparison 
operators :(

> +				goto out_finish;
> +
> +			if (ret == 0)

if (!ret)

(Further down, too)

> +				break;
> +
> +			memcpy(buf + LZO_OVH_SIZE + ul,
> +			       data_of(*snapshot), PAGE_SIZE);
> +
> +			if (!(nr_pages % m))
> +				printk(KERN_CONT "\b\b\b\b%3d%%", nr_pages / m);
> +			nr_pages++;
> +		}
> +
> +		if (ul == 0)
> +			break;
> +
> +		ret = lzo1x_1_compress(buf + LZO_OVH_SIZE, ul,
> +		                       buf + LZO_HEADER,&cl, wrk);
> +		if (ret<  0) {
> +			printk(KERN_ERR "PM: LZO compression failed\n");
>   			break;
> -		ret = swap_write_page(handle, data_of(*snapshot),&bio);
> -		if (ret)
> +		}
> +
> +		if (unlikely(cl == 0 || LZO_HEADER + cl>  LZO_CMP_SIZE)) {
> +			printk(KERN_ERR "PM: Invalid LZO length\n");
> +			ret = -1;
>   			break;
> -		if (!(nr_pages % m))
> -			printk(KERN_CONT "\b\b\b\b%3d%%", nr_pages / m);
> -		nr_pages++;
> +		}
> +
> +		*(size_t *)buf = cl;
> +
> +		for (ul = 0; ul<  LZO_HEADER + cl; ul += PAGE_SIZE) {
> +			memcpy(page, buf + ul, PAGE_SIZE);
> +
> +			ret = swap_write_page(handle, page,&bio);
> +			if (ret)
> +				goto out_finish;
> +		}
>   	}
> +
> +out_finish:
>   	err2 = hib_wait_on_bio_chain(&bio);
>   	do_gettimeofday(&stop);
>   	if (!ret)
> @@ -401,6 +471,11 @@ static int save_image(struct swap_map_handle *handle,
>   	else
>   		printk(KERN_CONT "\n");
>   	swsusp_show_speed(&start,&stop, nr_to_write, "Wrote");
> +
> +	vfree(buf);
> +	vfree(wrk);
> +	free_page((unsigned long)page);
> +
>   	return ret;
>   }
>
> @@ -416,7 +491,8 @@ static int enough_swap(unsigned int nr_pages)
>   	unsigned int free_swap = count_swap_pages(root_swap, 1);
>
>   	pr_debug("PM: Free swap pages: %u\n", free_swap);
> -	return free_swap>  nr_pages + PAGES_FOR_IO;
> +	return free_swap>
> +	       (nr_pages * LZO_CMP_PAGES) / LZO_UNC_PAGES + 1 + PAGES_FOR_IO;

PAGES_FOR_IO doesn't belong here, but that's not your problem :)

>   }
>
>   /**
> @@ -547,9 +623,22 @@ static int load_image(struct swap_map_handle *handle,
>   	int error = 0;
>   	struct timeval start;
>   	struct timeval stop;
> -	struct bio *bio;
> -	int err2;
>   	unsigned nr_pages;
> +	size_t ul, cl, off;

As per comments on ul and cl above.

[...]

Regards,

Nigel


  reply	other threads:[~2010-08-04  2:43 UTC|newest]

Thread overview: 38+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-07-30  4:46 [PATCH]: Compress hibernation image with LZO (in-kernel) Bojan Smojver
2010-07-30 10:44 ` Bojan Smojver
2010-07-30 22:05   ` Nigel Cunningham
2010-07-30 22:19     ` Bojan Smojver
2010-07-30 23:22     ` Bojan Smojver
2010-07-30 23:40       ` Nigel Cunningham
2010-07-31  1:03         ` Bojan Smojver
2010-07-31  1:18           ` Nigel Cunningham
2010-07-31  1:33             ` Bojan Smojver
2010-07-31  4:41               ` Bojan Smojver
2010-07-31  5:03                 ` Bojan Smojver
2010-08-02  0:17                 ` KAMEZAWA Hiroyuki
2010-08-02  0:54                   ` Bojan Smojver
2010-08-02  1:10                     ` KAMEZAWA Hiroyuki
2010-08-02  1:21                       ` Bojan Smojver
2010-08-02  1:27                         ` KAMEZAWA Hiroyuki
2010-08-02  1:43                           ` Bojan Smojver
2010-08-03  1:59                             ` Bojan Smojver
2010-08-03  2:30                               ` Bojan Smojver
2010-08-04  2:42                                 ` Nigel Cunningham [this message]
2010-08-04  2:47                                   ` Bojan Smojver
2010-08-04  4:04                                     ` Bojan Smojver
2010-08-04  4:23                                       ` Nigel Cunningham
2010-08-04  5:12                                         ` Bojan Smojver
2010-08-04  5:58                                           ` Bojan Smojver
2010-08-05  1:26                                     ` Bojan Smojver
2010-08-03  6:34                               ` Bojan Smojver
2010-08-04  1:50                               ` Nigel Cunningham
2010-08-04  1:58                                 ` Bojan Smojver
2010-08-04  2:02                                 ` KAMEZAWA Hiroyuki
2010-08-04  2:14                                   ` Bojan Smojver
2010-08-04  2:18                                     ` KAMEZAWA Hiroyuki
2010-08-04  2:37                                       ` Nigel Cunningham
2010-08-04  2:24                                   ` Nigel Cunningham
2010-08-04  2:24                                     ` KAMEZAWA Hiroyuki
2010-08-04  2:38                                       ` Nigel Cunningham
2010-08-05  6:26 ` Pavel Machek
2010-08-05  6:55   ` Bojan Smojver

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4C58D3B0.10602@tuxonice.net \
    --to=nigel@tuxonice.net \
    --cc=bojan@rexursive.com \
    --cc=kamezawa.hiroyu@jp.fujitsu.com \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.