Skip to content

Commit e43fd1d

Browse files
sergey-senozhatskydgstevens
authored andcommitted
UPSTREAM: zram: rework writeback target selection strategy
Writeback suffers from the same problem as recompression did before - target slot selection for writeback is just a simple iteration over zram->table entries (stored pages) which selects suboptimal targets for writeback. This is especially problematic for writeback, because we uncompress objects before writeback so each of them takes 4K out of limited writeback storage. For example, when we take a 48 bytes slot and store it as a 4K object to writeback device we only save 48 bytes of memory (release from zsmalloc pool). We naturally want to pick the largest objects for writeback, because then each writeback will release the largest amount of memory. This patch applies the same solution and strategy as for recompression target selection: pp control (post-process) with 16 buckets of candidate pp slots. Slots are assigned to pp buckets based on sizes - the larger the slot the higher the group index. This gives us sorted by size lists of candidate slots (in linear time), so that among post-processing candidate slots we always select the largest ones first and maximize the memory saving. TEST ==== A very simple demonstration: zram is configured with a writeback device. A limited writeback (wb_limit 2500 pages) is performed then, with a log of sizes of slots that were written back. You can see that patched zram selects slots for recompression in significantly different manner, which leads to higher memory savings (see column #2 of mm_stat output). BASE ---- *** initial state of zram device /sys/block/zram0/mm_stat 1750327296 619765836 631902208 0 631902208 1 0 34278 34278 *** writeback idle wb_limit 2500 /sys/block/zram0/mm_stat 1750327296 617622333 631578624 0 631902208 1 0 34278 34278 Sizes of selected objects for writeback: ... 193 349 46 46 46 46 852 1002 543 162 107 49 34 34 34 ... PATCHED ------- *** initial state of zram device /sys/block/zram0/mm_stat 1750319104 619760957 631992320 0 631992320 1 0 34278 34278 *** writeback idle wb_limit 2500 /sys/block/zram0/mm_stat 1750319104 612672056 626135040 0 631992320 1 0 34278 34278 Sizes of selected objects for writeback: ... 3667 3580 3581 3580 3581 3581 3581 3231 3211 3203 3231 3246 ... Note, pp-slots are not strictly sorted, there is a PP_BUCKET_SIZE_RANGE variation of sizes within particular bucket. Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: Sergey Senozhatsky <[email protected]> Cc: Minchan Kim <[email protected]> Signed-off-by: Andrew Morton <[email protected]> (cherry picked from commit 330edc2) Bug: 446676432 Change-Id: I2f0f4dd79f9bd4fc2e8d773e7bc2f29e2903f4ce Signed-off-by: David Stevens <[email protected]>
1 parent 5fb9b14 commit e43fd1d

File tree

1 file changed

+64
-19
lines changed

1 file changed

+64
-19
lines changed

drivers/block/zram/zram_drv.c

Lines changed: 64 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ static void zram_accessed(struct zram *zram, u32 index)
184184
#endif
185185
}
186186

