All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH 0/3] add LZ4 compression support
@ 2014-01-17 11:04 Sergey Senozhatsky
  2014-01-17 11:04 ` [RFC PATCH 1/3] zram: delete zram_init_device() function Sergey Senozhatsky
                   ` (2 more replies)
  0 siblings, 3 replies; 11+ messages in thread
From: Sergey Senozhatsky @ 2014-01-17 11:04 UTC (permalink / raw)
  To: Minchan Kim
  Cc: Jerome Marchand, Nitin Gupta, linux-kernel, Sergey Senozhatsky

This patchset introduces support for LZ4 compression
(along with LZO) and adds functionality to list and change
compression algorithms, using new `compressor' device attribute.

Sergey Senozhatsky (3):
  zram: delete zram_init_device() function
  zram: introduce zram compressor operations struct
  zram: list and select compression algorithms

 Documentation/blockdev/zram.txt | 23 +++++++++---
 drivers/block/zram/Kconfig      |  2 +
 drivers/block/zram/zram_drv.c   | 83 +++++++++++++++++++++++++++++------------
 drivers/block/zram/zram_drv.h   | 10 +++++
 4 files changed, 89 insertions(+), 29 deletions(-)

-- 
1.8.5.3.493.gb139ac2


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

* [RFC PATCH 1/3] zram: delete zram_init_device() function
  2014-01-17 11:04 [RFC PATCH 0/3] add LZ4 compression support Sergey Senozhatsky
@ 2014-01-17 11:04 ` Sergey Senozhatsky
  2014-01-20  4:43   ` Minchan Kim
  2014-01-17 11:04 ` [RFC PATCH 2/3] zram: introduce zram compressor operations struct Sergey Senozhatsky
  2014-01-17 11:04 ` [RFC PATCH 3/3] zram: list and select compression algorithms Sergey Senozhatsky
  2 siblings, 1 reply; 11+ messages in thread
From: Sergey Senozhatsky @ 2014-01-17 11:04 UTC (permalink / raw)
  To: Minchan Kim
  Cc: Jerome Marchand, Nitin Gupta, linux-kernel, Sergey Senozhatsky

allocate new `zram_meta' in disksize_store() only for uninitialised
zram device, saving a number of allocations and deallocations in case
if disksize_store() was called on currently used device. at the same
time zram_meta stack variable is not necessary, because we can set
->meta directly. there is also no need in setting QUEUE_FLAG_NONROT
queue on every disksize_store(), set it once during device creation.

Signed-off-by: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
---
 drivers/block/zram/zram_drv.c | 19 +++++--------------
 1 file changed, 5 insertions(+), 14 deletions(-)

diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
index 5ec61be..7124042 100644
--- a/drivers/block/zram/zram_drv.c
+++ b/drivers/block/zram/zram_drv.c
@@ -533,38 +533,28 @@ static void zram_reset_device(struct zram *zram, bool reset_capacity)
 	up_write(&zram->init_lock);
 }
 
-static void zram_init_device(struct zram *zram, struct zram_meta *meta)
-{
-	/* zram devices sort of resembles non-rotational disks */
-	queue_flag_set_unlocked(QUEUE_FLAG_NONROT, zram->disk->queue);
-	zram->meta = meta;
-	pr_debug("Initialization done!\n");
-}
-
 static ssize_t disksize_store(struct device *dev,
 		struct device_attribute *attr, const char *buf, size_t len)
 {
 	u64 disksize;
-	struct zram_meta *meta;
 	struct zram *zram = dev_to_zram(dev);
 
 	disksize = memparse(buf, NULL);
 	if (!disksize)
 		return -EINVAL;
 
-	disksize = PAGE_ALIGN(disksize);
-	meta = zram_meta_alloc(disksize);
 	down_write(&zram->init_lock);
 	if (init_done(zram)) {
 		up_write(&zram->init_lock);
-		zram_meta_free(meta);
 		pr_info("Cannot change disksize for initialized device\n");
 		return -EBUSY;
 	}
 
+	disksize = PAGE_ALIGN(disksize);
+	zram->meta = zram_meta_alloc(disksize);
+
 	zram->disksize = disksize;
 	set_capacity(zram->disk, zram->disksize >> SECTOR_SHIFT);
-	zram_init_device(zram, meta);
 	up_write(&zram->init_lock);
 
 	return len;
@@ -774,7 +764,8 @@ static int create_device(struct zram *zram, int device_id)
 
 	/* Actual capacity set using syfs (/sys/block/zram<id>/disksize */
 	set_capacity(zram->disk, 0);
-
+	/* zram devices sort of resembles non-rotational disks */
+	queue_flag_set_unlocked(QUEUE_FLAG_NONROT, zram->disk->queue);
 	/*
 	 * To ensure that we always get PAGE_SIZE aligned
 	 * and n*PAGE_SIZED sized I/O requests.
-- 
1.8.5.3.493.gb139ac2


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

* [RFC PATCH 2/3] zram: introduce zram compressor operations struct
  2014-01-17 11:04 [RFC PATCH 0/3] add LZ4 compression support Sergey Senozhatsky
  2014-01-17 11:04 ` [RFC PATCH 1/3] zram: delete zram_init_device() function Sergey Senozhatsky
@ 2014-01-17 11:04 ` Sergey Senozhatsky
  2014-01-20  5:12   ` Minchan Kim
  2014-01-17 11:04 ` [RFC PATCH 3/3] zram: list and select compression algorithms Sergey Senozhatsky
  2 siblings, 1 reply; 11+ messages in thread
From: Sergey Senozhatsky @ 2014-01-17 11:04 UTC (permalink / raw)
  To: Minchan Kim
  Cc: Jerome Marchand, Nitin Gupta, linux-kernel, Sergey Senozhatsky

This is preparation patch to add LZ4 compression support.

struct zram_compress_ops defines common compress and decompress
prototypes. Use these ops->compress and ops->decompress callbacks
instead of direct LZO lzo1x_1_compress() and lzo1x_decompress_safe()
calls.

Compressor ops should be defined before zram meta allocation,
because the size of meta->compress_workmem depends on selected
compression algorithm.

Define LZO compressor ops and set it as the only one available
zram compressor at the moment.

Signed-off-by: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
---
 drivers/block/zram/zram_drv.c | 20 +++++++++++++-------
 drivers/block/zram/zram_drv.h | 10 ++++++++++
 2 files changed, 23 insertions(+), 7 deletions(-)

diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
index 7124042..4f2c748 100644
--- a/drivers/block/zram/zram_drv.c
+++ b/drivers/block/zram/zram_drv.c
@@ -28,10 +28,9 @@
 #include <linux/device.h>
 #include <linux/genhd.h>
 #include <linux/highmem.h>
-#include <linux/slab.h>
-#include <linux/lzo.h>
 #include <linux/string.h>
 #include <linux/vmalloc.h>
+#include <linux/lzo.h>
 
 #include "zram_drv.h"
 
@@ -42,6 +41,12 @@ static struct zram *zram_devices;
 /* Module params (documentation at end) */
 static unsigned int num_devices = 1;
 
+static struct zram_compress_ops lzo_compressor = {
+	.workmem_sz = LZO1X_MEM_COMPRESS,
+	.compress = lzo1x_1_compress,
+	.decompress = lzo1x_decompress_safe,
+};
+
 #define ZRAM_ATTR_RO(name)						\
 static ssize_t zram_attr_##name##_show(struct device *d,		\
 				struct device_attribute *attr, char *b)	\
@@ -166,14 +171,14 @@ static void zram_meta_free(struct zram_meta *meta)
 	kfree(meta);
 }
 
