Skip to content

Commit b0377ee

Browse files
sergey-senozhatskyakpm00
authored andcommitted
zram: do not slot_free() written-back slots
slot_free() basically completely resets the slots by clearing all of its flags and attributes. While zram_writeback_complete() restores some of flags back (those that are necessary for async read decompression) we still lose a lot of slot's metadata. For example, slot's ac-time, or ZRAM_INCOMPRESSIBLE. More importantly, restoring flags/attrs requires extra attention as some of the flags are directly affecting zram device stats. And the original code did not pay that attention. Namely ZRAM_HUGE slots handling in zram_writeback_complete(). The call to slot_free() would decrement ->huge_pages, however when zram_writeback_complete() restored the slot's ZRAM_HUGE flag, it would not get reflected in an incremented ->huge_pages. So when the slot would finally get freed, slot_free() would decrement ->huge_pages again, leading to underflow. Fix this by open-coding the required memory free and stats updates in zram_writeback_complete(), rather than calling the destructive slot_free(). Since we now preserve the ZRAM_HUGE flag on written-back slots (for the deferred decompression path), we also update slot_free() to skip decrementing ->huge_pages if ZRAM_WB is set. Link: https://lkml.kernel.org/r/[email protected] Link: https://lkml.kernel.org/r/[email protected] Fixes: d38fab6 ("zram: introduce compressed data writeback") Signed-off-by: Sergey Senozhatsky <[email protected]> Acked-by: Minchan Kim <[email protected]> Cc: Brian Geffon <[email protected]> Cc: Richard Chang <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent 26f775a commit b0377ee

1 file changed

Lines changed: 14 additions & 25 deletions

File tree

drivers/block/zram/zram_drv.c

Lines changed: 14 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -917,9 +917,8 @@ static void zram_account_writeback_submit(struct zram *zram)
917917

918918
static int zram_writeback_complete(struct zram *zram, struct zram_wb_req *req)
919919
{
920-
u32 size, index = req->pps->index;
921-
int err, prio;
922-
bool huge;
920+
u32 index = req->pps->index;
921+
int err;
923922

924923
err = blk_status_to_errno(req->bio.bi_status);
925924
if (err) {
@@ -946,28 +945,13 @@ static int zram_writeback_complete(struct zram *zram, struct zram_wb_req *req)
946945
goto out;
947946
}
948947

949-
if (zram->compressed_wb) {
950-
/*
951-
* ZRAM_WB slots get freed, we need to preserve data required
952-
* for read decompression.
953-
*/
954-
size = get_slot_size(zram, index);
955-
prio = get_slot_comp_priority(zram, index);
956-
huge = test_slot_flag(zram, index, ZRAM_HUGE);
957-
}
958-
959-
slot_free(zram, index);
960-
set_slot_flag(zram, index, ZRAM_WB);
948+
clear_slot_flag(zram, index, ZRAM_IDLE);
949+
if (test_slot_flag(zram, index, ZRAM_HUGE))
950+
atomic64_dec(&zram->stats.huge_pages);
951+
atomic64_sub(get_slot_size(zram, index), &zram->stats.compr_data_size);
952+
zs_free(zram->mem_pool, get_slot_handle(zram, index));
961953
set_slot_handle(zram, index, req->blk_idx);
962-
963-
if (zram->compressed_wb) {
964-
if (huge)
965-
set_slot_flag(zram, index, ZRAM_HUGE);
966-
set_slot_size(zram, index, size);
967-
set_slot_comp_priority(zram, index, prio);
968-
}
969-
970-
atomic64_inc(&zram->stats.pages_stored);
954+
set_slot_flag(zram, index, ZRAM_WB);
971955

972956
out:
973957
slot_unlock(zram, index);
@@ -2010,8 +1994,13 @@ static void slot_free(struct zram *zram, u32 index)
20101994
set_slot_comp_priority(zram, index, 0);
20111995

20121996
if (test_slot_flag(zram, index, ZRAM_HUGE)) {
1997+
/*
1998+
* Writeback completion decrements ->huge_pages but keeps
1999+
* ZRAM_HUGE flag for deferred decompression path.
2000+
*/
2001+
if (!test_slot_flag(zram, index, ZRAM_WB))
2002+
atomic64_dec(&zram->stats.huge_pages);
20132003
clear_slot_flag(zram, index, ZRAM_HUGE);
2014-
atomic64_dec(&zram->stats.huge_pages);
20152004
}
20162005

20172006
if (test_slot_flag(zram, index, ZRAM_WB)) {

0 commit comments

Comments
 (0)