187-
#ifdef CONFIG_ZRAM_MULTI_COMP
187+
#if defined CONFIG_ZRAM_WRITEBACK || defined CONFIG_ZRAM_MULTI_COMP
188188
struct zram_pp_slot {
189189
unsigned long index;
190190
struct list_head entry;
@@ -700,11 +700,57 @@ static void read_from_bdev_async(struct zram *zram, struct page *page,
700700
#define IDLE_WRITEBACK (1<<1)
701701
#define INCOMPRESSIBLE_WRITEBACK (1<<2)
702702

703+
static int scan_slots_for_writeback(struct zram *zram, u32 mode,
704+
unsigned long nr_pages,
705+
unsigned long index,
706+
struct zram_pp_ctl *ctl)
707+
{
708+
struct zram_pp_slot *pps = NULL;
709+
710+
for (; nr_pages != 0; index++, nr_pages--) {
711+
if (!pps)
712+
pps = kmalloc(sizeof(*pps), GFP_KERNEL);
713+
if (!pps)
714+
return -ENOMEM;
715+
716+
INIT_LIST_HEAD(&pps->entry);
717+
718+
zram_slot_lock(zram, index);
719+
if (!zram_allocated(zram, index))
720+
goto next;
721+
722+
if (zram_test_flag(zram, index, ZRAM_WB) ||
723+
zram_test_flag(zram, index, ZRAM_SAME))
724+
goto next;
725+
726+
if (mode & IDLE_WRITEBACK &&
727+
!zram_test_flag(zram, index, ZRAM_IDLE))
728+
goto next;
729+
if (mode & HUGE_WRITEBACK &&
730+
!zram_test_flag(zram, index, ZRAM_HUGE))
731+
goto next;
732+
if (mode & INCOMPRESSIBLE_WRITEBACK &&
733+
!zram_test_flag(zram, index, ZRAM_INCOMPRESSIBLE))
734+
goto next;
735+
736+
pps->index = index;
737+
place_pp_slot(zram, ctl, pps);
738+
pps = NULL;
739+
next:
740+
zram_slot_unlock(zram, index);
741+
}
742+
743+
kfree(pps);
744+
return 0;
745+
}
746+
703747
static ssize_t writeback_store(struct device *dev,
704748
struct device_attribute *attr, const char *buf, size_t len)
705749
{
706750
struct zram *zram = dev_to_zram(dev);
707751
unsigned long nr_pages = zram->disksize >> PAGE_SHIFT;
752+
struct zram_pp_ctl *ctl = NULL;
753+
struct zram_pp_slot *pps;
708754
unsigned long index = 0;
709755
struct bio bio;
710756
struct bio_vec bio_vec;
@@ -756,7 +802,15 @@ static ssize_t writeback_store(struct device *dev,
756802
goto release_init_lock;
757803
}
758804

759-
for (; nr_pages != 0; index++, nr_pages--) {
805+
ctl = init_pp_ctl();
806+
if (!ctl) {
807+
ret = -ENOMEM;
808+
goto release_init_lock;
809+
}
810+
811+
scan_slots_for_writeback(zram, mode, nr_pages, index, ctl);
812+
813+
while ((pps = select_pp_slot(ctl))) {
760814
spin_lock(&zram->wb_limit_lock);
761815
if (zram->wb_limit_enable && !zram->bd_wb_limit) {
762816
spin_unlock(&zram->wb_limit_lock);
@@ -773,25 +827,10 @@ static ssize_t writeback_store(struct device *dev,
773827
}
774828
}
775829

830+
index = pps->index;
776831
zram_slot_lock(zram, index);
777-
if (!zram_allocated(zram, index))
778-
goto next;
779-
780-
if (zram_test_flag(zram, index, ZRAM_WB) ||
781-
zram_test_flag(zram, index, ZRAM_SAME) ||
782-
zram_test_flag(zram, index, ZRAM_UNDER_WB))
783-
goto next;
784-
785-
if (mode & IDLE_WRITEBACK &&
786-
!zram_test_flag(zram, index, ZRAM_IDLE))
787-
goto next;
788-
if (mode & HUGE_WRITEBACK &&
789-
!zram_test_flag(zram, index, ZRAM_HUGE))
790-
goto next;
791-
if (mode & INCOMPRESSIBLE_WRITEBACK &&
792-
!zram_test_flag(zram, index, ZRAM_INCOMPRESSIBLE))
832+
if (!zram_test_flag(zram, index, ZRAM_PP_SLOT))
793833
goto next;
794-
795834
/*
796835
* Clearing ZRAM_UNDER_WB is duty of caller.
797836
* IOW, zram_free_page never clear it.
@@ -805,6 +844,8 @@ static ssize_t writeback_store(struct device *dev,
805844
zram_clear_flag(zram, index, ZRAM_UNDER_WB);
806845
zram_clear_flag(zram, index, ZRAM_IDLE);
807846
zram_slot_unlock(zram, index);
847+
848+
release_pp_slot(zram, pps);
808849
continue;
809850
}
810851

@@ -823,6 +864,8 @@ static ssize_t writeback_store(struct device *dev,
823864
zram_clear_flag(zram, index, ZRAM_UNDER_WB);
824865
zram_clear_flag(zram, index, ZRAM_IDLE);
825866
zram_slot_unlock(zram, index);
867+
868+
release_pp_slot(zram, pps);
826869
/*
827870
* BIO errors are not fatal, we continue and simply
828871
* attempt to writeback the remaining objects (pages).
@@ -865,12 +908,14 @@ static ssize_t writeback_store(struct device *dev,
865908
spin_unlock(&zram->wb_limit_lock);
866909
next:
867910
zram_slot_unlock(zram, index);
911+
release_pp_slot(zram, pps);
868912
}
869913

870914
if (blk_idx)
871915
free_block_bdev(zram, blk_idx);
872916
__free_page(page);
873917
release_init_lock:
918+
release_pp_ctl(zram, ctl);
874919
atomic_set(&zram->pp_in_progress, 0);
875920
up_read(&zram->init_lock);
876921

0 commit comments

Comments
 (0)