zram: make compression algorithm selection possible
authorSergey Senozhatsky <sergey.senozhatsky@gmail.com>
Mon, 7 Apr 2014 22:38:17 +0000 (15:38 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 7 Apr 2014 23:36:01 +0000 (16:36 -0700)
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>
Documentation/ABI/testing/sysfs-block-zram
Documentation/blockdev/zram.txt
drivers/block/zram/zcomp.c
drivers/block/zram/zcomp.h
drivers/block/zram/zram_drv.c
drivers/block/zram/zram_drv.h

index 0da9ed6b82ea91320926ce5e17f9777f185f84af..70ec992514d03e91e7f5b1644929c5e195ff8d13 100644 (file)
@@ -65,6 +65,14 @@ Description:
                number of backend's zcomp_strm compression streams (number of
                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
 Date:          August 2010
 Contact:       Nitin Gupta <ngupta@vflare.org>
index aadfe60391b74643150b9a911f9fde8da8746abe..2604ffed51db8b4e024685756e50eea030d42209 100644 (file)
@@ -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
 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'.
         The value can be either in bytes or you can use mem suffixes.
         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
 size of the disk when not in use so a huge zram is wasteful.
 
-4) Activate:
+5) Activate:
        mkswap /dev/zram0
        swapon /dev/zram0
 
        mkfs.ext4 /dev/zram1
        mount /dev/zram1 /tmp
 
-5) Stats:
+6) Stats:
        Per-device statistics are exported as various nodes under
        /sys/block/zram<id>/
                disksize
@@ -81,11 +95,11 @@ size of the disk when not in use so a huge zram is wasteful.
                compr_data_size
                mem_used_total
 
-6) Deactivate:
+7) Deactivate:
        swapoff /dev/zram0
        umount /dev/zram1
 
-7) Reset:
+8) Reset:
        Write any positive value to 'reset' sysfs node
        echo 1 > /sys/block/zram0/reset
        echo 1 > /sys/block/zram1/reset
index ac276f79f21ce3ff44b7b619b91dd7423479f4eb..aad533a8bc55661471d6742b0aa68f10b00d9b41 100644 (file)
@@ -39,11 +39,20 @@ struct zcomp_strm_multi {
        wait_queue_head_t strm_wait;
 };
 
+static struct zcomp_backend *backends[] = {
+       &zcomp_lzo,
+       NULL
+};
+
 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)
@@ -251,6 +260,23 @@ static int zcomp_strm_single_create(struct zcomp *comp)
        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)
 {
        return comp->set_max_streams(comp, num_strm);
index bd11d59c5dd161dfdd4bc69fb23b5dcd806836c8..8b8997f8613bd2d790c3eb26819b00bc10951e21 100644 (file)
@@ -50,6 +50,8 @@ struct zcomp {
        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);
 void zcomp_destroy(struct zcomp *comp);
 
index 3a5f24c341dc8f552f6da5233d291a9bf65d2a2a..15d46f2e158c891360ac8bc3983091022038328b 100644 (file)
@@ -141,6 +141,34 @@ static ssize_t max_comp_streams_store(struct device *dev,
        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 */
 static int zram_test_flag(struct zram_meta *meta, u32 index,
                        enum zram_pageflags flag)
@@ -572,10 +600,10 @@ static ssize_t disksize_store(struct device *dev,
                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) {
                pr_info("Cannot initialise %s compressing backend\n",
-                               default_compressor);
+                               zram->compressor);
                err = -EINVAL;
                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(max_comp_streams, S_IRUGO | S_IWUSR,
                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_writes);
@@ -760,6 +790,7 @@ static struct attribute *zram_disk_attrs[] = {
        &dev_attr_compr_data_size.attr,
        &dev_attr_mem_used_total.attr,
        &dev_attr_max_comp_streams.attr,
+       &dev_attr_comp_algorithm.attr,
        NULL,
 };
 
@@ -820,7 +851,7 @@ static int create_device(struct zram *zram, int device_id)
                pr_warn("Error creating sysfs group");
                goto out_free_disk;
        }
-
+       strlcpy(zram->compressor, default_compressor, sizeof(zram->compressor));
        zram->meta = NULL;
        zram->max_comp_streams = 1;
        return 0;
index ccf36d11755ae751036904290bc07b913088dbf4..7f21c145e317f49e785eafeb1aea78097109e158 100644 (file)
@@ -101,5 +101,6 @@ struct zram {
        u64 disksize;   /* bytes */
        int max_comp_streams;
        struct zram_stats stats;
+       char compressor[10];
 };
 #endif