Commit a55cf964 authored by Sergey Senozhatsky's avatar Sergey Senozhatsky Committed by Andrew Morton
Browse files

zram: add algo parameter support to zram_recompress()

Recompression iterates through all the registered secondary compression
algorithms in order of their priorities so that we have higher chances of
finding the algorithm that compresses a particular page.  This, however,
may not always be best approach and sometimes we may want to limit
recompression to only one particular algorithm.  For instance, when a
higher priority algorithm uses too much power and device has a relatively
low battery level we may want to limit recompression to use only a lower
priority algorithm, which uses less power.

Introduce algo= parameter support to recompression sysfs knob so that
user-sapce can request recompression with particular algorithm only:

  echo "type=idle algo=zstd" > /sys/block/zramX/recompress

Link: https://lkml.kernel.org/r/20221109115047.2921851-11-senozhatsky@chromium.org


Signed-off-by: default avatarSergey Senozhatsky <senozhatsky@chromium.org>
Acked-by: default avatarMinchan Kim <minchan@kernel.org>
Cc: Alexey Romanov <avromanov@sberdevices.ru>
Cc: Nhat Pham <nphamcs@gmail.com>
Cc: Nitin Gupta <ngupta@vflare.org>
Cc: Suleiman Souhlal <suleiman@google.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
parent 4942cf6a
Loading
Loading
Loading
Loading
+45 −9
Original line number Diff line number Diff line
@@ -1674,6 +1674,7 @@ static int zram_recompress(struct zram *zram, u32 index, struct page *page,
	unsigned int comp_len_new;
	unsigned int class_index_old;
	unsigned int class_index_new;
	u32 num_recomps = 0;
	void *src, *dst;
	int ret;

@@ -1708,6 +1709,7 @@ static int zram_recompress(struct zram *zram, u32 index, struct page *page,
		if (prio <= zram_get_priority(zram, index))
			continue;

		num_recomps++;
		zstrm = zcomp_stream_get(zram->comps[prio]);
		src = kmap_atomic(page);
		ret = zcomp_compress(zstrm, src, &comp_len_new);
@@ -1740,12 +1742,18 @@ static int zram_recompress(struct zram *zram, u32 index, struct page *page,
	if (!zstrm)
		return 0;

	if (class_index_new >= class_index_old) {
		/*
	 * All secondary algorithms failed to re-compress the page in a way
	 * that would save memory, mark the object as incompressible so that
	 * we will not try to compress it again.
		 * Secondary algorithms failed to re-compress the page
		 * in a way that would save memory, mark the object as
		 * incompressible so that we will not try to compress
		 * it again.
		 *
		 * We need to make sure that all secondary algorithms have
		 * failed, so we test if the number of recompressions matches
		 * the number of active secondary algorithms.
		 */
	if (class_index_new >= class_index_old) {
		if (num_recomps == zram->num_active_comps - 1)
			zram_set_flag(zram, index, ZRAM_INCOMPRESSIBLE);
		return 0;
	}
@@ -1795,10 +1803,11 @@ static ssize_t recompress_store(struct device *dev,
				struct device_attribute *attr,
				const char *buf, size_t len)
{
	u32 prio = ZRAM_SECONDARY_COMP, prio_max = ZRAM_MAX_COMPS;
	struct zram *zram = dev_to_zram(dev);
	u32 mode = 0, threshold = 0, prio = ZRAM_SECONDARY_COMP;
	unsigned long nr_pages = zram->disksize >> PAGE_SHIFT;
	char *args, *param, *val;
	char *args, *param, *val, *algo = NULL;
	u32 mode = 0, threshold = 0;
	unsigned long index;
	struct page *page;
	ssize_t ret;
@@ -1830,6 +1839,11 @@ static ssize_t recompress_store(struct device *dev,
				return ret;
			continue;
		}

		if (!strcmp(param, "algo")) {
			algo = val;
			continue;
		}
	}

	if (threshold >= PAGE_SIZE)
@@ -1841,6 +1855,26 @@ static ssize_t recompress_store(struct device *dev,
		goto release_init_lock;
	}

	if (algo) {
		bool found = false;

		for (; prio < ZRAM_MAX_COMPS; prio++) {
			if (!zram->comp_algs[prio])
				continue;

			if (!strcmp(zram->comp_algs[prio], algo)) {
				prio_max = min(prio + 1, ZRAM_MAX_COMPS);
				found = true;
				break;
			}
		}

		if (!found) {
			ret = -EINVAL;
			goto release_init_lock;
		}
	}

	page = alloc_page(GFP_KERNEL);
	if (!page) {
		ret = -ENOMEM;
@@ -1871,7 +1905,7 @@ static ssize_t recompress_store(struct device *dev,
			goto next;

		err = zram_recompress(zram, index, page, threshold,
				      prio, ZRAM_MAX_COMPS);
				      prio, prio_max);
next:
		zram_slot_unlock(zram, index);
		if (err) {
@@ -2107,6 +2141,7 @@ static void zram_destroy_comps(struct zram *zram)
		if (!comp)
			continue;
		zcomp_destroy(comp);
		zram->num_active_comps--;
	}
}

@@ -2174,6 +2209,7 @@ static ssize_t disksize_store(struct device *dev,
		}

		zram->comps[prio] = comp;
		zram->num_active_comps++;
	}
	zram->disksize = disksize;
	set_capacity_and_notify(zram->disk, zram->disksize >> SECTOR_SHIFT);
+1 −0
Original line number Diff line number Diff line
@@ -125,6 +125,7 @@ struct zram {
	 */
	u64 disksize;	/* bytes */
	const char *comp_algs[ZRAM_MAX_COMPS];
	s8 num_active_comps;
	/*
	 * zram is claimed so open request will be failed
	 */