Skip to content

Commit 755804d

Browse files
bgafftorvalds
authored andcommitted
zram: introduce an aged idle interface
This change introduces an aged idle interface to the existing idle sysfs file for zram. When CONFIG_ZRAM_MEMORY_TRACKING is enabled the idle file now also accepts an integer argument. This integer is the age (in seconds) of pages to mark as idle. The idle file still supports 'all' as it always has. This new approach allows for much more control over which pages get marked as idle. [[email protected]: use IS_ENABLED and cleanup comment] Link: https://lkml.kernel.org/r/[email protected] [[email protected]: Sergey's cleanup suggestions] Link: https://lkml.kernel.org/r/[email protected] Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: Brian Geffon <[email protected]> Acked-by: Minchan Kim <[email protected]> Reviewed-by: Sergey Senozhatsky <[email protected]> Cc: Nitin Gupta <[email protected]> Cc: Jonathan Corbet <[email protected]> Cc: Suleiman Souhlal <[email protected]> Cc: Jesse Barnes <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent a88e03c commit 755804d

File tree

2 files changed

+54
-16
lines changed

2 files changed

+54
-16
lines changed

Documentation/admin-guide/blockdev/zram.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,14 @@ as idle::
328328
From now on, any pages on zram are idle pages. The idle mark
329329
will be removed until someone requests access of the block.
330330
IOW, unless there is access request, those pages are still idle pages.
331+
Additionally, when CONFIG_ZRAM_MEMORY_TRACKING is enabled pages can be
332+
marked as idle based on how long (in seconds) it's been since they were
333+
last accessed::
334+
335+
echo 86400 > /sys/block/zramX/idle
336+
337+
In this example all pages which haven't been accessed in more than 86400
338+
seconds (one day) will be marked idle.
331339

332340
Admin can request writeback of those idle pages at right timing via::
333341

drivers/block/zram/zram_drv.c

Lines changed: 46 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -291,37 +291,67 @@ static ssize_t mem_used_max_store(struct device *dev,
291291
return len;
292292
}
293293

294-
static ssize_t idle_store(struct device *dev,
295-
struct device_attribute *attr, const char *buf, size_t len)
294+
/*
295+
* Mark all pages which are older than or equal to cutoff as IDLE.
296+
* Callers should hold the zram init lock in read mode
297+
*/
298+
static void mark_idle(struct zram *zram, ktime_t cutoff)
296299
{
297-
struct zram *zram = dev_to_zram(dev);
300+
int is_idle = 1;
298301
unsigned long nr_pages = zram->disksize >> PAGE_SHIFT;
299302
int index;
300303

301-
if (!sysfs_streq(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-
310304
for (index = 0; index < nr_pages; index++) {
311305
/*
312306
* Do not mark ZRAM_UNDER_WB slot as ZRAM_IDLE to close race.
313307
* See the comment in writeback_store.
314308
*/
315309
zram_slot_lock(zram, index);
316310
if (zram_allocated(zram, index) &&
317-
!zram_test_flag(zram, index, ZRAM_UNDER_WB))
318-
zram_set_flag(zram, index, ZRAM_IDLE);
311+
!zram_test_flag(zram, index, ZRAM_UNDER_WB)) {
312+
#ifdef CONFIG_ZRAM_MEMORY_TRACKING
313+
is_idle = !cutoff || ktime_after(cutoff, zram->table[index].ac_time);
314+
#endif
315+
if (is_idle)
316+
zram_set_flag(zram, index, ZRAM_IDLE);
317+
}
319318
zram_slot_unlock(zram, index);
320319
}
320+
}
321321

322-
up_read(&zram->init_lock);
322+
static ssize_t idle_store(struct device *dev,
323+
struct device_attribute *attr, const char *buf, size_t len)
324+
{
325+
struct zram *zram = dev_to_zram(dev);
326+
ktime_t cutoff_time = 0;
327+
ssize_t rv = -EINVAL;
323328

324-
return len;
329+
if (!sysfs_streq(buf, "all")) {
330+
/*
331+
* If it did not parse as 'all' try to treat it as an integer when
332+
* we have memory tracking enabled.
333+
*/
334+
u64 age_sec;
335+
336+
if (IS_ENABLED(CONFIG_ZRAM_MEMORY_TRACKING) && !kstrtoull(buf, 0, &age_sec))
337+
cutoff_time = ktime_sub(ktime_get_boottime(),
338+
ns_to_ktime(age_sec * NSEC_PER_SEC));
339+
else
340+
goto out;
341+
}
342+
343+
down_read(&zram->init_lock);
344+
if (!init_done(zram))
345+
goto out_unlock;
346+
347+
/* A cutoff_time of 0 marks everything as idle, this is the "all" behavior */
348+
mark_idle(zram, cutoff_time);
349+
rv = len;
350+
351+
out_unlock:
352+
up_read(&zram->init_lock);
353+
out:
354+
return rv;
325355
}
326356

327357
#ifdef CONFIG_ZRAM_WRITEBACK

0 commit comments

Comments
 (0)