From nobody Mon Feb 9 13:59:17 2026 Received: from mail-pf1-f173.google.com (mail-pf1-f173.google.com [209.85.210.173]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E7F472EC562 for ; Tue, 13 Jan 2026 03:47:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.173 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768276022; cv=none; b=fvR3QrOJMN0eUkfZj9X8CyjutHIcEXj02PAi99oE8d4rlu11c4uT0bHXGxBoG1UuuOhPbWhWBNJjSeWQjkKMtImROWBwDz80bt/VPd5qnDUPUrxz6lMmP4TtunPiVNIqchyppj/xWFPKyW6Macg4aaYBrJK8r6oYsGT7D+9tzrc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768276022; c=relaxed/simple; bh=oyDDSqm83fprlzq/ZuYDZvn60+JP+wR+mfNS3Yh/08U=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=SCQ09fj2SfpPdlbFYCpmodE1atEXCHHNIgAZjZIBi8Kos6IL7nhEVCHaCAobWoDFScI115pthbogPIxuq9FGIiSb8+RR7JM2d+QdGLmPCg6qZ5MCDjYwF9g43GBEIyMGMyXKXuZB5AggDLNi7IAfC1jH7SuHlljS1gZXGiuynM4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org; spf=pass smtp.mailfrom=chromium.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b=mvQfS4RR; arc=none smtp.client-ip=209.85.210.173 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=chromium.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="mvQfS4RR" Received: by mail-pf1-f173.google.com with SMTP id d2e1a72fcca58-81f3c14027cso1303502b3a.1 for ; Mon, 12 Jan 2026 19:47:00 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1768276020; x=1768880820; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=OG8CS3/xgGfJ8PQ65WNk3vWPobqgC7PlowynwQH/ywQ=; b=mvQfS4RRtwvp9j8fleO9trLU1W9n3AbPZttTukDnkN22bcEKeEXKSl+EZtsCC4hpIs k/6X6Uvqhd0dBglXI9y13uRC2SNvNvmGq90FVr9RRrOQQ4I+ig37vTm8U9lcbqCNSWMG KsHStYoWHpcqr7tqQBWaCbdCzgxHA+An1Icbo= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1768276020; x=1768880820; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=OG8CS3/xgGfJ8PQ65WNk3vWPobqgC7PlowynwQH/ywQ=; b=YkTtWv9kBq45CG8a6lL7A88Xw8uFFM86RgdZGWKdRA12UTkxDmTND7WPpbyN8raTo0 Kt0X99kHK5aoR6Cmx7bGNmfq1cEVkkN69quRx/ow2wXJov+gMwyWhN6a7srXxlAoV6nF 1WOzzb0R7vyxqronufuQv3U2nduedukwNj4eUTxNZrxHYm8HKFmYiXhq9dz+i5PSYgV9 f5xJJnvCAvla0RqUsTeH5irBMWMyKzTWYzMCS/yyXH/7c3YWQsDsNzeIMRtpYtVc2gTd UYoA42EqRayTmv6J5t9Tj8z0GAhwwYhccWK8zBaC5IQoOhhYj1xx3V9MDNTEehR21uI/ 8AcQ== X-Forwarded-Encrypted: i=1; AJvYcCU22hUBQRb4JL1HhDbmCgmsFKogBrKenm2VgVObuyYLJ07q4OUg21Cw/KRSg28w5+VN/P/ljvZDaCzgCiA=@vger.kernel.org X-Gm-Message-State: AOJu0YxRx6AF3I1AaqQ7SK3Gt4OaPA8esohzdJWxzVgFyTynClASjK4k Hzgq/zORxO426Q5aPQr5xpxp7v8nLqaC638LSK/39nF5WjnhW7WF/qd40KOKV8psVw== X-Gm-Gg: AY/fxX69jOEasd6JE1i4PWEH3CuzBuK7/jyhcm26Vnp+1EprvfdCsAahYpQkVUoNjRU XhmjDuChKqhZLPfjTLtqRar5oHgIhMHi4AMvCDWMFCbght0prOdzGawsw1Alh6iQfk+b6zgf3JM Ibz+mmhaZZTsHIHXKq0hPp2i+HOvDGk2TLPiNBxUyjL6q0aYMlq0ff0j6GnYjPBQVZFoBCcJvVD fFrppP3gwGoAIyQCJjq+Sin6kBf6du3EevXbbd7F9OaRcb3/TLSWN+7h4o5ZddwRU+sUGi0rHUM b0DZp8Xmc7uSNns5vjH3xi5rwQEky3jU0RZFbXxAjC8vgckAyhJD4UAkpY+vOk2O3n4+b6s3y2H wb0czPSluHE0Rj+gO44mgmONm2xml5z+q83K4zLJnAOlrLBruKZIgqsbK9jI6ghv5C9nOhUReoC uRXHQ+dl7OSXzpp+QMMGBhl/obYdnYnn4syWBSFlqh1lkvFbIWJ+hsr44tm/1QzGf8bGdgmcoUR KRXQjYjwwea X-Received: by 2002:a05:6a00:6709:b0:7ab:2c18:34eb with SMTP id d2e1a72fcca58-81f6f762765mr1084097b3a.12.1768276020136; Mon, 12 Jan 2026 19:47:00 -0800 (PST) Received: from tigerii.tok.corp.google.com ([2a00:79e0:2031:6:3c61:f146:e418:e233]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-81f3fc40c1csm7448287b3a.55.2026.01.12.19.46.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 12 Jan 2026 19:46:59 -0800 (PST) From: Sergey Senozhatsky To: Andrew Morton , Yosry Ahmed Cc: Minchan Kim , Nhat Pham , Johannes Weiner , Brian Geffon , linux-kernel@vger.kernel.org, linux-mm@kvack.org, Sergey Senozhatsky , Herbert Xu Subject: [PATCH] zsmalloc: introduce SG-list based object read API Date: Tue, 13 Jan 2026 12:46:45 +0900 Message-ID: <20260113034645.2729998-1-senozhatsky@chromium.org> X-Mailer: git-send-email 2.52.0.457.g6b5491de43-goog Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Currently, zsmalloc performs address linearization on read (which sometimes requires memcpy() to a local buffer). Not all zsmalloc users need a linear address. For example, Crypto API supports SG-list, performing linearization under the hood, if needed. In addition, some compressors can have native SG-list support, completely avoiding the linearization step. Provide an SG-list based zsmalloc read API: - zs_obj_read_sg_begin() - zs_obj_read_sg_end() This API allows callers to obtain an SG representation of the object (one entry for objects that are contained in a single page and two entries for spanning objects), avoiding the need for a bounce buffer and memcpy. Signed-off-by: Sergey Senozhatsky Cc: Herbert Xu Acked-by: Herbert Xu Acked-by: Nhat Pham Tested-by: Yosry Ahmed --- include/linux/zsmalloc.h | 4 +++ mm/zsmalloc.c | 65 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+) diff --git a/include/linux/zsmalloc.h b/include/linux/zsmalloc.h index 5565c3171007..11e614663dd3 100644 --- a/include/linux/zsmalloc.h +++ b/include/linux/zsmalloc.h @@ -22,6 +22,7 @@ struct zs_pool_stats { }; =20 struct zs_pool; +struct scatterlist; =20 struct zs_pool *zs_create_pool(const char *name); void zs_destroy_pool(struct zs_pool *pool); @@ -43,6 +44,9 @@ void *zs_obj_read_begin(struct zs_pool *pool, unsigned lo= ng handle, size_t mem_len, void *local_copy); void zs_obj_read_end(struct zs_pool *pool, unsigned long handle, size_t mem_len, void *handle_mem); +int zs_obj_read_sg_begin(struct zs_pool *pool, unsigned long handle, + struct scatterlist *sg, size_t mem_len); +void zs_obj_read_sg_end(struct zs_pool *pool, unsigned long handle); void zs_obj_write(struct zs_pool *pool, unsigned long handle, void *handle_mem, size_t mem_len); =20 diff --git a/mm/zsmalloc.c b/mm/zsmalloc.c index 16d5587a052a..5abb8bc0956a 100644 --- a/mm/zsmalloc.c +++ b/mm/zsmalloc.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -1146,6 +1147,70 @@ void zs_obj_read_end(struct zs_pool *pool, unsigned = long handle, } EXPORT_SYMBOL_GPL(zs_obj_read_end); =20 +int zs_obj_read_sg_begin(struct zs_pool *pool, unsigned long handle, + struct scatterlist *sg, size_t mem_len) +{ + struct zspage *zspage; + struct zpdesc *zpdesc; + unsigned long obj, off; + unsigned int obj_idx; + struct size_class *class; + + /* Guarantee we can get zspage from handle safely */ + read_lock(&pool->lock); + obj =3D handle_to_obj(handle); + obj_to_location(obj, &zpdesc, &obj_idx); + zspage =3D get_zspage(zpdesc); + + /* Make sure migration doesn't move any pages in this zspage */ + zspage_read_lock(zspage); + read_unlock(&pool->lock); + + class =3D zspage_class(pool, zspage); + off =3D offset_in_page(class->size * obj_idx); + + if (!ZsHugePage(zspage)) + off +=3D ZS_HANDLE_SIZE; + + if (off + mem_len <=3D PAGE_SIZE) { + /* this object is contained entirely within a page */ + sg_init_table(sg, 1); + sg_set_page(sg, zpdesc_page(zpdesc), mem_len, off); + } else { + size_t sizes[2]; + + /* this object spans two pages */ + sizes[0] =3D PAGE_SIZE - off; + sizes[1] =3D mem_len - sizes[0]; + + sg_init_table(sg, 2); + sg_set_page(sg, zpdesc_page(zpdesc), sizes[0], off); + + zpdesc =3D get_next_zpdesc(zpdesc); + sg =3D sg_next(sg); + + sg_set_page(sg, zpdesc_page(zpdesc), sizes[1], 0); + } + + return 0; +} +EXPORT_SYMBOL_GPL(zs_obj_read_sg_begin); + +void zs_obj_read_sg_end(struct zs_pool *pool, unsigned long handle) +{ + struct zspage *zspage; + struct zpdesc *zpdesc; + unsigned long obj; + unsigned int obj_idx; + + obj =3D handle_to_obj(handle); + obj_to_location(obj, &zpdesc, &obj_idx); + zspage =3D get_zspage(zpdesc); + + zspage_read_unlock(zspage); +} +EXPORT_SYMBOL_GPL(zs_obj_read_sg_end); + void zs_obj_write(struct zs_pool *pool, unsigned long handle, void *handle_mem, size_t mem_len) { --=20 2.52.0.457.g6b5491de43-goog