Skip to content

Commit 0dfcc58

Browse files
JoonsooKimDhineshCool
authored andcommitted
zram: make deduplication feature optional
Benefit of deduplication is dependent on the workload so it's not preferable to always enable. Therefore, make it optional in Kconfig and device param. Default is 'off'. This option will be beneficial for users who use the zram as blockdev and stores build output to it. Change-Id: If282bb8aa15c5749859a87cf36db7eb9edb3b1ed Reviewed-by: Sergey Senozhatsky <sergey.senozhatsky@gmail.com> Acked-by: Minchan Kim <minchan@kernel.org> Signed-off-by: Joonsoo Kim <iamjoonsoo.kim@lge.com> Link: https://lore.kernel.org/patchwork/patch/787164/ Patch-mainline: linux-kernel@ Thu, 11 May 2017 22:30:52 Signed-off-by: Charan Teja Reddy <charante@codeaurora.org> Signed-off-by: Marco Zanin <mrczn.bb@gmail.com> Signed-off-by: snnbyyds <snnbyyds@gmail.com>
1 parent 3343551 commit 0dfcc58

8 files changed

Lines changed: 149 additions & 13 deletions

File tree

Documentation/ABI/testing/sysfs-block-zram

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,16 @@ Description:
107107
If system has mounted debugfs, user can see which slots
108108
are idle via /sys/kernel/debug/zram/zram<id>/block_state
109109

110+
What: /sys/block/zram<id>/use_dedup
111+
Date: March 2017
112+
Contact: Joonsoo Kim <iamjoonsoo.kim@lge.com>
113+
Description:
114+
The use_dedup file is read-write and specifies deduplication
115+
feature is used or not. If enabled, duplicated data is
116+
managed by reference count and will not be stored in memory
117+
twice. Benefit of this feature largely depends on the workload
118+
so keep attention when use.
119+
110120
What: /sys/block/zram<id>/writeback
111121
Date: November 2018
112122
Contact: Minchan Kim <minchan@kernel.org>

Documentation/blockdev/zram.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,8 @@ comp_algorithm RW show and change the compression algorithm
172172
compact WO trigger memory compaction
173173
debug_stat RO this file is used for zram debugging purposes
174174
backing_dev RW set up backend storage for zram to write out
175-
idle WO mark allocated slot as idle
175+
idle WO mark allocated slot as idle
176+
use_dedup RW show and set deduplication feature
176177

177178

178179
User space is advised to use the following files to read the device statistics.

drivers/block/zram/Kconfig

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,20 @@ config ZRAM
1414

1515
See Documentation/blockdev/zram.txt for more information.
1616

17+
config ZRAM_DEDUP
18+
bool "Deduplication support for ZRAM data"
19+
depends on ZRAM
20+
default n
21+
help
22+
Deduplicate ZRAM data to reduce amount of memory consumption.
23+
Advantage largely depends on the workload. In some cases, this
24+
option reduces memory usage to the half. However, if there is no
25+
duplicated data, the amount of memory consumption would be
26+
increased due to additional metadata usage. And, there is
27+
computation time trade-off. Please check the benefit before
28+
enabling this option. Experiment shows the positive effect when
29+
the zram is used as blockdev and is used to store build output.
30+
1731
config ZRAM_WRITEBACK
1832
bool "Write back incompressible or idle page to backing device"
1933
depends on ZRAM

drivers/block/zram/Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1-
zram-y := zcomp.o zram_drv.o zram_dedup.o
1+
zram-y := zcomp.o zram_drv.o
2+
zram-$(CONFIG_ZRAM_DEDUP) += zram_dedup.o
23

34
obj-$(CONFIG_ZRAM) += zram.o

