[PATCH 4/7] zram: allocate zsmalloc object under slot lock

From: Sergey Senozhatsky

Date: Wed Nov 04 2026 - 23:49:12 EST


zram_write_page() and write_incompressible_page() allocate and
write zsmalloc object first and take slot lock only to free the
old slot data and set the new handle. The next patch makes
zsmalloc store object location directly in zram table entry, so
we need to free the slot before we allocate a new object for it.

Free the slot and allocate the object under slot lock.
recompress_slot() already allocates objects under it, and
GFP_NOIO reclaim cannot re-enter zram write path.

Signed-off-by: Sergey Senozhatsky <senozhatsky@xxxxxxxxxxxx>
---
drivers/block/zram/zram_drv.c | 15 ++++++++++-----
1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
index 2c2e11b2b663..e2710ce35b1f 100644
--- a/drivers/block/zram/zram_drv.c
+++ b/drivers/block/zram/zram_drv.c
@@ -2260,14 +2260,19 @@ static int write_incompressible_page(struct zram *zram, struct page *page,
struct zs_handle *handle;
void *src;

+ slot_lock(zram, index);
+ slot_free(zram, index);
handle = zs_malloc(zram->mem_pool, PAGE_SIZE,
GFP_NOIO | __GFP_NOWARN |
__GFP_HIGHMEM | __GFP_MOVABLE, page_to_nid(page));
- if (IS_ERR(handle))
+ if (IS_ERR(handle)) {
+ slot_unlock(zram, index);
return PTR_ERR(handle);
+ }

if (!zram_can_store_page(zram)) {
zs_free(zram->mem_pool, handle);
+ slot_unlock(zram, index);
return -ENOMEM;
}

@@ -2275,8 +2280,6 @@ static int write_incompressible_page(struct zram *zram, struct page *page,
zs_obj_write(zram->mem_pool, handle, src, PAGE_SIZE);
kunmap_local(src);

- slot_lock(zram, index);
- slot_free(zram, index);
set_slot_flag(zram, index, ZRAM_HUGE);
zram->table[index].handle = handle;
set_slot_size(zram, index, PAGE_SIZE);
@@ -2325,25 +2328,27 @@ static int zram_write_page(struct zram *zram, struct page *page,
return write_incompressible_page(zram, page, index);
}

+ slot_lock(zram, index);
+ slot_free(zram, index);
handle = zs_malloc(zram->mem_pool, comp_len,
GFP_NOIO | __GFP_NOWARN |
__GFP_HIGHMEM | __GFP_MOVABLE, page_to_nid(page));
if (IS_ERR(handle)) {
zcomp_cstrm_put(zstrm);
+ slot_unlock(zram, index);
return PTR_ERR(handle);
}

if (!zram_can_store_page(zram)) {
zcomp_cstrm_put(zstrm);
zs_free(zram->mem_pool, handle);
+ slot_unlock(zram, index);
return -ENOMEM;
}

zs_obj_write(zram->mem_pool, handle, zstrm->buffer, comp_len);
zcomp_cstrm_put(zstrm);

- slot_lock(zram, index);
- slot_free(zram, index);
zram->table[index].handle = handle;
set_slot_size(zram, index, comp_len);
mark_slot_accessed(zram, index);
--
2.56.0.398.g882cbad275-goog