-static struct zram_meta *zram_meta_alloc(u64 disksize)
+static struct zram_meta *zram_meta_alloc(int workmem_sz, u64 disksize)
 {
 	size_t num_pages;
 	struct zram_meta *meta = kmalloc(sizeof(*meta), GFP_KERNEL);
 	if (!meta)
 		goto out;
 
-	meta->compress_workmem = kzalloc(LZO1X_MEM_COMPRESS, GFP_KERNEL);
+	meta->compress_workmem = kzalloc(workmem_sz, GFP_KERNEL);
 	if (!meta->compress_workmem)
 		goto free_meta;
 
@@ -301,7 +306,7 @@ static int zram_decompress_page(struct zram *zram, char *mem, u32 index)
 	if (size == PAGE_SIZE)
 		copy_page(mem, cmem);
 	else
-		ret = lzo1x_decompress_safe(cmem, size,	mem, &clen);
+		ret = zram->ops->decompress(cmem, size, mem, &clen);
 	zs_unmap_object(meta->mem_pool, handle);
 	read_unlock(&meta->tb_lock);
 
@@ -420,7 +425,7 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index,
 		goto out;
 	}
 
-	ret = lzo1x_1_compress(uncmem, PAGE_SIZE, src, &clen,
+	ret = zram->ops->compress(uncmem, PAGE_SIZE, src, &clen,
 			       meta->compress_workmem);
 	if (!is_partial_io(bvec)) {
 		kunmap_atomic(user_mem);
@@ -551,7 +556,7 @@ static ssize_t disksize_store(struct device *dev,
 	}
 
 	disksize = PAGE_ALIGN(disksize);
-	zram->meta = zram_meta_alloc(disksize);
+	zram->meta = zram_meta_alloc(zram->ops->workmem_sz, disksize);
 
 	zram->disksize = disksize;
 	set_capacity(zram->disk, zram->disksize >> SECTOR_SHIFT);
@@ -785,6 +790,7 @@ static int create_device(struct zram *zram, int device_id)
 		goto out_free_disk;
 	}
 
+	zram->ops = &lzo_compressor;
 	zram->meta = NULL;
 	return 0;
 
diff --git a/drivers/block/zram/zram_drv.h b/drivers/block/zram/zram_drv.h
index 1d5b1f5..5488682 100644
--- a/drivers/block/zram/zram_drv.h
+++ b/drivers/block/zram/zram_drv.h
@@ -88,8 +88,18 @@ struct zram_meta {
 	struct mutex buffer_lock; /* protect compress buffers */
 };
 
+/* compression/decompression functions and algorithm-specific workmem size */
+struct zram_compress_ops {
+	int (*compress)(const unsigned char *src, size_t src_len,
+			unsigned char *dst, size_t *dst_len, void *wrkmem);
+	int (*decompress)(const unsigned char *src, size_t src_len,
+			unsigned char *dst, size_t *dst_len);
+	long workmem_sz;
+};
+
 struct zram {
 	struct zram_meta *meta;
+	struct zram_compress_ops *ops;
 	struct request_queue *queue;
 	struct gendisk *disk;
 	/* Prevent concurrent execution of device init, reset and R/W request */
-- 
1.8.5.3.493.gb139ac2


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

* [RFC PATCH 3/3] zram: list and select compression algorithms
  2014-01-17 11:04 [RFC PATCH 0/3] add LZ4 compression support Sergey Senozhatsky
  2014-01-17 11:04 ` [RFC PATCH 1/3] zram: delete zram_init_device() function Sergey Senozhatsky
  2014-01-17 11:04 ` [RFC PATCH 2/3] zram: introduce zram compressor operations struct Sergey Senozhatsky
@ 2014-01-17 11:04 ` Sergey Senozhatsky
  2014-01-20  5:18   ` Minchan Kim
  2 siblings, 1 reply; 11+ messages in thread
From: Sergey Senozhatsky @ 2014-01-17 11:04 UTC (permalink / raw)
  To: Minchan Kim
  Cc: Jerome Marchand, Nitin Gupta, linux-kernel, Sergey Senozhatsky

Add compressor device attr that allows to list and select
compression algorithms.

Define and make available for selection LZ4 compressor ops.

usage example:
List available compression algorithms (currently selected
one is LZO):
  cat /sys/block/zram0/compressor
  <lzo> lz4

Change compression algorithm to LZ4:
  echo lz4 > /sys/block/zram0/compressor
  cat /sys/block/zram0/compressor
  lzo <lz4>

Update documentation with "Select compression algorithm" section

Signed-off-by: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
---
 Documentation/blockdev/zram.txt | 23 ++++++++++++++++-----
 drivers/block/zram/Kconfig      |  2 ++
 drivers/block/zram/zram_drv.c   | 46 +++++++++++++++++++++++++++++++++++++----
 3 files changed, 62 insertions(+), 9 deletions(-)

diff --git a/Documentation/blockdev/zram.txt b/Documentation/blockdev/zram.txt
index 393541be..af90d29 100644
--- a/Documentation/blockdev/zram.txt
+++ b/Documentation/blockdev/zram.txt
@@ -21,7 +21,20 @@ Following shows a typical sequence of steps for using zram.
 	This creates 4 devices: /dev/zram{0,1,2,3}
 	(num_devices parameter is optional. Default: 1)
 
-2) Set Disksize
+2) Select compression algorithm
+'compressor' sysfs node allows to see available, currently used
+and change compression algorithms.
+In order to list available compression algorithms (currently selected
+one is LZO):
+	cat /sys/block/zram0/compressor
+	<lzo> lz4
+
+Change compression algorithm to LZ4:
+	echo lz4 > /sys/block/zram0/compressor
+	cat /sys/block/zram0/compressor
+	lzo <lz4>
+
+3) Set Disksize
         Set disk size by writing the value to sysfs node 'disksize'.
         The value can be either in bytes or you can use mem suffixes.
         Examples:
@@ -38,14 +51,14 @@ There is little point creating a zram of greater than twice the size of memory
 since we expect a 2:1 compression ratio. Note that zram uses about 0.1% of the
 size of the disk when not in use so a huge zram is wasteful.
 
-3) Activate:
+4) Activate:
 	mkswap /dev/zram0
 	swapon /dev/zram0
 
 	mkfs.ext4 /dev/zram1
 	mount /dev/zram1 /tmp
 
-4) Stats:
+5) Stats:
 	Per-device statistics are exported as various nodes under
 	/sys/block/zram<id>/
 		disksize
@@ -59,11 +72,11 @@ size of the disk when not in use so a huge zram is wasteful.
 		compr_data_size
 		mem_used_total
 
-5) Deactivate:
+6) Deactivate:
 	swapoff /dev/zram0
 	umount /dev/zram1
 
-6) Reset:
+7) Reset:
 	Write any positive value to 'reset' sysfs node
 	echo 1 > /sys/block/zram0/reset
 	echo 1 > /sys/block/zram1/reset
diff --git a/drivers/block/zram/Kconfig b/drivers/block/zram/Kconfig
index 3450be8..09dacd6 100644
--- a/drivers/block/zram/Kconfig
+++ b/drivers/block/zram/Kconfig
@@ -3,6 +3,8 @@ config ZRAM
 	depends on BLOCK && SYSFS && ZSMALLOC
 	select LZO_COMPRESS
 	select LZO_DECOMPRESS
+	select LZ4_COMPRESS
+	select LZ4_DECOMPRESS
 	default n
 	help
 	  Creates virtual block devices called /dev/zramX (X = 0, 1, ...).
diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
index 4f2c748..f1434f8 100644
--- a/drivers/block/zram/zram_drv.c
+++ b/drivers/block/zram/zram_drv.c
@@ -31,6 +31,7 @@
 #include <linux/string.h>
 #include <linux/vmalloc.h>
 #include <linux/lzo.h>
