summaryrefslogtreecommitdiffstats
path: root/drivers/block/zram
diff options
context:
space:
mode:
authorMinchan Kim <minchan@kernel.org>2018-12-28 03:36:54 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2018-12-28 15:11:49 -0500
commitbb416d18b850faaa44bd3bb67c9728922c3cce98 (patch)
tree112f74c2842e9e2565911546cb0ff69c407ad393 /drivers/block/zram
parent23eddf39b2c28c05cb8f8203d38e61807d701b38 (diff)
zram: writeback throttle
If there are lots of write IO with flash device, it could have a wearout problem of storage. To overcome the problem, admin needs to design write limitation to guarantee flash health for entire product life. This patch creates a new knob "writeback_limit" for zram. writeback_limit's default value is 0 so that it doesn't limit any writeback. If admin want to measure writeback count in a certain period, he could know it via /sys/block/zram0/bd_stat's 3rd column. If admin want to limit writeback as per-day 400M, he could do it like below. MB_SHIFT=20 4K_SHIFT=12 echo $((400<<MB_SHIFT>>4K_SHIFT)) > \ /sys/block/zram0/writeback_limit. If admin want to allow further write again, he could do it like below echo 0 > /sys/block/zram0/writeback_limit If admin want to see remaining writeback budget, cat /sys/block/zram0/writeback_limit The writeback_limit count will reset whenever you reset zram (e.g., system reboot, echo 1 > /sys/block/zramX/reset) so keeping how many of writeback happened until you reset the zram to allocate extra writeback budget in next setting is user's job. [minchan@kernel.org: v4] Link: http://lkml.kernel.org/r/20181203024045.153534-8-minchan@kernel.org Link: http://lkml.kernel.org/r/20181127055429.251614-8-minchan@kernel.org Signed-off-by: Minchan Kim <minchan@kernel.org> Reviewed-by: Sergey Senozhatsky <sergey.senozhatsky@gmail.com> Cc: Joey Pabalinas <joeypabalinas@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/block/zram')
-rw-r--r--drivers/block/zram/zram_drv.c52
-rw-r--r--drivers/block/zram/zram_drv.h2
2 files changed, 51 insertions, 3 deletions
diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
index f1832fa3ba41..33c5cc879f24 100644
--- a/drivers/block/zram/zram_drv.c
+++ b/drivers/block/zram/zram_drv.c
@@ -330,6 +330,39 @@ next:
330} 330}
331 331
332#ifdef CONFIG_ZRAM_WRITEBACK 332#ifdef CONFIG_ZRAM_WRITEBACK
333static ssize_t writeback_limit_store(struct device *dev,
334 struct device_attribute *attr, const char *buf, size_t len)
335{
336 struct zram *zram = dev_to_zram(dev);
337 u64 val;
338 ssize_t ret = -EINVAL;
339
340 if (kstrtoull(buf, 10, &val))
341 return ret;
342
343 down_read(&zram->init_lock);
344 atomic64_set(&zram->stats.bd_wb_limit, val);
345 if (val == 0)
346 zram->stop_writeback = false;
347 up_read(&zram->init_lock);
348 ret = len;
349
350 return ret;
351}
352
353static ssize_t writeback_limit_show(struct device *dev,
354 struct device_attribute *attr, char *buf)
355{
356 u64 val;
357 struct zram *zram = dev_to_zram(dev);
358
359 down_read(&zram->init_lock);
360 val = atomic64_read(&zram->stats.bd_wb_limit);
361 up_read(&zram->init_lock);
362
363 return scnprintf(buf, PAGE_SIZE, "%llu\n", val);
364}
365
333static void reset_bdev(struct zram *zram) 366static void reset_bdev(struct zram *zram)
334{ 367{
335 struct block_device *bdev; 368 struct block_device *bdev;
@@ -612,6 +645,11 @@ static ssize_t writeback_store(struct device *dev,
612 bvec.bv_len = PAGE_SIZE; 645 bvec.bv_len = PAGE_SIZE;
613 bvec.bv_offset = 0; 646 bvec.bv_offset = 0;
614 647
648 if (zram->stop_writeback) {
649 ret = -EIO;
650 break;
651 }
652
615 if (!blk_idx) { 653 if (!blk_idx) {
616 blk_idx = alloc_block_bdev(zram); 654 blk_idx = alloc_block_bdev(zram);
617 if (!blk_idx) { 655 if (!blk_idx) {
@@ -694,6 +732,11 @@ static ssize_t writeback_store(struct device *dev,
694 zram_set_element(zram, index, blk_idx); 732 zram_set_element(zram, index, blk_idx);
695 blk_idx = 0; 733 blk_idx = 0;
696 atomic64_inc(&zram->stats.pages_stored); 734 atomic64_inc(&zram->stats.pages_stored);
735 if (atomic64_add_unless(&zram->stats.bd_wb_limit,
736 -1 << (PAGE_SHIFT - 12), 0)) {
737 if (atomic64_read(&zram->stats.bd_wb_limit) == 0)
738 zram->stop_writeback = true;
739 }
697next: 740next:
698 zram_slot_unlock(zram, index); 741 zram_slot_unlock(zram, index);
699 } 742 }
@@ -1018,6 +1061,7 @@ static ssize_t mm_stat_show(struct device *dev,
1018} 1061}
1019 1062
1020#ifdef CONFIG_ZRAM_WRITEBACK 1063#ifdef CONFIG_ZRAM_WRITEBACK
1064#define FOUR_K(x) ((x) * (1 << (PAGE_SHIFT - 12)))
1021static ssize_t bd_stat_show(struct device *dev, 1065static ssize_t bd_stat_show(struct device *dev,
1022 struct device_attribute *attr, char *buf) 1066 struct device_attribute *attr, char *buf)
1023{ 1067{
@@ -1027,9 +1071,9 @@ static ssize_t bd_stat_show(struct device *dev,
1027 down_read(&zram->init_lock); 1071 down_read(&zram->init_lock);
1028 ret = scnprintf(buf, PAGE_SIZE, 1072 ret = scnprintf(buf, PAGE_SIZE,
1029 "%8llu %8llu %8llu\n", 1073 "%8llu %8llu %8llu\n",
1030 (u64)atomic64_read(&zram->stats.bd_count) * (PAGE_SHIFT - 12), 1074 FOUR_K((u64)atomic64_read(&zram->stats.bd_count)),
1031 (u64)atomic64_read(&zram->stats.bd_reads) * (PAGE_SHIFT - 12), 1075 FOUR_K((u64)atomic64_read(&zram->stats.bd_reads)),
1032 (u64)atomic64_read(&zram->stats.bd_writes) * (PAGE_SHIFT - 12)); 1076 FOUR_K((u64)atomic64_read(&zram->stats.bd_writes)));
1033 up_read(&zram->init_lock); 1077 up_read(&zram->init_lock);
1034 1078
1035 return ret; 1079 return ret;
@@ -1767,6 +1811,7 @@ static DEVICE_ATTR_RW(comp_algorithm);
1767#ifdef CONFIG_ZRAM_WRITEBACK 1811#ifdef CONFIG_ZRAM_WRITEBACK
1768static DEVICE_ATTR_RW(backing_dev); 1812static DEVICE_ATTR_RW(backing_dev);
1769static DEVICE_ATTR_WO(writeback); 1813static DEVICE_ATTR_WO(writeback);
1814static DEVICE_ATTR_RW(writeback_limit);
1770#endif 1815#endif
1771 1816
1772static struct attribute *zram_disk_attrs[] = { 1817static struct attribute *zram_disk_attrs[] = {
@@ -1782,6 +1827,7 @@ static struct attribute *zram_disk_attrs[] = {
1782#ifdef CONFIG_ZRAM_WRITEBACK 1827#ifdef CONFIG_ZRAM_WRITEBACK
1783 &dev_attr_backing_dev.attr, 1828 &dev_attr_backing_dev.attr,
1784 &dev_attr_writeback.attr, 1829 &dev_attr_writeback.attr,
1830 &dev_attr_writeback_limit.attr,
1785#endif 1831#endif
1786 &dev_attr_io_stat.attr, 1832 &dev_attr_io_stat.attr,
1787 &dev_attr_mm_stat.attr, 1833 &dev_attr_mm_stat.attr,
diff --git a/drivers/block/zram/zram_drv.h b/drivers/block/zram/zram_drv.h
index bc477803530d..4bd3afd15e83 100644
--- a/drivers/block/zram/zram_drv.h
+++ b/drivers/block/zram/zram_drv.h
@@ -86,6 +86,7 @@ struct zram_stats {
86 atomic64_t bd_count; /* no. of pages in backing device */ 86 atomic64_t bd_count; /* no. of pages in backing device */
87 atomic64_t bd_reads; /* no. of reads from backing device */ 87 atomic64_t bd_reads; /* no. of reads from backing device */
88 atomic64_t bd_writes; /* no. of writes from backing device */ 88 atomic64_t bd_writes; /* no. of writes from backing device */
89 atomic64_t bd_wb_limit; /* writeback limit of backing device */
89#endif 90#endif
90}; 91};
91 92
@@ -113,6 +114,7 @@ struct zram {
113 */ 114 */
114 bool claim; /* Protected by bdev->bd_mutex */ 115 bool claim; /* Protected by bdev->bd_mutex */
115 struct file *backing_dev; 116 struct file *backing_dev;
117 bool stop_writeback;
116#ifdef CONFIG_ZRAM_WRITEBACK 118#ifdef CONFIG_ZRAM_WRITEBACK
117 struct block_device *bdev; 119 struct block_device *bdev;
118 unsigned int old_block_size; 120 unsigned int old_block_size;