Эх сурвалжийг харах

zram: make compression algorithm selection possible

Add and document `comp_algorithm' device attribute.  This attribute allows
to show supported compression and currently selected compression
algorithms:

	cat /sys/block/zram0/comp_algorithm
	[lzo] lz4

and change selected compression algorithm:
	echo lzo > /sys/block/zram0/comp_algorithm

Signed-off-by: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
Acked-by: Minchan Kim <minchan@kernel.org>
Cc: Jerome Marchand <jmarchan@redhat.com>
Cc: Nitin Gupta <ngupta@vflare.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Sergey Senozhatsky 11 жил өмнө
parent
commit
e46b8a030d

+ 8 - 0
Documentation/ABI/testing/sysfs-block-zram

@@ -65,6 +65,14 @@ Description:
 		number of backend's zcomp_strm compression streams (number of
 		number of backend's zcomp_strm compression streams (number of
 		concurrent compress operations).
 		concurrent compress operations).
 
 
+What:		/sys/block/zram<id>/comp_algorithm
+Date:		February 2014
+Contact:	Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
+Description:
+		The comp_algorithm file is read-write and lets to show
+		available and selected compression algorithms, change
+		compression algorithm selection.
+
 What:		/sys/block/zram<id>/notify_free
 What:		/sys/block/zram<id>/notify_free
 Date:		August 2010
 Date:		August 2010
 Contact:	Nitin Gupta <ngupta@vflare.org>
 Contact:	Nitin Gupta <ngupta@vflare.org>

+ 19 - 5
Documentation/blockdev/zram.txt

@@ -42,7 +42,21 @@ will not take any effect, because single stream compression backend implemented
 as a special case and does not support dynamic max_comp_streams. Only multi
 as a special case and does not support dynamic max_comp_streams. Only multi
 stream backend supports dynamic max_comp_streams adjustment.
 stream backend supports dynamic max_comp_streams adjustment.
 
 
-3) Set Disksize
+3) Select compression algorithm
+	Using comp_algorithm device attribute one can see available and
+	currently selected (shown in square brackets) compression algortithms,
+	change selected compression algorithm (once the device is initialised
+	there is no way to change compression algorithm).
+
+	Examples:
+	#show supported compression algorithms
+	cat /sys/block/zram0/comp_algorithm
+	lzo [lz4]
+
+	#select lzo compression algorithm
+	echo lzo > /sys/block/zram0/comp_algorithm
+
+4) Set Disksize
         Set disk size by writing the value to sysfs node '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.
         The value can be either in bytes or you can use mem suffixes.
         Examples:
         Examples:
@@ -59,14 +73,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
 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.
 size of the disk when not in use so a huge zram is wasteful.
 
 
-4) Activate:
+5) Activate:
 	mkswap /dev/zram0
 	mkswap /dev/zram0
 	swapon /dev/zram0
 	swapon /dev/zram0
 
 
 	mkfs.ext4 /dev/zram1
 	mkfs.ext4 /dev/zram1
 	mount /dev/zram1 /tmp
 	mount /dev/zram1 /tmp
 
 
-5) Stats:
+6) Stats:
 	Per-device statistics are exported as various nodes under
 	Per-device statistics are exported as various nodes under
 	/sys/block/zram<id>/
 	/sys/block/zram<id>/
 		disksize
 		disksize
@@ -81,11 +95,11 @@ size of the disk when not in use so a huge zram is wasteful.
 		compr_data_size
 		compr_data_size
 		mem_used_total
 		mem_used_total
 
 
-6) Deactivate:
+7) Deactivate:
 	swapoff /dev/zram0
 	swapoff /dev/zram0
 	umount /dev/zram1
 	umount /dev/zram1
 
 
-7) Reset:
+8) Reset:
 	Write any positive value to 'reset' sysfs node
 	Write any positive value to 'reset' sysfs node
 	echo 1 > /sys/block/zram0/reset
 	echo 1 > /sys/block/zram0/reset
 	echo 1 > /sys/block/zram1/reset
 	echo 1 > /sys/block/zram1/reset

+ 29 - 3
drivers/block/zram/zcomp.c

@@ -39,11 +39,20 @@ struct zcomp_strm_multi {
 	wait_queue_head_t strm_wait;
 	wait_queue_head_t strm_wait;
 };
 };
 
 
+static struct zcomp_backend *backends[] = {
+	&zcomp_lzo,
+	NULL
+};
+
 static struct zcomp_backend *find_backend(const char *compress)
 static struct zcomp_backend *find_backend(const char *compress)
 {
 {
-	if (strncmp(compress, "lzo", 3) == 0)
-		return &zcomp_lzo;
-	return NULL;
+	int i = 0;
+	while (backends[i]) {
+		if (sysfs_streq(compress, backends[i]->name))
+			break;
+		i++;
+	}
+	return backends[i];
 }
 }
 
 
 static void zcomp_strm_free(struct zcomp *comp, struct zcomp_strm *zstrm)
 static void zcomp_strm_free(struct zcomp *comp, struct zcomp_strm *zstrm)
@@ -251,6 +260,23 @@ static int zcomp_strm_single_create(struct zcomp *comp)
 	return 0;
 	return 0;
 }
 }
 
 
+/* show available compressors */
+ssize_t zcomp_available_show(const char *comp, char *buf)
+{
+	ssize_t sz = 0;
+	int i = 0;
+
+	while (backends[i]) {
+		if (sysfs_streq(comp, backends[i]->name))
+			sz += sprintf(buf + sz, "[%s] ", backends[i]->name);
+		else
+			sz += sprintf(buf + sz, "%s ", backends[i]->name);
+		i++;
+	}
+	sz += sprintf(buf + sz, "\n");
+	return sz;
+}
+
 int zcomp_set_max_streams(struct zcomp *comp, int num_strm)
 int zcomp_set_max_streams(struct zcomp *comp, int num_strm)
 {
 {
 	return comp->set_max_streams(comp, num_strm);
 	return comp->set_max_streams(comp, num_strm);

+ 2 - 0
drivers/block/zram/zcomp.h

@@ -50,6 +50,8 @@ struct zcomp {
 	void (*destroy)(struct zcomp *comp);
 	void (*destroy)(struct zcomp *comp);
 };
 };
 
 
+ssize_t zcomp_available_show(const char *comp, char *buf);
+
 struct zcomp *zcomp_create(const char *comp, int max_strm);
 struct zcomp *zcomp_create(const char *comp, int max_strm);
 void zcomp_destroy(struct zcomp *comp);
 void zcomp_destroy(struct zcomp *comp);
 
 

+ 34 - 3
drivers/block/zram/zram_drv.c

@@ -141,6 +141,34 @@ static ssize_t max_comp_streams_store(struct device *dev,
 	return len;
 	return len;
 }
 }
 
 
+static ssize_t comp_algorithm_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	size_t sz;
+	struct zram *zram = dev_to_zram(dev);
+
+	down_read(&zram->init_lock);
+	sz = zcomp_available_show(zram->compressor, buf);
+	up_read(&zram->init_lock);
+
+	return sz;
+}
+
+static ssize_t comp_algorithm_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("Can't change algorithm for initialized device\n");
+		return -EBUSY;
+	}
+	strlcpy(zram->compressor, buf, sizeof(zram->compressor));
+	up_write(&zram->init_lock);
+	return len;
+}
+
 /* flag operations needs meta->tb_lock */
 /* flag operations needs meta->tb_lock */
 static int zram_test_flag(struct zram_meta *meta, u32 index,
 static int zram_test_flag(struct zram_meta *meta, u32 index,
 			enum zram_pageflags flag)
 			enum zram_pageflags flag)
@@ -572,10 +600,10 @@ static ssize_t disksize_store(struct device *dev,
 		goto out_free_meta;
 		goto out_free_meta;
 	}
 	}
 
 
-	zram->comp = zcomp_create(default_compressor, zram->max_comp_streams);
+	zram->comp = zcomp_create(zram->compressor, zram->max_comp_streams);
 	if (!zram->comp) {
 	if (!zram->comp) {
 		pr_info("Cannot initialise %s compressing backend\n",
 		pr_info("Cannot initialise %s compressing backend\n",
-				default_compressor);
+				zram->compressor);
 		err = -EINVAL;
 		err = -EINVAL;
 		goto out_free_meta;
 		goto out_free_meta;
 	}
 	}
@@ -735,6 +763,8 @@ 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(mem_used_total, S_IRUGO, mem_used_total_show, NULL);
 static DEVICE_ATTR(max_comp_streams, S_IRUGO | S_IWUSR,
 static DEVICE_ATTR(max_comp_streams, S_IRUGO | S_IWUSR,
 		max_comp_streams_show, max_comp_streams_store);
 		max_comp_streams_show, max_comp_streams_store);
+static DEVICE_ATTR(comp_algorithm, S_IRUGO | S_IWUSR,
+		comp_algorithm_show, comp_algorithm_store);
 
 
 ZRAM_ATTR_RO(num_reads);
 ZRAM_ATTR_RO(num_reads);
 ZRAM_ATTR_RO(num_writes);
 ZRAM_ATTR_RO(num_writes);
@@ -760,6 +790,7 @@ static struct attribute *zram_disk_attrs[] = {
 	&dev_attr_compr_data_size.attr,
 	&dev_attr_compr_data_size.attr,
 	&dev_attr_mem_used_total.attr,
 	&dev_attr_mem_used_total.attr,
 	&dev_attr_max_comp_streams.attr,
 	&dev_attr_max_comp_streams.attr,
+	&dev_attr_comp_algorithm.attr,
 	NULL,
 	NULL,
 };
 };
 
 
@@ -820,7 +851,7 @@ static int create_device(struct zram *zram, int device_id)
 		pr_warn("Error creating sysfs group");
 		pr_warn("Error creating sysfs group");
 		goto out_free_disk;
 		goto out_free_disk;
 	}
 	}
-
+	strlcpy(zram->compressor, default_compressor, sizeof(zram->compressor));
 	zram->meta = NULL;
 	zram->meta = NULL;
 	zram->max_comp_streams = 1;
 	zram->max_comp_streams = 1;
 	return 0;
 	return 0;

+ 1 - 0
drivers/block/zram/zram_drv.h

@@ -101,5 +101,6 @@ struct zram {
 	u64 disksize;	/* bytes */
 	u64 disksize;	/* bytes */
 	int max_comp_streams;
 	int max_comp_streams;
 	struct zram_stats stats;
 	struct zram_stats stats;
+	char compressor[10];
 };
 };
 #endif
 #endif