Skip to content

Commit f09307f

Browse files
sergey-senozhatskysmb49
authored andcommitted
zram: permit only one post-processing operation at a time
BugLink: https://bugs.launchpad.net/bugs/2101915 [ Upstream commit 58652f2 ] Both recompress and writeback soon will unlock slots during processing, which makes things too complex wrt possible race-conditions. We still want to clear PP_SLOT in slot_free, because this is how we figure out that slot that was selected for post-processing has been released under us and when we start post-processing we check if slot still has PP_SLOT set. At the same time, theoretically, we can have something like this: CPU0 CPU1 recompress scan slots set PP_SLOT unlock slot slot_free clear PP_SLOT allocate PP_SLOT writeback scan slots set PP_SLOT unlock slot select PP-slot test PP_SLOT So recompress will not detect that slot has been re-used and re-selected for concurrent writeback post-processing. Make sure that we only permit on post-processing operation at a time. So now recompress and writeback post-processing don't race against each other, we only need to handle slot re-use (slot_free and write), which is handled individually by each pp operation. Having recompress and writeback competing for the same slots is not exactly good anyway (can't imagine anyone doing that). Link: https://lkml.kernel.org/r/20240917021020.883356-3-senozhatsky@chromium.org Signed-off-by: Sergey Senozhatsky <senozhatsky@chromium.org> Cc: Minchan Kim <minchan@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Stable-dep-of: f364cde ("zram: fix NULL pointer in comp_algorithm_show()") Signed-off-by: Sasha Levin <sashal@kernel.org> Signed-off-by: Koichiro Den <koichiro.den@canonical.com> Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
1 parent 661db4e commit f09307f

File tree

3 files changed

+19
-0
lines changed

3 files changed

+19
-0
lines changed

Documentation/admin-guide/blockdev/zram.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ The list of possible return codes:
4747
-ENOMEM zram was not able to allocate enough memory to fulfil your
4848
needs.
4949
-EINVAL invalid input has been provided.
50+
-EAGAIN re-try operation later (e.g. when attempting to run recompress
51+
and writeback simultaneously).
5052
======== =============================================================
5153

5254
If you use 'echo', the returned value is set by the 'echo' utility,

drivers/block/zram/zram_drv.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -640,6 +640,12 @@ static ssize_t writeback_store(struct device *dev,
640640
goto release_init_lock;
641641
}
642642

643+
/* Do not permit concurrent post-processing actions. */
644+
if (atomic_xchg(&zram->pp_in_progress, 1)) {
645+
up_read(&zram->init_lock);
646+
return -EAGAIN;
647+
}
648+
643649
if (!zram->backing_dev) {
644650
ret = -ENODEV;
645651
goto release_init_lock;
@@ -766,6 +772,7 @@ static ssize_t writeback_store(struct device *dev,
766772
free_block_bdev(zram, blk_idx);
767773
__free_page(page);
768774
release_init_lock:
775+
atomic_set(&zram->pp_in_progress, 0);
769776
up_read(&zram->init_lock);
770777

771778
return ret;
@@ -1765,6 +1772,12 @@ static ssize_t recompress_store(struct device *dev,
17651772
goto release_init_lock;
17661773
}
17671774

1775+
/* Do not permit concurrent post-processing actions. */
1776+
if (atomic_xchg(&zram->pp_in_progress, 1)) {
1777+
up_read(&zram->init_lock);
1778+
return -EAGAIN;
1779+
}
1780+
17681781
if (algo) {
17691782
bool found = false;
17701783

@@ -1829,6 +1842,7 @@ static ssize_t recompress_store(struct device *dev,
18291842
__free_page(page);
18301843

18311844
release_init_lock:
1845+
atomic_set(&zram->pp_in_progress, 0);
18321846
up_read(&zram->init_lock);
18331847
return ret;
18341848
}
@@ -2014,6 +2028,7 @@ static void zram_reset_device(struct zram *zram)
20142028
zram->disksize = 0;
20152029
zram_destroy_comps(zram);
20162030
memset(&zram->stats, 0, sizeof(zram->stats));
2031+
atomic_set(&zram->pp_in_progress, 0);
20172032
reset_bdev(zram);
20182033

20192034
comp_algorithm_set(zram, ZRAM_PRIMARY_COMP, default_compressor);
@@ -2224,6 +2239,7 @@ static int zram_add(void)
22242239
zram->disk->fops = &zram_devops;
22252240
zram->disk->private_data = zram;
22262241
snprintf(zram->disk->disk_name, 16, "zram%d", device_id);
2242+
atomic_set(&zram->pp_in_progress, 0);
22272243

22282244
/* Actual capacity set using sysfs (/sys/block/zram<id>/disksize */
22292245
set_capacity(zram->disk, 0);

drivers/block/zram/zram_drv.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,5 +139,6 @@ struct zram {
139139
#ifdef CONFIG_ZRAM_MEMORY_TRACKING
140140
struct dentry *debugfs_dir;
141141
#endif
142+
atomic_t pp_in_progress;
142143
};
143144
#endif

0 commit comments

Comments
 (0)