Skip to content

Commit e82592c

Browse files
minchanktorvalds
authored andcommitted
zram: introduce ZRAM_IDLE flag
To support idle page writeback with upcoming patches, this patch introduces a new ZRAM_IDLE flag. Userspace can mark zram slots as "idle" via "echo all > /sys/block/zramX/idle" which marks every allocated zram slot as ZRAM_IDLE. User could see it by /sys/kernel/debug/zram/zram0/block_state. 300 75.033841 ...i 301 63.806904 s..i 302 63.806919 ..hi Once there is IO for the slot, the mark will be disappeared. 300 75.033841 ... 301 63.806904 s..i 302 63.806919 ..hi Therefore, 300th block is idle zpage. With this feature, user can how many zram has idle pages which are waste of memory. Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Minchan Kim <[email protected]> Reviewed-by: Sergey Senozhatsky <[email protected]> Reviewed-by: Joey Pabalinas <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent 7e52928 commit e82592c

File tree

4 files changed

+69
-7
lines changed

4 files changed

+69
-7
lines changed

Documentation/ABI/testing/sysfs-block-zram

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,3 +98,11 @@ Description:
9898
The backing_dev file is read-write and set up backing
9999
device for zram to write incompressible pages.
100100
For using, user should enable CONFIG_ZRAM_WRITEBACK.
101+
102+
What: /sys/block/zram<id>/idle
103+
Date: November 2018
104+
Contact: Minchan Kim <[email protected]>
105+
Description:
106+
idle file is write-only and mark zram slot as idle.
107+
If system has mounted debugfs, user can see which slots
108+
are idle via /sys/kernel/debug/zram/zram<id>/block_state

Documentation/blockdev/zram.txt

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ comp_algorithm RW show and change the compression algorithm
169169
compact WO trigger memory compaction
170170
debug_stat RO this file is used for zram debugging purposes
171171
backing_dev RW set up backend storage for zram to write out
172+
idle WO mark allocated slot as idle
172173

173174

174175
User space is advised to use the following files to read the device statistics.
@@ -251,16 +252,17 @@ pages of the process with*pagemap.
251252
If you enable the feature, you could see block state via
252253
/sys/kernel/debug/zram/zram0/block_state". The output is as follows,
253254

254-
300 75.033841 .wh
255-
301 63.806904 s..
256-
302 63.806919 ..h
255+
300 75.033841 .wh.
256+
301 63.806904 s...
257+
302 63.806919 ..hi
257258

258259
First column is zram's block index.
259260
Second column is access time since the system was booted
260261
Third column is state of the block.
261262
(s: same page
262263
w: written page to backing store
263-
h: huge page)
264+
h: huge page
265+
i: idle page)
264266

265267
First line of above example says 300th block is accessed at 75.033841sec
266268
and the block's state is huge so it is written back to the backing

drivers/block/zram/zram_drv.c

Lines changed: 54 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,47 @@ static ssize_t mem_used_max_store(struct device *dev,
281281
return len;
282282
}
283283

