From: Takero Funaki <flintglass@gmail.com>
To: Johannes Weiner <hannes@cmpxchg.org>,
Yosry Ahmed <yosryahmed@google.com>,
Nhat Pham <nphamcs@gmail.com>,
Chengming Zhou <chengming.zhou@linux.dev>,
Jonathan Corbet <corbet@lwn.net>,
Andrew Morton <akpm@linux-foundation.org>,
Domenico Cerasuolo <cerasuolodomenico@gmail.com>
Cc: Takero Funaki <flintglass@gmail.com>,
linux-mm@kvack.org, linux-doc@vger.kernel.org,
linux-kernel@vger.kernel.org
Subject: [PATCH v2 5/6] mm: zswap: store incompressible page as-is
Date: Sat, 6 Jul 2024 02:25:21 +0000 [thread overview]
Message-ID: <20240706022523.1104080-6-flintglass@gmail.com> (raw)
In-Reply-To: <20240706022523.1104080-1-flintglass@gmail.com>
This patch allows zswap to accept incompressible pages and store them
into zpool if possible.
This change is required to achieve zero rejection on zswap_store(). With
proper amount of proactive shrinking, swapout can be buffered by zswap
without IO latency. Storing incompressible pages may seem costly, but it
can reduce latency. A rare incompressible page in a large batch of
compressive pages can delay the entire batch during swapping.
The memory overhead is negligible because the underlying zsmalloc
already accepts nearly incompressible pages. zsmalloc stores data close
to PAGE_SIZE to a dedicated page. Thus storing as-is saves decompression
cycles without allocation overhead. zswap itself has not rejected pages
in these cases.
To store the page as-is, use the compressed data size field `length` in
struct `zswap_entry`. The length == PAGE_SIZE indicates
incompressible data.
If a zpool backend does not support allocating PAGE_SIZE (zbud), the
behavior remains unchanged. The allocation failure reported by the zpool
blocks accepting the page as before.
Signed-off-by: Takero Funaki <flintglass@gmail.com>
---
mm/zswap.c | 36 +++++++++++++++++++++++++++++++++---
1 file changed, 33 insertions(+), 3 deletions(-)
diff --git a/mm/zswap.c b/mm/zswap.c
index 76691ca7b6a7..def0f948a4ab 100644
--- a/mm/zswap.c
+++ b/mm/zswap.c
@@ -186,6 +186,8 @@ static struct shrinker *zswap_shrinker;
* length - the length in bytes of the compressed page data. Needed during
* decompression. For a same value filled page length is 0, and both
* pool and lru are invalid and must be ignored.
+ * If length is equal to PAGE_SIZE, the data stored in handle is
+ * not compressed. The data must be copied to page as-is.
* pool - the zswap_pool the entry's data is in
* handle - zpool allocation handle that stores the compressed page data
* value - value of the same-value filled pages which have same content
@@ -969,9 +971,23 @@ static bool zswap_compress(struct folio *folio, struct zswap_entry *entry)
*/
comp_ret = crypto_wait_req(crypto_acomp_compress(acomp_ctx->req), &acomp_ctx->wait);
dlen = acomp_ctx->req->dlen;
- if (comp_ret)
+
+ /* coa_compress returns -EINVAL for errors including insufficient dlen */
+ if (comp_ret && comp_ret != -EINVAL)
goto unlock;
+ /*
+ * If the data cannot be compressed well, store the data as-is.
+ * Switching by a threshold at
+ * PAGE_SIZE - (allocation granularity)
+ * zbud and z3fold use 64B granularity.
+ * zsmalloc stores >3632B in one page for 4K page arch.
+ */
+ if (comp_ret || dlen > PAGE_SIZE - 64) {
+ /* we do not use compressed result anymore */
+ comp_ret = 0;
+ dlen = PAGE_SIZE;
+ }
zpool = zswap_find_zpool(entry);
gfp = __GFP_NORETRY | __GFP_NOWARN | __GFP_KSWAPD_RECLAIM;
if (zpool_malloc_support_movable(zpool))
@@ -981,14 +997,20 @@ static bool zswap_compress(struct folio *folio, struct zswap_entry *entry)
goto unlock;
buf = zpool_map_handle(zpool, handle, ZPOOL_MM_WO);
- memcpy(buf, dst, dlen);
+
+ /* PAGE_SIZE indicates not compressed. */
+ if (dlen == PAGE_SIZE)
+ memcpy_from_folio(buf, folio, 0, PAGE_SIZE);
+ else
+ memcpy(buf, dst, dlen);
+
zpool_unmap_handle(zpool, handle);
entry->handle = handle;
entry->length = dlen;
unlock:
- if (comp_ret == -ENOSPC || alloc_ret == -ENOSPC)
+ if (alloc_ret == -ENOSPC)
zswap_reject_compress_poor++;
else if (comp_ret)
zswap_reject_compress_fail++;
@@ -1006,6 +1028,14 @@ static void zswap_decompress(struct zswap_entry *entry, struct page *page)
struct crypto_acomp_ctx *acomp_ctx;
u8 *src;
+ if (entry->length == PAGE_SIZE) {
+ /* the content is not compressed. copy back as-is. */
+ src = zpool_map_handle(zpool, entry->handle, ZPOOL_MM_RO);
+ memcpy_to_page(page, 0, src, entry->length);
+ zpool_unmap_handle(zpool, entry->handle);
+ return;
+ }
+
acomp_ctx = raw_cpu_ptr(entry->pool->acomp_ctx);
mutex_lock(&acomp_ctx->mutex);
--
2.43.0
next prev parent reply other threads:[~2024-07-06 2:25 UTC|newest]
Thread overview: 37+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-07-06 2:25 [PATCH v2 0/6] mm: zswap: global shrinker fix and proactive shrink Takero Funaki
2024-07-06 2:25 ` [PATCH v2 1/6] mm: zswap: fix global shrinker memcg iteration Takero Funaki
2024-07-08 4:54 ` Chengming Zhou
2024-07-17 1:54 ` Yosry Ahmed
2024-07-06 2:25 ` [PATCH v2 2/6] mm: zswap: fix global shrinker error handling logic Takero Funaki
2024-07-17 2:39 ` Yosry Ahmed
2024-07-06 2:25 ` [PATCH v2 3/6] mm: zswap: proactive shrinking before pool size limit is hit Takero Funaki
2024-07-12 23:18 ` Nhat Pham
2024-07-06 2:25 ` [PATCH v2 4/6] mm: zswap: make writeback run in the background Takero Funaki
2024-07-06 2:25 ` Takero Funaki [this message]
2024-07-06 23:53 ` [PATCH v2 5/6] mm: zswap: store incompressible page as-is Nhat Pham
2024-07-07 9:38 ` Takero Funaki
2024-07-12 22:36 ` Nhat Pham
2024-07-08 3:56 ` Chengming Zhou
2024-07-08 13:44 ` Takero Funaki
2024-07-09 13:26 ` Chengming Zhou
2024-07-12 22:47 ` Nhat Pham
2024-07-16 2:30 ` Chengming Zhou
2024-07-06 2:25 ` [PATCH v2 6/6] mm: zswap: interrupt shrinker writeback while pagein/out IO Takero Funaki
2024-07-08 19:17 ` Nhat Pham
2024-07-09 0:57 ` Nhat Pham
2024-07-10 21:21 ` Takero Funaki
2024-07-10 22:10 ` Nhat Pham
2024-07-15 7:33 ` Takero Funaki
2024-07-06 17:32 ` [PATCH v2 0/6] mm: zswap: global shrinker fix and proactive shrink Andrew Morton
2024-07-07 10:54 ` Takero Funaki
2024-07-09 0:53 ` Nhat Pham
2024-07-10 22:26 ` Takero Funaki
2024-07-12 23:02 ` Nhat Pham
2024-07-15 8:20 ` Takero Funaki
2024-07-26 18:13 ` Nhat Pham
2024-07-26 18:25 ` Nhat Pham
2024-07-17 2:53 ` Yosry Ahmed
2024-07-17 17:49 ` Nhat Pham
2024-07-17 18:05 ` Yosry Ahmed
2024-07-17 19:01 ` Nhat Pham
2024-07-19 14:55 ` Takero Funaki
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20240706022523.1104080-6-flintglass@gmail.com \
--to=flintglass@gmail.com \
--cc=akpm@linux-foundation.org \
--cc=cerasuolodomenico@gmail.com \
--cc=chengming.zhou@linux.dev \
--cc=corbet@lwn.net \
--cc=hannes@cmpxchg.org \
--cc=linux-doc@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=nphamcs@gmail.com \
--cc=yosryahmed@google.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox