Skip to content

Commit 4fec80f

Browse files
Barry Song (Xiaomi)kawasaki
authored andcommitted
zram: defer zs_free() in swap slot free notification path
zram_slot_free_notify() is called on the process exit path when unmapping swap entries. The slot_free() it calls internally invokes zs_free(), which accounts for ~87% of slot_free() cost due to zsmalloc internal locking (pool->lock, class->lock) and potential zspage freeing. This blocks the process exit path, delaying overall memory release during Android low-memory killing. Split slot_free() into slot_free_extract() and the actual zs_free() call. slot_free_extract() handles all slot metadata cleanup (clearing flags, updating stats, zeroing handle/size) and returns the zsmalloc handle that needs freeing. This separation has two benefits: 1. It makes the two responsibilities of slot_free() explicit: slot metadata management (must be done under slot lock) vs zsmalloc memory release (can be deferred). 2. It allows zram_slot_free_notify() to use zs_free_deferred() for the handle, deferring the expensive zs_free() to a workqueue so the exit path can release memory faster. While at it, merge three separate clear_slot_flag() calls for ZRAM_IDLE, ZRAM_INCOMPRESSIBLE, and ZRAM_PP_SLOT into a single bitmask operation via clear_slot_flags_on_free(), reducing redundant read-modify-write cycles on the same flags word. All other slot_free() callers (write, discard, meta_free) continue to use synchronous zs_free() through the unchanged slot_free() wrapper. Signed-off-by: Barry Song (Xiaomi) <[email protected]> Signed-off-by: Wenchao Hao <[email protected]>
1 parent 029543c commit 4fec80f

1 file changed

Lines changed: 28 additions & 9 deletions

File tree

drivers/block/zram/zram_drv.c

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,15 @@ static inline bool slot_allocated(struct zram *zram, u32 index)
165165
test_slot_flag(zram, index, ZRAM_WB);
166166
}
167167

168+
#define ZRAM_FLAGS_TO_CLEAR_ON_FREE (BIT(ZRAM_IDLE) | \
169+
BIT(ZRAM_INCOMPRESSIBLE) | \
170+
BIT(ZRAM_PP_SLOT))
171+
172+
static inline void clear_slot_flags_on_free(struct zram *zram, u32 index)
173+
{
174+
zram->table[index].attr.flags &= ~ZRAM_FLAGS_TO_CLEAR_ON_FREE;
175+
}
176+
168177
static inline void set_slot_comp_priority(struct zram *zram, u32 index,
169178
u32 prio)
170179
{
@@ -2000,17 +2009,20 @@ static bool zram_meta_alloc(struct zram *zram, u64 disksize)
20002009
return true;
20012010
}
20022011

2003-
static void slot_free(struct zram *zram, u32 index)
2012+
/*
2013+
* Clear slot metadata and extract the zsmalloc handle for freeing.
2014+
* Returns the handle that needs to be freed via zs_free(), or 0 if
2015+
* no zsmalloc freeing is needed (e.g. same-filled or writeback slots).
2016+
*/
2017+
static unsigned long slot_free_extract(struct zram *zram, u32 index)
20042018
{
2005-
unsigned long handle;
2019+
unsigned long handle = 0;
20062020

20072021
#ifdef CONFIG_ZRAM_TRACK_ENTRY_ACTIME
20082022
zram->table[index].attr.ac_time = 0;
20092023
#endif
20102024

2011-
clear_slot_flag(zram, index, ZRAM_IDLE);
2012-
clear_slot_flag(zram, index, ZRAM_INCOMPRESSIBLE);
2013-
clear_slot_flag(zram, index, ZRAM_PP_SLOT);
2025+
clear_slot_flags_on_free(zram, index);
20142026
set_slot_comp_priority(zram, index, 0);
20152027

20162028
if (test_slot_flag(zram, index, ZRAM_HUGE)) {
@@ -2041,16 +2053,23 @@ static void slot_free(struct zram *zram, u32 index)
20412053

20422054
handle = get_slot_handle(zram, index);
20432055
if (!handle)
2044-
return;
2045-
2046-
zs_free(zram->mem_pool, handle);
2056+
return 0;
20472057

20482058
atomic64_sub(get_slot_size(zram, index),
20492059
&zram->stats.compr_data_size);
20502060
out:
20512061
atomic64_dec(&zram->stats.pages_stored);
20522062
set_slot_handle(zram, index, 0);
20532063
set_slot_size(zram, index, 0);
2064+
2065+
return handle;
2066+
}
2067+
2068+
static void slot_free(struct zram *zram, u32 index)
2069+
{
2070+
unsigned long handle = slot_free_extract(zram, index);
2071+
2072+
zs_free(zram->mem_pool, handle);
20542073
}
20552074

20562075
static int read_same_filled_page(struct zram *zram, struct page *page,
@@ -2797,7 +2816,7 @@ static void zram_slot_free_notify(struct block_device *bdev,
27972816
return;
27982817
}
27992818

2800-
slot_free(zram, index);
2819+
zs_free_deferred(zram->mem_pool, slot_free_extract(zram, index));
28012820
slot_unlock(zram, index);
28022821
}
28032822

0 commit comments

Comments
 (0)