Re: [PATCH v4] zram: Introduce an aged idle interface

Andrew Morton
2021-09-23T22:53:11Z

On Thu, 23 Sep 2021 06:01:15 -0700 Brian Geffon <bgeffon@google.com> wrote:

> 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.
>
> @@ -291,22 +291,16 @@ static ssize_t mem_used_max_store(struct device *dev,
> return len;
> }
>
> -static ssize_t idle_store(struct device *dev,
> - struct device_attribute *attr, const char *buf, size_t len)
> +/*
> + * Mark all pages which are older than or equal to cutoff as IDLE.
> + * Callers should hold the zram init lock in read mode
> + **/

A simple "*/" is conventional.

> +static void mark_idle(struct zram *zram, ktime_t cutoff)
> {
> - struct zram *zram = dev_to_zram(dev);
> + int is_idle = 1;
> unsigned long nr_pages = zram->disksize >> PAGE_SHIFT;
> int index;
>
> - if (!sysfs_streq(buf, "all"))
> - return -EINVAL;
> -
> - down_read(&zram->init_lock);
> - if (!init_done(zram)) {
> - up_read(&zram->init_lock);
> - return -EINVAL;
> - }
> -
> for (index = 0; index < nr_pages; index++) {
> /*
> * Do not mark ZRAM_UNDER_WB slot as ZRAM_IDLE to close race.
> @@ -314,14 +308,48 @@ static ssize_t idle_store(struct device *dev,
> */
> zram_slot_lock(zram, index);
> if (zram_allocated(zram, index) &&
> - !zram_test_flag(zram, index, ZRAM_UNDER_WB))
> - zram_set_flag(zram, index, ZRAM_IDLE);
> + !zram_test_flag(zram, index, ZRAM_UNDER_WB)) {
> +#ifdef CONFIG_ZRAM_MEMORY_TRACKING
> + is_idle = (!cutoff || ktime_after(cutoff, zram->table[index].ac_time));
> +#endif
> + if (is_idle)
> + zram_set_flag(zram, index, ZRAM_IDLE);
> + }
> zram_slot_unlock(zram, index);
> }
> +}
>
> - up_read(&zram->init_lock);
> +static ssize_t idle_store(struct device *dev,
> + struct device_attribute *attr, const char *buf, size_t len)
> +{
> + struct zram *zram = dev_to_zram(dev);
> + ktime_t cutoff_time = 0;
> + ssize_t rv = -EINVAL;
>
> - return len;
> + if (!sysfs_streq(buf, "all")) {
> +#ifdef CONFIG_ZRAM_MEMORY_TRACKING
> + u64 age_sec;
> + /* If it did not parse as 'all' try to treat it as an integer */
> + if (!kstrtoull(buf, 0, &age_sec))
> + cutoff_time = ktime_sub(ktime_get_boottime(),
> + ns_to_ktime(age_sec * NSEC_PER_SEC));
> + else
> +#endif
> + goto out;
> + }

The ifdef tricks are pretty ugly. Can things be improved with IS_ENABLED()?