284+
static ssize_t idle_store(struct device *dev,
285+
struct device_attribute *attr, const char *buf, size_t len)
286+
{
287+
struct zram *zram = dev_to_zram(dev);
288+
unsigned long nr_pages = zram->disksize >> PAGE_SHIFT;
289+
int index;
290+
char mode_buf[8];
291+
ssize_t sz;
292+
293+
sz = strscpy(mode_buf, buf, sizeof(mode_buf));
294+
if (sz <= 0)
295+
return -EINVAL;
296+
297+
/* ignore trailing new line */
298+
if (mode_buf[sz - 1] == '\n')
299+
mode_buf[sz - 1] = 0x00;
300+
301+
if (strcmp(mode_buf, "all"))
302+
return -EINVAL;
303+
304+
down_read(&zram->init_lock);
305+
if (!init_done(zram)) {
306+
up_read(&zram->init_lock);
307+
return -EINVAL;
308+
}
309+
310+
for (index = 0; index < nr_pages; index++) {
311+
zram_slot_lock(zram, index);
312+
if (!zram_allocated(zram, index))
313+
goto next;
314+
315+
zram_set_flag(zram, index, ZRAM_IDLE);
316+
next:
317+
zram_slot_unlock(zram, index);
318+
}
319+
320+
up_read(&zram->init_lock);
321+
322+
return len;
323+
}
324+
284325
#ifdef CONFIG_ZRAM_WRITEBACK
285326
static void reset_bdev(struct zram *zram)
286327
{
@@ -638,6 +679,7 @@ static void zram_debugfs_destroy(void)
638679

639680
static void zram_accessed(struct zram *zram, u32 index)
640681
{
682+
zram_clear_flag(zram, index, ZRAM_IDLE);
641683
zram->table[index].ac_time = ktime_get_boottime();
642684
}
643685

@@ -670,12 +712,13 @@ static ssize_t read_block_state(struct file *file, char __user *buf,
670712

671713
ts = ktime_to_timespec64(zram->table[index].ac_time);
672714
copied = snprintf(kbuf + written, count,
673-
"%12zd %12lld.%06lu %c%c%c\n",
715+
"%12zd %12lld.%06lu %c%c%c%c\n",
674716
index, (s64)ts.tv_sec,
675717
ts.tv_nsec / NSEC_PER_USEC,
676718
zram_test_flag(zram, index, ZRAM_SAME) ? 's' : '.',
677719
zram_test_flag(zram, index, ZRAM_WB) ? 'w' : '.',
678-
zram_test_flag(zram, index, ZRAM_HUGE) ? 'h' : '.');
720+
zram_test_flag(zram, index, ZRAM_HUGE) ? 'h' : '.',
721+
zram_test_flag(zram, index, ZRAM_IDLE) ? 'i' : '.');
679722

680723
if (count < copied) {
681724
zram_slot_unlock(zram, index);
@@ -720,7 +763,10 @@ static void zram_debugfs_unregister(struct zram *zram)
720763
#else
721764
static void zram_debugfs_create(void) {};
722765
static void zram_debugfs_destroy(void) {};
723-
static void zram_accessed(struct zram *zram, u32 index) {};
766+
static void zram_accessed(struct zram *zram, u32 index)
767+
{
768+
zram_clear_flag(zram, index, ZRAM_IDLE);
769+
};
724770
static void zram_debugfs_register(struct zram *zram) {};
725771
static void zram_debugfs_unregister(struct zram *zram) {};
726772
#endif
@@ -924,6 +970,9 @@ static void zram_free_page(struct zram *zram, size_t index)
924970
#ifdef CONFIG_ZRAM_MEMORY_TRACKING
925971
zram->table[index].ac_time = 0;
926972
#endif
973+
if (zram_test_flag(zram, index, ZRAM_IDLE))
974+
zram_clear_flag(zram, index, ZRAM_IDLE);
975+
927976
if (zram_test_flag(zram, index, ZRAM_HUGE)) {
928977
zram_clear_flag(zram, index, ZRAM_HUGE);
929978
atomic64_dec(&zram->stats.huge_pages);
@@ -1589,6 +1638,7 @@ static DEVICE_ATTR_RO(initstate);
15891638
static DEVICE_ATTR_WO(reset);
15901639
static DEVICE_ATTR_WO(mem_limit);
15911640
static DEVICE_ATTR_WO(mem_used_max);
1641+
static DEVICE_ATTR_WO(idle);
15921642
static DEVICE_ATTR_RW(max_comp_streams);
15931643
static DEVICE_ATTR_RW(comp_algorithm);
15941644
#ifdef CONFIG_ZRAM_WRITEBACK
@@ -1602,6 +1652,7 @@ static struct attribute *zram_disk_attrs[] = {
16021652
&dev_attr_compact.attr,
16031653
&dev_attr_mem_limit.attr,
16041654
&dev_attr_mem_used_max.attr,
1655+
&dev_attr_idle.attr,
16051656
&dev_attr_max_comp_streams.attr,
16061657
&dev_attr_comp_algorithm.attr,
16071658
#ifdef CONFIG_ZRAM_WRITEBACK

drivers/block/zram/zram_drv.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ enum zram_pageflags {
4848
ZRAM_SAME, /* Page consists the same element */
4949
ZRAM_WB, /* page is stored on backing_device */
5050
ZRAM_HUGE, /* Incompressible page */
51+
ZRAM_IDLE, /* not accessed page since last idle marking */
5152

5253
__NR_ZRAM_PAGEFLAGS,
5354
};

0 commit comments

Comments
 (0)