drivers/block/zram/zram_dedup.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ void zram_dedup_insert(struct zram *zram, struct zram_entry *new,
4141
struct rb_node **rb_node, *parent = NULL;
4242
struct zram_entry *entry;
4343

44+
if (!zram_dedup_enabled(zram))
45+
return;
46+
4447
new->checksum = checksum;
4548
hash = &zram->hash[checksum % zram->hash_size];
4649
rb_root = &hash->rb_root;
@@ -148,6 +151,9 @@ struct zram_entry *zram_dedup_find(struct zram *zram, struct page *page,
148151
void *mem;
149152
struct zram_entry *entry;
150153

154+
if (!zram_dedup_enabled(zram))
155+
return NULL;
156+
151157
mem = kmap_atomic(page);
152158
*checksum = zram_dedup_checksum(mem);
153159

@@ -160,13 +166,19 @@ struct zram_entry *zram_dedup_find(struct zram *zram, struct page *page,
160166
void zram_dedup_init_entry(struct zram *zram, struct zram_entry *entry,
161167
unsigned long handle, unsigned int len)
162168
{
169+
if (!zram_dedup_enabled(zram))
170+
return;
171+
163172
entry->handle = handle;
164173
entry->refcount = 1;
165174
entry->len = len;
166175
}
167176

168177
bool zram_dedup_put_entry(struct zram *zram, struct zram_entry *entry)
169178
{
179+
if (!zram_dedup_enabled(zram))
180+
return true;
181+
170182
if (zram_dedup_put(zram, entry))
171183
return false;
172184

@@ -178,6 +190,9 @@ int zram_dedup_init(struct zram *zram, size_t num_pages)
178190
int i;
179191
struct zram_hash *hash;
180192

193+
if (!zram_dedup_enabled(zram))
194+
return 0;
195+
181196
zram->hash_size = num_pages >> ZRAM_HASH_SHIFT;
182197
zram->hash_size = min_t(size_t, ZRAM_HASH_SIZE_MAX, zram->hash_size);
183198
zram->hash_size = max_t(size_t, ZRAM_HASH_SIZE_MIN, zram->hash_size);

drivers/block/zram/zram_dedup.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
struct zram;
55
struct zram_entry;
66

7+
#ifdef CONFIG_ZRAM_DEDUP
8+
79
u64 zram_dedup_dup_size(struct zram *zram);
810
u64 zram_dedup_meta_size(struct zram *zram);
911

@@ -18,5 +20,26 @@ bool zram_dedup_put_entry(struct zram *zram, struct zram_entry *entry);
1820

1921
int zram_dedup_init(struct zram *zram, size_t num_pages);
2022
void zram_dedup_fini(struct zram *zram);
23+
#else
24+
25+
static inline u64 zram_dedup_dup_size(struct zram *zram) { return 0; }
26+
static inline u64 zram_dedup_meta_size(struct zram *zram) { return 0; }
27+
28+
static inline void zram_dedup_insert(struct zram *zram, struct zram_entry *new,
29+
u32 checksum) { }
30+
static inline struct zram_entry *zram_dedup_find(struct zram *zram,
31+
struct page *page, u32 *checksum) { return NULL; }
32+
33+
static inline void zram_dedup_init_entry(struct zram *zram,
34+
struct zram_entry *entry, unsigned long handle,
35+
unsigned int len) { }
36+
static inline bool zram_dedup_put_entry(struct zram *zram,
37+
struct zram_entry *entry) { return true; }
38+
39+
static inline int zram_dedup_init(struct zram *zram,
40+
size_t num_pages) { return 0; }
41+
static inline void zram_dedup_fini(struct zram *zram) { }
42+
43+
#endif
2144

2245
#endif /* _ZRAM_DEDUP_H_ */

drivers/block/zram/zram_drv.c

Lines changed: 72 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1028,6 +1028,41 @@ static ssize_t comp_algorithm_store(struct device *dev,
10281028
return len;
10291029
}
10301030

1031+
static ssize_t use_dedup_show(struct device *dev,
1032+
struct device_attribute *attr, char *buf)
1033+
{
1034+
bool val;
1035+
struct zram *zram = dev_to_zram(dev);
1036+
1037+
down_read(&zram->init_lock);
1038+
val = zram->use_dedup;
1039+
up_read(&zram->init_lock);
1040+
1041+
return scnprintf(buf, PAGE_SIZE, "%d\n", (int)val);
1042+
}
1043+
1044+
#ifdef CONFIG_ZRAM_DEDUP
1045+
static ssize_t use_dedup_store(struct device *dev,
1046+
struct device_attribute *attr, const char *buf, size_t len)
1047+
{
1048+
int val;
1049+
struct zram *zram = dev_to_zram(dev);
1050+
1051+
if (kstrtoint(buf, 10, &val) || (val != 0 && val != 1))
1052+
return -EINVAL;
1053+
1054+
down_write(&zram->init_lock);
1055+
if (init_done(zram)) {
1056+
up_write(&zram->init_lock);
1057+
pr_info("Can't change dedup usage for initialized device\n");
1058+
return -EBUSY;
1059+
}
1060+
zram->use_dedup = val;
1061+
up_write(&zram->init_lock);
1062+
return len;
1063+
}
1064+
#endif
1065+
10311066
static ssize_t compact_store(struct device *dev,
10321067
struct device_attribute *attr, const char *buf, size_t len)
10331068
{
@@ -1145,21 +1180,35 @@ static DEVICE_ATTR_RO(bd_stat);
11451180
#endif
11461181
static DEVICE_ATTR_RO(debug_stat);
11471182

1183+
static unsigned long zram_entry_handle(struct zram *zram,
1184+
struct zram_entry *entry)
1185+
{
1186+
if (zram_dedup_enabled(zram))
1187+
return entry->handle;
1188+
else
1189+
return (unsigned long)entry;
1190+
}
1191+
1192+
11481193

11491194
static struct zram_entry *zram_entry_alloc(struct zram *zram,
11501195
unsigned int len, gfp_t flags)
11511196
{
11521197
struct zram_entry *entry;
11531198
unsigned long handle;
11541199

1155-
entry = kzalloc(sizeof(*entry),
1156-
flags & ~(__GFP_HIGHMEM|__GFP_MOVABLE|__GFP_CMA));
1157-
if (!entry)
1200+
handle = zs_malloc(zram->mem_pool, len, flags);
1201+
if (!handle)
1202+
11581203
return NULL;
11591204

1160-
handle = zs_malloc(zram->mem_pool, len, flags);
1161-
if (!handle) {
1162-
kfree(entry);
1205+
if (!zram_dedup_enabled(zram))
1206+
return (struct zram_entry *)handle;
1207+
1208+
entry = kzalloc(sizeof(*entry),
1209+
flags & ~(__GFP_HIGHMEM|__GFP_MOVABLE|__GFP_CMA));
1210+
if (!entry) {
1211+
zs_free(zram->mem_pool, handle);
11631212
return NULL;
11641213
}
11651214

@@ -1175,7 +1224,11 @@ void zram_entry_free(struct zram *zram, struct zram_entry *entry)
11751224
if (!zram_dedup_put_entry(zram, entry))
11761225
return;
11771226

1178-
zs_free(zram->mem_pool, entry->handle);
1227+
zs_free(zram->mem_pool, zram_entry_handle(zram, entry));
1228+
1229+
if (!zram_dedup_enabled(zram))
1230+
return;
1231+
11791232
kfree(entry);
11801233

11811234
atomic64_sub(sizeof(*entry), &zram->stats.meta_data_size);
@@ -1314,7 +1367,8 @@ static int __zram_bvec_read(struct zram *zram, struct page *page, u32 index,
13141367

13151368
size = zram_get_obj_size(zram, index);
13161369

1317-
src = zs_map_object(zram->mem_pool, entry->handle, ZS_MM_RO);
1370+
src = zs_map_object(zram->mem_pool,
1371+
zram_entry_handle(zram, entry), ZS_MM_RO);
13181372
if (size == PAGE_SIZE) {
13191373
dst = kmap_atomic(page);
13201374
memcpy(dst, src, PAGE_SIZE);
@@ -1328,7 +1382,7 @@ static int __zram_bvec_read(struct zram *zram, struct page *page, u32 index,
13281382
kunmap_atomic(dst);
13291383
zcomp_stream_put(zram->comp);
13301384
}
1331-
zs_unmap_object(zram->mem_pool, entry->handle);
1385+
zs_unmap_object(zram->mem_pool, zram_entry_handle(zram, entry));
13321386
zram_slot_unlock(zram, index);
13331387

13341388
/* Should NEVER happen. Return bio error if it does. */
@@ -1456,7 +1510,8 @@ static int __zram_bvec_write(struct zram *zram, struct bio_vec *bvec,
14561510
return -ENOMEM;
14571511
}
14581512

1459-
dst = zs_map_object(zram->mem_pool, entry->handle, ZS_MM_WO);
1513+
dst = zs_map_object(zram->mem_pool,
1514+
zram_entry_handle(zram, entry), ZS_MM_WO);
14601515

14611516
src = zstrm->buffer;
14621517
if (comp_len == PAGE_SIZE)
@@ -1466,7 +1521,7 @@ static int __zram_bvec_write(struct zram *zram, struct bio_vec *bvec,
14661521
kunmap_atomic(src);
14671522

14681523
zcomp_stream_put(zram->comp);
1469-
zs_unmap_object(zram->mem_pool, entry->handle);
1524+
zs_unmap_object(zram->mem_pool, zram_entry_handle(zram, entry));
14701525
atomic64_add(comp_len, &zram->stats.compr_data_size);
14711526
zram_dedup_insert(zram, entry, checksum);
14721527
out:
@@ -1904,6 +1959,11 @@ static DEVICE_ATTR_WO(writeback);
19041959
static DEVICE_ATTR_RW(writeback_limit);
19051960
static DEVICE_ATTR_RW(writeback_limit_enable);
19061961
#endif
1962+
#ifdef CONFIG_ZRAM_DEDUP
1963+
static DEVICE_ATTR_RW(use_dedup);
1964+
#else
1965+
static DEVICE_ATTR_RO(use_dedup);
1966+
#endif
19071967

19081968
static struct attribute *zram_disk_attrs[] = {
19091969
&dev_attr_disksize.attr,
@@ -1921,6 +1981,7 @@ static struct attribute *zram_disk_attrs[] = {
19211981
&dev_attr_writeback_limit.attr,
19221982
&dev_attr_writeback_limit_enable.attr,
19231983
#endif
1984+
&dev_attr_use_dedup.attr,
19241985
&dev_attr_io_stat.attr,
19251986
&dev_attr_mm_stat.attr,
19261987
#ifdef CONFIG_ZRAM_WRITEBACK

drivers/block/zram/zram_drv.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,8 @@ struct zram {
135135
* zram is claimed so open request will be failed
136136
*/
137137
bool claim; /* Protected by bdev->bd_mutex */
138+
bool use_dedup;
139+
138140
struct file *backing_dev;
139141
#ifdef CONFIG_ZRAM_WRITEBACK
140142
spinlock_t wb_limit_lock;
@@ -150,5 +152,14 @@ struct zram {
150152
#endif
151153
};
152154

155+
static inline bool zram_dedup_enabled(struct zram *zram)
156+
{
157+
#ifdef CONFIG_ZRAM_DEDUP
158+
return zram->use_dedup;
159+
#else
160+
return false;
161+
#endif
162+
}
163+
153164
void zram_entry_free(struct zram *zram, struct zram_entry *entry);
154165
#endif

0 commit comments

Comments
 (0)