+#include <linux/lz4.h>
 
 #include "zram_drv.h"
 
@@ -47,6 +48,12 @@ static struct zram_compress_ops lzo_compressor = {
 	.decompress = lzo1x_decompress_safe,
 };
 
+static struct zram_compress_ops lz4_compressor = {
+	.workmem_sz = LZ4_MEM_COMPRESS,
+	.compress = lz4_compress,
+	.decompress = lz4_decompress_unknownoutputsize,
+};
+
 #define ZRAM_ATTR_RO(name)						\
 static ssize_t zram_attr_##name##_show(struct device *d,		\
 				struct device_attribute *attr, char *b)	\
@@ -113,6 +120,34 @@ static ssize_t mem_used_total_show(struct device *dev,
 	return sprintf(buf, "%llu\n", val);
 }
 
+static ssize_t compressor_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct zram *zram = dev_to_zram(dev);
+	if (zram->ops == &lzo_compressor)
+		return sprintf(buf, "<lzo> lz4\n");
+	return sprintf(buf, "lzo <lz4>\n");
+}
+
+static ssize_t compressor_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t len)
+{
+	struct zram *zram = dev_to_zram(dev);
+
+	down_write(&zram->init_lock);
+	if (init_done(zram)) {
+		up_write(&zram->init_lock);
+		pr_info("Cannot change compressor for initialized device\n");
+		return -EBUSY;
+	}
+	if (strncmp(buf, "lzo", 3) == 0)
+		zram->ops = &lzo_compressor;
+	else
+		zram->ops = &lz4_compressor;
+	up_write(&zram->init_lock);
+	return len;
+}
+
 /* flag operations needs meta->tb_lock */
 static int zram_test_flag(struct zram_meta *meta, u32 index,
 			enum zram_pageflags flag)
@@ -285,7 +320,7 @@ static void zram_free_page(struct zram *zram, size_t index)
 
 static int zram_decompress_page(struct zram *zram, char *mem, u32 index)
 {
-	int ret = LZO_E_OK;
+	int ret = 0;
 	size_t clen = PAGE_SIZE;
 	unsigned char *cmem;
 	struct zram_meta *meta = zram->meta;
@@ -311,7 +346,7 @@ static int zram_decompress_page(struct zram *zram, char *mem, u32 index)
 	read_unlock(&meta->tb_lock);
 
 	/* Should NEVER happen. Return bio error if it does. */
-	if (unlikely(ret != LZO_E_OK)) {
+	if (unlikely(ret)) {
 		pr_err("Decompression failed! err=%d, page=%u\n", ret, index);
 		atomic64_inc(&zram->stats.failed_reads);
 		return ret;
@@ -354,7 +389,7 @@ static int zram_bvec_read(struct zram *zram, struct bio_vec *bvec,
 
 	ret = zram_decompress_page(zram, uncmem, index);
 	/* Should NEVER happen. Return bio error if it does. */
-	if (unlikely(ret != LZO_E_OK))
+	if (unlikely(ret))
 		goto out_cleanup;
 
 	if (is_partial_io(bvec))
@@ -433,7 +468,7 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index,
 		uncmem = NULL;
 	}
 
-	if (unlikely(ret != LZO_E_OK)) {
+	if (unlikely(ret)) {
 		pr_err("Compression failed! err=%d\n", ret);
 		goto out;
 	}
@@ -705,6 +740,8 @@ static DEVICE_ATTR(initstate, S_IRUGO, initstate_show, NULL);
 static DEVICE_ATTR(reset, S_IWUSR, NULL, reset_store);
 static DEVICE_ATTR(orig_data_size, S_IRUGO, orig_data_size_show, NULL);
 static DEVICE_ATTR(mem_used_total, S_IRUGO, mem_used_total_show, NULL);
+static DEVICE_ATTR(compressor, S_IRUGO | S_IWUSR,
+		compressor_show, compressor_store);
 
 ZRAM_ATTR_RO(num_reads);
 ZRAM_ATTR_RO(num_writes);
@@ -719,6 +756,7 @@ static struct attribute *zram_disk_attrs[] = {
 	&dev_attr_disksize.attr,
 	&dev_attr_initstate.attr,
 	&dev_attr_reset.attr,
+	&dev_attr_compressor.attr,
 	&dev_attr_num_reads.attr,
 	&dev_attr_num_writes.attr,
 	&dev_attr_failed_reads.attr,
-- 
1.8.5.3.493.gb139ac2


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

* Re: [RFC PATCH 1/3] zram: delete zram_init_device() function
  2014-01-17 11:04 ` [RFC PATCH 1/3] zram: delete zram_init_device() function Sergey Senozhatsky
@ 2014-01-20  4:43   ` Minchan Kim
  0 siblings, 0 replies; 11+ messages in thread
From: Minchan Kim @ 2014-01-20  4:43 UTC (permalink / raw)
  To: Sergey Senozhatsky; +Cc: Jerome Marchand, Nitin Gupta, linux-kernel

Hello Sergey,

Looks good to me and I found a bug which had been in there so I rebased
this patch on the top.
https://git.kernel.org/cgit/linux/kernel/git/minchan/linux.git/commit/?h=zram-next&id=241e34fc6c3c1a41575fbe6383436be70df300d1

On Fri, Jan 17, 2014 at 02:04:15PM +0300, Sergey Senozhatsky wrote:
> allocate new `zram_meta' in disksize_store() only for uninitialised
> zram device, saving a number of allocations and deallocations in case
> if disksize_store() was called on currently used device. at the same
> time zram_meta stack variable is not necessary, because we can set
> ->meta directly. there is also no need in setting QUEUE_FLAG_NONROT
> queue on every disksize_store(), set it once during device creation.
> 
> Signed-off-by: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>

Otherwise,

Acked-by: Minchan Kim <minchan@kernel.org>

-- 
Kind regards,
Minchan Kim

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

* Re: [RFC PATCH 2/3] zram: introduce zram compressor operations struct
  2014-01-17 11:04 ` [RFC PATCH 2/3] zram: introduce zram compressor operations struct Sergey Senozhatsky
@ 2014-01-20  5:12   ` Minchan Kim
  2014-01-20  8:39     ` Sergey Senozhatsky
  2014-01-20 10:03     ` Sergey Senozhatsky
  0 siblings, 2 replies; 11+ messages in thread
From: Minchan Kim @ 2014-01-20  5:12 UTC (permalink / raw)
  To: Sergey Senozhatsky; +Cc: Jerome Marchand, Nitin Gupta, linux-kernel

Hello Sergey,

I reviewed this patchset and I suggest somethings.
Please have a look and feedback to me. :)

1. Let's define new file zram_comp.c
2. zram_comp includes following field
   .create
   .compress
   .decompress.
   .destroy
   .name

1) create/destroy
Will set up necessary things like allocating buffer, lock init or other things
might happen in future when initialization time.
I have a plan to support multiple buffer to do compression/decompression in
parallel so we could optimize write VS write path, too.

2) compress/decompress

It's very clear.

3) name field will be used for tell to user what's kinds of compression
algorithm zram support.

On Fri, Jan 17, 2014 at 02:04:16PM +0300, Sergey Senozhatsky wrote:
> This is preparation patch to add LZ4 compression support.
> 
> struct zram_compress_ops defines common compress and decompress
> prototypes. Use these ops->compress and ops->decompress callbacks
> instead of direct LZO lzo1x_1_compress() and lzo1x_decompress_safe()
> calls.
> 
> Compressor ops should be defined before zram meta allocation,
> because the size of meta->compress_workmem depends on selected
> compression algorithm.
> 
> Define LZO compressor ops and set it as the only one available
> zram compressor at the moment.
> 
> Signed-off-by: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
> ---
>  drivers/block/zram/zram_drv.c | 20 +++++++++++++-------
>  drivers/block/zram/zram_drv.h | 10 ++++++++++
>  2 files changed, 23 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
> index 7124042..4f2c748 100644
> --- a/drivers/block/zram/zram_drv.c
> +++ b/drivers/block/zram/zram_drv.c
> @@ -28,10 +28,9 @@
>  #include <linux/device.h>
>  #include <linux/genhd.h>
>  #include <linux/highmem.h>
> -#include <linux/slab.h>
> -#include <linux/lzo.h>
>  #include <linux/string.h>
>  #include <linux/vmalloc.h>
> +#include <linux/lzo.h>

Let's include zram_comps.h only and zram_comps.h includes other compression
alrogithms header. If user don't want to support some compression
alrogithm, it shouldn't be included.
Of course, user can select kinds of compressor in configuration step.

>  
>  #include "zram_drv.h"
>  
> @@ -42,6 +41,12 @@ static struct zram *zram_devices;
>  /* Module params (documentation at end) */
>  static unsigned int num_devices = 1;
>  
> +static struct zram_compress_ops lzo_compressor = {
> +	.workmem_sz = LZO1X_MEM_COMPRESS,

workmem_sz should be part of compressor internal.

> +	.compress = lzo1x_1_compress,
> +	.decompress = lzo1x_decompress_safe,
> +};
> +
>  #define ZRAM_ATTR_RO(name)						\
>  static ssize_t zram_attr_##name##_show(struct device *d,		\
>  				struct device_attribute *attr, char *b)	\
> @@ -166,14 +171,14 @@ static void zram_meta_free(struct zram_meta *meta)
>  	kfree(meta);
>  }
>  
> -static struct zram_meta *zram_meta_alloc(u64 disksize)
> +static struct zram_meta *zram_meta_alloc(int workmem_sz, u64 disksize)
>  {
>  	size_t num_pages;
>  	struct zram_meta *meta = kmalloc(sizeof(*meta), GFP_KERNEL);
>  	if (!meta)
>  		goto out;
>  
> -	meta->compress_workmem = kzalloc(LZO1X_MEM_COMPRESS, GFP_KERNEL);
> +	meta->compress_workmem = kzalloc(workmem_sz, GFP_KERNEL);

Instead of exposing compression internal stuff, let's call comp->create.

>  	if (!meta->compress_workmem)
>  		goto free_meta;
>  
> @@ -301,7 +306,7 @@ static int zram_decompress_page(struct zram *zram, char *mem, u32 index)
>  	if (size == PAGE_SIZE)
>  		copy_page(mem, cmem);
>  	else
> -		ret = lzo1x_decompress_safe(cmem, size,	mem, &clen);
> +		ret = zram->ops->decompress(cmem, size, mem, &clen);
>  	zs_unmap_object(meta->mem_pool, handle);
>  	read_unlock(&meta->tb_lock);
>  
> @@ -420,7 +425,7 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index,
>  		goto out;
>  	}
>  
> -	ret = lzo1x_1_compress(uncmem, PAGE_SIZE, src, &clen,
> +	ret = zram->ops->compress(uncmem, PAGE_SIZE, src, &clen,
>  			       meta->compress_workmem);

Ditto. compress_workmem should be part of compressor itself.


>  	if (!is_partial_io(bvec)) {
>  		kunmap_atomic(user_mem);
> @@ -551,7 +556,7 @@ static ssize_t disksize_store(struct device *dev,
>  	}
>  
>  	disksize = PAGE_ALIGN(disksize);
> -	zram->meta = zram_meta_alloc(disksize);
> +	zram->meta = zram_meta_alloc(zram->ops->workmem_sz, disksize);

So, we don't need zram->ops->workmem_sz.

>  
>  	zram->disksize = disksize;
>  	set_capacity(zram->disk, zram->disksize >> SECTOR_SHIFT);
> @@ -785,6 +790,7 @@ static int create_device(struct zram *zram, int device_id)
>  		goto out_free_disk;
>  	}
>  
> +	zram->ops = &lzo_compressor;

Let's define choose_compressor function with some argument
so the result is following as

zram->comp = choose_compressor("lzo");

>  	zram->meta = NULL;
>  	return 0;
>  
> diff --git a/drivers/block/zram/zram_drv.h b/drivers/block/zram/zram_drv.h
> index 1d5b1f5..5488682 100644
> --- a/drivers/block/zram/zram_drv.h
> +++ b/drivers/block/zram/zram_drv.h
> @@ -88,8 +88,18 @@ struct zram_meta {
>  	struct mutex buffer_lock; /* protect compress buffers */
>  };
>  
> +/* compression/decompression functions and algorithm-specific workmem size */
> +struct zram_compress_ops {
> +	int (*compress)(const unsigned char *src, size_t src_len,
> +			unsigned char *dst, size_t *dst_len, void *wrkmem);
> +	int (*decompress)(const unsigned char *src, size_t src_len,
> +			unsigned char *dst, size_t *dst_len);
> +	long workmem_sz;
> +};
> +
>  struct zram {
>  	struct zram_meta *meta;
> +	struct zram_compress_ops *ops;
>  	struct request_queue *queue;
>  	struct gendisk *disk;
>  	/* Prevent concurrent execution of device init, reset and R/W request */
> -- 
> 1.8.5.3.493.gb139ac2
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/

-- 
Kind regards,
Minchan Kim

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

* Re: [RFC PATCH 3/3] zram: list and select compression algorithms
  2014-01-17 11:04 ` [RFC PATCH 3/3] zram: list and select compression algorithms Sergey Senozhatsky
@ 2014-01-20  5:18   ` Minchan Kim
  0 siblings, 0 replies; 11+ messages in thread
From: Minchan Kim @ 2014-01-20  5:18 UTC (permalink / raw)
  To: Sergey Senozhatsky; +Cc: Jerome Marchand, Nitin Gupta, linux-kernel

On Fri, Jan 17, 2014 at 02:04:17PM +0300, Sergey Senozhatsky wrote:
> Add compressor device attr that allows to list and select
> compression algorithms.
> 
> Define and make available for selection LZ4 compressor ops.
> 
> usage example:
> List available compression algorithms (currently selected
> one is LZO):
>   cat /sys/block/zram0/compressor
>   <lzo> lz4
> 
> Change compression algorithm to LZ4:
>   echo lz4 > /sys/block/zram0/compressor
>   cat /sys/block/zram0/compressor
>   lzo <lz4>

Interface looks good to me.

> 
> Update documentation with "Select compression algorithm" section
> 
> Signed-off-by: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
> ---
>  Documentation/blockdev/zram.txt | 23 ++++++++++++++++-----
>  drivers/block/zram/Kconfig      |  2 ++
>  drivers/block/zram/zram_drv.c   | 46 +++++++++++++++++++++++++++++++++++++----
>  3 files changed, 62 insertions(+), 9 deletions(-)
> 
> diff --git a/Documentation/blockdev/zram.txt b/Documentation/blockdev/zram.txt
> index 393541be..af90d29 100644
> --- a/Documentation/blockdev/zram.txt
> +++ b/Documentation/blockdev/zram.txt
> @@ -21,7 +21,20 @@ Following shows a typical sequence of steps for using zram.
>  	This creates 4 devices: /dev/zram{0,1,2,3}
>  	(num_devices parameter is optional. Default: 1)
>  
> -2) Set Disksize
> +2) Select compression algorithm
> +'compressor' sysfs node allows to see available, currently used
> +and change compression algorithms.
> +In order to list available compression algorithms (currently selected
> +one is LZO):
> +	cat /sys/block/zram0/compressor
> +	<lzo> lz4
> +
> +Change compression algorithm to LZ4:
> +	echo lz4 > /sys/block/zram0/compressor
> +	cat /sys/block/zram0/compressor
> +	lzo <lz4>
> +
> +3) Set Disksize
>          Set disk size by writing the value to sysfs node 'disksize'.
>          The value can be either in bytes or you can use mem suffixes.
>          Examples:
> @@ -38,14 +51,14 @@ There is little point creating a zram of greater than twice the size of memory
>  since we expect a 2:1 compression ratio. Note that zram uses about 0.1% of the
>  size of the disk when not in use so a huge zram is wasteful.
>  
> -3) Activate:
> +4) Activate:
>  	mkswap /dev/zram0
>  	swapon /dev/zram0
>  
>  	mkfs.ext4 /dev/zram1
>  	mount /dev/zram1 /tmp
>  
> -4) Stats:
> +5) Stats:
>  	Per-device statistics are exported as various nodes under
>  	/sys/block/zram<id>/
>  		disksize
> @@ -59,11 +72,11 @@ size of the disk when not in use so a huge zram is wasteful.
>  		compr_data_size
>  		mem_used_total
>  
> -5) Deactivate:
> +6) Deactivate:
>  	swapoff /dev/zram0
>  	umount /dev/zram1
>  
> -6) Reset:
> +7) Reset:
>  	Write any positive value to 'reset' sysfs node
>  	echo 1 > /sys/block/zram0/reset
>  	echo 1 > /sys/block/zram1/reset
> diff --git a/drivers/block/zram/Kconfig b/drivers/block/zram/Kconfig
> index 3450be8..09dacd6 100644
> --- a/drivers/block/zram/Kconfig
> +++ b/drivers/block/zram/Kconfig
> @@ -3,6 +3,8 @@ config ZRAM
>  	depends on BLOCK && SYSFS && ZSMALLOC
>  	select LZO_COMPRESS
>  	select LZO_DECOMPRESS
> +	select LZ4_COMPRESS
> +	select LZ4_DECOMPRESS

But user should select what kinds of compressor then want
some user want only lzo while others want lzo, lz2 and zlib all.


>  	default n
>  	help
>  	  Creates virtual block devices called /dev/zramX (X = 0, 1, ...).
> diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
> index 4f2c748..f1434f8 100644
> --- a/drivers/block/zram/zram_drv.c
> +++ b/drivers/block/zram/zram_drv.c
> @@ -31,6 +31,7 @@
>  #include <linux/string.h>
>  #include <linux/vmalloc.h>
>  #include <linux/lzo.h>
> +#include <linux/lz4.h>
>  
>  #include "zram_drv.h"
>  
> @@ -47,6 +48,12 @@ static struct zram_compress_ops lzo_compressor = {
>  	.decompress = lzo1x_decompress_safe,
>  };
>  
> +static struct zram_compress_ops lz4_compressor = {
> +	.workmem_sz = LZ4_MEM_COMPRESS,
> +	.compress = lz4_compress,
> +	.decompress = lz4_decompress_unknownoutputsize,
> +};
> +
>  #define ZRAM_ATTR_RO(name)						\
>  static ssize_t zram_attr_##name##_show(struct device *d,		\
>  				struct device_attribute *attr, char *b)	\
> @@ -113,6 +120,34 @@ static ssize_t mem_used_total_show(struct device *dev,
>  	return sprintf(buf, "%llu\n", val);
>  }
>  
> +static ssize_t compressor_show(struct device *dev,
> +		struct device_attribute *attr, char *buf)
> +{
> +	struct zram *zram = dev_to_zram(dev);
> +	if (zram->ops == &lzo_compressor)
> +		return sprintf(buf, "<lzo> lz4\n");
> +	return sprintf(buf, "lzo <lz4>\n");
> +}
> +
> +static ssize_t compressor_store(struct device *dev,
> +		struct device_attribute *attr, const char *buf, size_t len)
> +{
> +	struct zram *zram = dev_to_zram(dev);
> +
> +	down_write(&zram->init_lock);
> +	if (init_done(zram)) {
> +		up_write(&zram->init_lock);
> +		pr_info("Cannot change compressor for initialized device\n");
> +		return -EBUSY;
> +	}
> +	if (strncmp(buf, "lzo", 3) == 0)
> +		zram->ops = &lzo_compressor;
> +	else
> +		zram->ops = &lz4_compressor;
> +	up_write(&zram->init_lock);
> +	return len;
> +}

Changing compressow should be allowed only when zram was created or
reset. IOW, there should be no datacompressed by old compressor in memory.

> +
>  /* flag operations needs meta->tb_lock */
>  static int zram_test_flag(struct zram_meta *meta, u32 index,
>  			enum zram_pageflags flag)
> @@ -285,7 +320,7 @@ static void zram_free_page(struct zram *zram, size_t index)
>  
>  static int zram_decompress_page(struct zram *zram, char *mem, u32 index)
>  {
> -	int ret = LZO_E_OK;
> +	int ret = 0;
>  	size_t clen = PAGE_SIZE;
>  	unsigned char *cmem;
>  	struct zram_meta *meta = zram->meta;
> @@ -311,7 +346,7 @@ static int zram_decompress_page(struct zram *zram, char *mem, u32 index)
>  	read_unlock(&meta->tb_lock);
>  
>  	/* Should NEVER happen. Return bio error if it does. */
> -	if (unlikely(ret != LZO_E_OK)) {
> +	if (unlikely(ret)) {
>  		pr_err("Decompression failed! err=%d, page=%u\n", ret, index);
>  		atomic64_inc(&zram->stats.failed_reads);
>  		return ret;
> @@ -354,7 +389,7 @@ static int zram_bvec_read(struct zram *zram, struct bio_vec *bvec,
>  
>  	ret = zram_decompress_page(zram, uncmem, index);
>  	/* Should NEVER happen. Return bio error if it does. */
> -	if (unlikely(ret != LZO_E_OK))
> +	if (unlikely(ret))
>  		goto out_cleanup;
>  
>  	if (is_partial_io(bvec))
> @@ -433,7 +468,7 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index,
>  		uncmem = NULL;
>  	}
>  
> -	if (unlikely(ret != LZO_E_OK)) {
> +	if (unlikely(ret)) {
>  		pr_err("Compression failed! err=%d\n", ret);
>  		goto out;
>  	}
> @@ -705,6 +740,8 @@ static DEVICE_ATTR(initstate, S_IRUGO, initstate_show, NULL);
>  static DEVICE_ATTR(reset, S_IWUSR, NULL, reset_store);
>  static DEVICE_ATTR(orig_data_size, S_IRUGO, orig_data_size_show, NULL);
>  static DEVICE_ATTR(mem_used_total, S_IRUGO, mem_used_total_show, NULL);
> +static DEVICE_ATTR(compressor, S_IRUGO | S_IWUSR,
> +		compressor_show, compressor_store);
>  
>  ZRAM_ATTR_RO(num_reads);
>  ZRAM_ATTR_RO(num_writes);
> @@ -719,6 +756,7 @@ static struct attribute *zram_disk_attrs[] = {
>  	&dev_attr_disksize.attr,
>  	&dev_attr_initstate.attr,
>  	&dev_attr_reset.attr,
> +	&dev_attr_compressor.attr,
>  	&dev_attr_num_reads.attr,
>  	&dev_attr_num_writes.attr,
>  	&dev_attr_failed_reads.attr,
> -- 
> 1.8.5.3.493.gb139ac2
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/

-- 
Kind regards,
Minchan Kim

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

* Re: [RFC PATCH 2/3] zram: introduce zram compressor operations struct
  2014-01-20  5:12   ` Minchan Kim
@ 2014-01-20  8:39     ` Sergey Senozhatsky
  2014-01-20 10:03     ` Sergey Senozhatsky
  1 sibling, 0 replies; 11+ messages in thread
From: Sergey Senozhatsky @ 2014-01-20  8:39 UTC (permalink / raw)
  To: Minchan Kim; +Cc: Jerome Marchand, Nitin Gupta, linux-kernel

On (01/20/14 14:12), Minchan Kim wrote:
> Date: Mon, 20 Jan 2014 14:12:33 +0900
> From: Minchan Kim <minchan@kernel.org>
> To: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
> Cc: Jerome Marchand <jmarchan@redhat.com>, Nitin Gupta <ngupta@vflare.org>,
>  linux-kernel@vger.kernel.org
> Subject: Re: [RFC PATCH 2/3] zram: introduce zram compressor operations
>  struct
> User-Agent: Mutt/1.5.21 (2010-09-15)
> 
> Hello Sergey,
> 

Hello Minchan,

> I reviewed this patchset and I suggest somethings.
> Please have a look and feedback to me. :)
> 
> 1. Let's define new file zram_comp.c
> 2. zram_comp includes following field
>    .create
>    .compress
>    .decompress.
>    .destroy
>    .name
> 
> 1) create/destroy
> Will set up necessary things like allocating buffer, lock init or other things
> might happen in future when initialization time.
> I have a plan to support multiple buffer to do compression/decompression in
> parallel so we could optimize write VS write path, too.
> 

I have a patch for this

> 2) compress/decompress
> 
> It's very clear.
> 
> 3) name field will be used for tell to user what's kinds of compression
> algorithm zram support.
> 

looks good. will start addressing


	-ss

> On Fri, Jan 17, 2014 at 02:04:16PM +0300, Sergey Senozhatsky wrote:
> > This is preparation patch to add LZ4 compression support.
> > 
> > struct zram_compress_ops defines common compress and decompress
> > prototypes. Use these ops->compress and ops->decompress callbacks
> > instead of direct LZO lzo1x_1_compress() and lzo1x_decompress_safe()
> > calls.
> > 
> > Compressor ops should be defined before zram meta allocation,
> > because the size of meta->compress_workmem depends on selected
> > compression algorithm.
> > 
> > Define LZO compressor ops and set it as the only one available
> > zram compressor at the moment.
> > 
> > Signed-off-by: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
> > ---
> >  drivers/block/zram/zram_drv.c | 20 +++++++++++++-------
> >  drivers/block/zram/zram_drv.h | 10 ++++++++++
> >  2 files changed, 23 insertions(+), 7 deletions(-)
> > 
> > diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
> > index 7124042..4f2c748 100644
> > --- a/drivers/block/zram/zram_drv.c
> > +++ b/drivers/block/zram/zram_drv.c
> > @@ -28,10 +28,9 @@
> >  #include <linux/device.h>
> >  #include <linux/genhd.h>
> >  #include <linux/highmem.h>
> > -#include <linux/slab.h>
> > -#include <linux/lzo.h>
> >  #include <linux/string.h>
> >  #include <linux/vmalloc.h>
> > +#include <linux/lzo.h>
> 
> Let's include zram_comps.h only and zram_comps.h includes other compression
> alrogithms header. If user don't want to support some compression
> alrogithm, it shouldn't be included.
> Of course, user can select kinds of compressor in configuration step.
> 
> >  
> >  #include "zram_drv.h"
> >  
> > @@ -42,6 +41,12 @@ static struct zram *zram_devices;
> >  /* Module params (documentation at end) */
> >  static unsigned int num_devices = 1;
> >  
> > +static struct zram_compress_ops lzo_compressor = {
> > +	.workmem_sz = LZO1X_MEM_COMPRESS,
> 
> workmem_sz should be part of compressor internal.
> 
> > +	.compress = lzo1x_1_compress,
> > +	.decompress = lzo1x_decompress_safe,
> > +};
> > +
> >  #define ZRAM_ATTR_RO(name)						\
> >  static ssize_t zram_attr_##name##_show(struct device *d,		\
> >  				struct device_attribute *attr, char *b)	\
> > @@ -166,14 +171,14 @@ static void zram_meta_free(struct zram_meta *meta)
> >  	kfree(meta);
> >  }
> >  
> > -static struct zram_meta *zram_meta_alloc(u64 disksize)
> > +static struct zram_meta *zram_meta_alloc(int workmem_sz, u64 disksize)
> >  {
> >  	size_t num_pages;
> >  	struct zram_meta *meta = kmalloc(sizeof(*meta), GFP_KERNEL);
> >  	if (!meta)
> >  		goto out;
> >  
> > -	meta->compress_workmem = kzalloc(LZO1X_MEM_COMPRESS, GFP_KERNEL);
> > +	meta->compress_workmem = kzalloc(workmem_sz, GFP_KERNEL);
> 
> Instead of exposing compression internal stuff, let's call comp->create.
> 
> >  	if (!meta->compress_workmem)
> >  		goto free_meta;
> >  
> > @@ -301,7 +306,7 @@ static int zram_decompress_page(struct zram *zram, char *mem, u32 index)
> >  	if (size == PAGE_SIZE)
> >  		copy_page(mem, cmem);
> >  	else
> > -		ret = lzo1x_decompress_safe(cmem, size,	mem, &clen);
> > +		ret = zram->ops->decompress(cmem, size, mem, &clen);
> >  	zs_unmap_object(meta->mem_pool, handle);
> >  	read_unlock(&meta->tb_lock);
> >  
> > @@ -420,7 +425,7 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index,
> >  		goto out;
> >  	}
> >  
> > -	ret = lzo1x_1_compress(uncmem, PAGE_SIZE, src, &clen,
> > +	ret = zram->ops->compress(uncmem, PAGE_SIZE, src, &clen,
> >  			       meta->compress_workmem);
> 
> Ditto. compress_workmem should be part of compressor itself.
> 
> 
> >  	if (!is_partial_io(bvec)) {
> >  		kunmap_atomic(user_mem);
> > @@ -551,7 +556,7 @@ static ssize_t disksize_store(struct device *dev,
> >  	}
> >  
> >  	disksize = PAGE_ALIGN(disksize);
> > -	zram->meta = zram_meta_alloc(disksize);
> > +	zram->meta = zram_meta_alloc(zram->ops->workmem_sz, disksize);
> 
> So, we don't need zram->ops->workmem_sz.
> 
> >  
> >  	zram->disksize = disksize;
> >  	set_capacity(zram->disk, zram->disksize >> SECTOR_SHIFT);
> > @@ -785,6 +790,7 @@ static int create_device(struct zram *zram, int device_id)
> >  		goto out_free_disk;
> >  	}
> >  
> > +	zram->ops = &lzo_compressor;
> 
> Let's define choose_compressor function with some argument
> so the result is following as
> 
> zram->comp = choose_compressor("lzo");
> 
> >  	zram->meta = NULL;
> >  	return 0;
> >  
> > diff --git a/drivers/block/zram/zram_drv.h b/drivers/block/zram/zram_drv.h
> > index 1d5b1f5..5488682 100644
> > --- a/drivers/block/zram/zram_drv.h
> > +++ b/drivers/block/zram/zram_drv.h
> > @@ -88,8 +88,18 @@ struct zram_meta {
> >  	struct mutex buffer_lock; /* protect compress buffers */
> >  };
> >  
> > +/* compression/decompression functions and algorithm-specific workmem size */
> > +struct zram_compress_ops {
> > +	int (*compress)(const unsigned char *src, size_t src_len,
> > +			unsigned char *dst, size_t *dst_len, void *wrkmem);
> > +	int (*decompress)(const unsigned char *src, size_t src_len,
> > +			unsigned char *dst, size_t *dst_len);
> > +	long workmem_sz;
> > +};
> > +
> >  struct zram {
> >  	struct zram_meta *meta;
> > +	struct zram_compress_ops *ops;
> >  	struct request_queue *queue;
> >  	struct gendisk *disk;
> >  	/* Prevent concurrent execution of device init, reset and R/W request */
> > -- 
> > 1.8.5.3.493.gb139ac2
> > 
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> > the body of a message to majordomo@vger.kernel.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> > Please read the FAQ at  http://www.tux.org/lkml/
> 
> -- 
> Kind regards,
> Minchan Kim
> 

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

* Re: [RFC PATCH 2/3] zram: introduce zram compressor operations struct
  2014-01-20  5:12   ` Minchan Kim
  2014-01-20  8:39     ` Sergey Senozhatsky
@ 2014-01-20 10:03     ` Sergey Senozhatsky
  2014-01-21  0:09       ` Minchan Kim
  1 sibling, 1 reply; 11+ messages in thread
From: Sergey Senozhatsky @ 2014-01-20 10:03 UTC (permalink / raw)
  To: Minchan Kim; +Cc: Jerome Marchand, Nitin Gupta, linux-kernel

On (01/20/14 14:12), Minchan Kim wrote:
> Hello Sergey,
> 
> I reviewed this patchset and I suggest somethings.
> Please have a look and feedback to me. :)
> 
> 1. Let's define new file zram_comp.c
> 2. zram_comp includes following field
>    .create
>    .compress
>    .decompress.
>    .destroy
>    .name
> 

alternatively, we can use crypto api, the same way as zswap does (that
will require handling of cpu hotplug).

	-ss

> 1) create/destroy
> Will set up necessary things like allocating buffer, lock init or other things
> might happen in future when initialization time.
> I have a plan to support multiple buffer to do compression/decompression in
> parallel so we could optimize write VS write path, too.
> 
> 2) compress/decompress
> 
> It's very clear.
> 
> 3) name field will be used for tell to user what's kinds of compression
> algorithm zram support.
> 
> On Fri, Jan 17, 2014 at 02:04:16PM +0300, Sergey Senozhatsky wrote:
> > This is preparation patch to add LZ4 compression support.
> > 
> > struct zram_compress_ops defines common compress and decompress
> > prototypes. Use these ops->compress and ops->decompress callbacks
> > instead of direct LZO lzo1x_1_compress() and lzo1x_decompress_safe()
> > calls.
> > 
> > Compressor ops should be defined before zram meta allocation,
> > because the size of meta->compress_workmem depends on selected
> > compression algorithm.
> > 
> > Define LZO compressor ops and set it as the only one available
> > zram compressor at the moment.
> > 
> > Signed-off-by: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
> > ---
> >  drivers/block/zram/zram_drv.c | 20 +++++++++++++-------
> >  drivers/block/zram/zram_drv.h | 10 ++++++++++
> >  2 files changed, 23 insertions(+), 7 deletions(-)
> > 
> > diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
> > index 7124042..4f2c748 100644
> > --- a/drivers/block/zram/zram_drv.c
> > +++ b/drivers/block/zram/zram_drv.c
> > @@ -28,10 +28,9 @@
> >  #include <linux/device.h>
> >  #include <linux/genhd.h>
> >  #include <linux/highmem.h>
> > -#include <linux/slab.h>
> > -#include <linux/lzo.h>
> >  #include <linux/string.h>
> >  #include <linux/vmalloc.h>
> > +#include <linux/lzo.h>
> 
> Let's include zram_comps.h only and zram_comps.h includes other compression
> alrogithms header. If user don't want to support some compression
> alrogithm, it shouldn't be included.
> Of course, user can select kinds of compressor in configuration step.
> 
> >  
> >  #include "zram_drv.h"
> >  
> > @@ -42,6 +41,12 @@ static struct zram *zram_devices;
> >  /* Module params (documentation at end) */
> >  static unsigned int num_devices = 1;
> >  
> > +static struct zram_compress_ops lzo_compressor = {
> > +	.workmem_sz = LZO1X_MEM_COMPRESS,
> 
> workmem_sz should be part of compressor internal.
> 
> > +	.compress = lzo1x_1_compress,
> > +	.decompress = lzo1x_decompress_safe,
> > +};
> > +
> >  #define ZRAM_ATTR_RO(name)						\
> >  static ssize_t zram_attr_##name##_show(struct device *d,		\
> >  				struct device_attribute *attr, char *b)	\
> > @@ -166,14 +171,14 @@ static void zram_meta_free(struct zram_meta *meta)
> >  	kfree(meta);
> >  }
> >  
> > -static struct zram_meta *zram_meta_alloc(u64 disksize)
> > +static struct zram_meta *zram_meta_alloc(int workmem_sz, u64 disksize)
> >  {
> >  	size_t num_pages;
> >  	struct zram_meta *meta = kmalloc(sizeof(*meta), GFP_KERNEL);
> >  	if (!meta)
> >  		goto out;
> >  
> > -	meta->compress_workmem = kzalloc(LZO1X_MEM_COMPRESS, GFP_KERNEL);
> > +	meta->compress_workmem = kzalloc(workmem_sz, GFP_KERNEL);
> 
> Instead of exposing compression internal stuff, let's call comp->create.
> 
> >  	if (!meta->compress_workmem)
> >  		goto free_meta;
> >  
> > @@ -301,7 +306,7 @@ static int zram_decompress_page(struct zram *zram, char *mem, u32 index)
> >  	if (size == PAGE_SIZE)
> >  		copy_page(mem, cmem);
> >  	else
> > -		ret = lzo1x_decompress_safe(cmem, size,	mem, &clen);
> > +		ret = zram->ops->decompress(cmem, size, mem, &clen);
> >  	zs_unmap_object(meta->mem_pool, handle);
> >  	read_unlock(&meta->tb_lock);
> >  
> > @@ -420,7 +425,7 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index,
> >  		goto out;
> >  	}
> >  
> > -	ret = lzo1x_1_compress(uncmem, PAGE_SIZE, src, &clen,
> > +	ret = zram->ops->compress(uncmem, PAGE_SIZE, src, &clen,
> >  			       meta->compress_workmem);
> 
> Ditto. compress_workmem should be part of compressor itself.
> 
> 
> >  	if (!is_partial_io(bvec)) {
> >  		kunmap_atomic(user_mem);
> > @@ -551,7 +556,7 @@ static ssize_t disksize_store(struct device *dev,
> >  	}
> >  
> >  	disksize = PAGE_ALIGN(disksize);
> > -	zram->meta = zram_meta_alloc(disksize);
> > +	zram->meta = zram_meta_alloc(zram->ops->workmem_sz, disksize);
> 
> So, we don't need zram->ops->workmem_sz.
> 
> >  
> >  	zram->disksize = disksize;
> >  	set_capacity(zram->disk, zram->disksize >> SECTOR_SHIFT);
> > @@ -785,6 +790,7 @@ static int create_device(struct zram *zram, int device_id)
> >  		goto out_free_disk;
> >  	}
> >  
> > +	zram->ops = &lzo_compressor;
> 
> Let's define choose_compressor function with some argument
> so the result is following as
> 
> zram->comp = choose_compressor("lzo");
> 
> >  	zram->meta = NULL;
> >  	return 0;
> >  
> > diff --git a/drivers/block/zram/zram_drv.h b/drivers/block/zram/zram_drv.h
> > index 1d5b1f5..5488682 100644
> > --- a/drivers/block/zram/zram_drv.h
> > +++ b/drivers/block/zram/zram_drv.h
> > @@ -88,8 +88,18 @@ struct zram_meta {
> >  	struct mutex buffer_lock; /* protect compress buffers */
> >  };
> >  
> > +/* compression/decompression functions and algorithm-specific workmem size */
> > +struct zram_compress_ops {
> > +	int (*compress)(const unsigned char *src, size_t src_len,
> > +			unsigned char *dst, size_t *dst_len, void *wrkmem);
> > +	int (*decompress)(const unsigned char *src, size_t src_len,
> > +			unsigned char *dst, size_t *dst_len);
> > +	long workmem_sz;
> > +};
> > +
> >  struct zram {
> >  	struct zram_meta *meta;
> > +	struct zram_compress_ops *ops;
> >  	struct request_queue *queue;
> >  	struct gendisk *disk;
> >  	/* Prevent concurrent execution of device init, reset and R/W request */
> > -- 
> > 1.8.5.3.493.gb139ac2
> > 
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> > the body of a message to majordomo@vger.kernel.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> > Please read the FAQ at  http://www.tux.org/lkml/
> 
> -- 
> Kind regards,
> Minchan Kim
> 

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

* Re: [RFC PATCH 2/3] zram: introduce zram compressor operations struct
  2014-01-20 10:03     ` Sergey Senozhatsky
@ 2014-01-21  0:09       ` Minchan Kim
  2014-01-21  8:47         ` Sergey Senozhatsky
  0 siblings, 1 reply; 11+ messages in thread
From: Minchan Kim @ 2014-01-21  0:09 UTC (permalink / raw)
  To: Sergey Senozhatsky; +Cc: Jerome Marchand, Nitin Gupta, linux-kernel

On Mon, Jan 20, 2014 at 01:03:48PM +0300, Sergey Senozhatsky wrote:
> On (01/20/14 14:12), Minchan Kim wrote:
> > Hello Sergey,
> > 
> > I reviewed this patchset and I suggest somethings.
> > Please have a look and feedback to me. :)
> > 
> > 1. Let's define new file zram_comp.c
> > 2. zram_comp includes following field
> >    .create
> >    .compress
> >    .decompress.
> >    .destroy
> >    .name
> > 
> 
> alternatively, we can use crypto api, the same way as zswap does (that
> will require handling of cpu hotplug).
> 
> 	-ss

I really doubt what's the benefit from crypto API for zram.
It's maybe since I'm not familiar with it so I should ask a silly
question.

1. What's the runtime overhead for using such frontend?

   As you know, zram is in-memory block device so I don't want to
   add unnecessary overhead to optimize.

2. What's the memory footprint for using such frontend?

   As you know, zram is very popular for small-memory embedded device
   so I don't want to consume more runtime memory and static memory
   due to CONFIG_CRYPTO friend.

3. Is it a flexible to alloc/handle multiple compressor buffer for
   the our purpose? zswap and zcache have been used it with per-cpu
   buffer but it would a problem for write scalabitliy if we uses zlib
   which takes long time to compress.
   When I read code, maybe we can allocate multiple buffers through
   cryptop_alloc_compo several time but it would cause 1) and 2) problem
   again.
   
So, what's the attractive point for using crypto?
One of thing I could imagine is that it could make zram H/W compressor
but I don't have heard about it so if we don't have any special reason,
I'd like to go with raw compressor so we can get a *base* number. Then,
if we really need crypto API, we can change it easily and benchmark.
Finally, we could get a comparision number in future and it would make
the decision easily.

Thanks.

-- 
Kind regards,
Minchan Kim

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

* Re: [RFC PATCH 2/3] zram: introduce zram compressor operations struct
  2014-01-21  0:09       ` Minchan Kim
@ 2014-01-21  8:47         ` Sergey Senozhatsky
  0 siblings, 0 replies; 11+ messages in thread
From: Sergey Senozhatsky @ 2014-01-21  8:47 UTC (permalink / raw)
  To: Minchan Kim; +Cc: Jerome Marchand, Nitin Gupta, linux-kernel

On (01/21/14 09:09), Minchan Kim wrote:
> On Mon, Jan 20, 2014 at 01:03:48PM +0300, Sergey Senozhatsky wrote:
> > On (01/20/14 14:12), Minchan Kim wrote:
> > > Hello Sergey,
> > > 
> > > I reviewed this patchset and I suggest somethings.
> > > Please have a look and feedback to me. :)
> > > 
> > > 1. Let's define new file zram_comp.c
> > > 2. zram_comp includes following field
> > >    .create
> > >    .compress
> > >    .decompress.
> > >    .destroy
> > >    .name
> > > 
> > 
> > alternatively, we can use crypto api, the same way as zswap does (that
> > will require handling of cpu hotplug).
> > 
> > 	-ss
> 
> I really doubt what's the benefit from crypto API for zram.
> It's maybe since I'm not familiar with it so I should ask a silly
> question.
> 
> 1. What's the runtime overhead for using such frontend?
> 
>    As you know, zram is in-memory block device so I don't want to
>    add unnecessary overhead to optimize.
> 
> 2. What's the memory footprint for using such frontend?
> 
>    As you know, zram is very popular for small-memory embedded device
>    so I don't want to consume more runtime memory and static memory
>    due to CONFIG_CRYPTO friend.
> 

schematically:

char *compressor = "lzo"; /* or supplied by user via COMPRESSOR_store() */

if (crypto_has_comp(compressor, 0, 0)) {
	tfms = alloc_percpu(struct crypto_comp *);
	tfm = crypto_alloc_comp(compressor, 0, 0);
	*per_cpu_ptr(tfms, cpu) = tfm;
}

	ret = crypto_comp_compress(tfm, src, slen, dst, dlen);
and
	ret = crypto_comp_decompress(tfm, src, slen, dst, dlen);


memory overhead looks like a bunch of structures (transformation
contexts -- tfm). they touch tfm within compress/decompress, so crypto
users usually allocate per cpu tfm or somehow protect parallel tfm
usage, which is a big disadvantage to my opinion. otoh, crypto provides
HC compressors (LZ4HC at the moment).

my choice is to use raw compressor (as I did in initial patchset).

	-ss

> 3. Is it a flexible to alloc/handle multiple compressor buffer for
>    the our purpose? zswap and zcache have been used it with per-cpu
>    buffer but it would a problem for write scalabitliy if we uses zlib
>    which takes long time to compress.
>    When I read code, maybe we can allocate multiple buffers through
>    cryptop_alloc_compo several time but it would cause 1) and 2) problem
>    again.
>    
> So, what's the attractive point for using crypto?
> One of thing I could imagine is that it could make zram H/W compressor
> but I don't have heard about it so if we don't have any special reason,
> I'd like to go with raw compressor so we can get a *base* number. Then,
> if we really need crypto API, we can change it easily and benchmark.
> Finally, we could get a comparision number in future and it would make
> the decision easily.
> 
> Thanks.
> 
> -- 
> Kind regards,
> Minchan Kim
> 

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

end of thread, other threads:[~2014-01-21  8:50 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-01-17 11:04 [RFC PATCH 0/3] add LZ4 compression support Sergey Senozhatsky
2014-01-17 11:04 ` [RFC PATCH 1/3] zram: delete zram_init_device() function Sergey Senozhatsky
2014-01-20  4:43   ` Minchan Kim
2014-01-17 11:04 ` [RFC PATCH 2/3] zram: introduce zram compressor operations struct Sergey Senozhatsky
2014-01-20  5:12   ` Minchan Kim
2014-01-20  8:39     ` Sergey Senozhatsky
2014-01-20 10:03     ` Sergey Senozhatsky
2014-01-21  0:09       ` Minchan Kim
2014-01-21  8:47         ` Sergey Senozhatsky
2014-01-17 11:04 ` [RFC PATCH 3/3] zram: list and select compression algorithms Sergey Senozhatsky
2014-01-20  5:18   ` Minchan Kim

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.