Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

zram: drop pp_in_progress

pp_in_progress makes sure that only one post-processing (writeback or
recomrpession) is active at any given time. Functionality wise it,
basically, shadows zram init_lock, when init_lock is acquired in writer
mode.

Switch recompress_store() and writeback_store() to take zram init_lock in
writer mode, like all store() sysfs handlers should do, so that we can
drop pp_in_progress. Recompression and writeback can be somewhat slow, so
holding init_lock in writer mode can block zram attrs reads, but in
reality the only zram attrs reads that take place are mm_stat reads, and
usually it's the same process that reads mm_stat and does recompression or
writeback.

Link: https://lkml.kernel.org/r/20251216071342.687993-1-senozhatsky@chromium.org
Signed-off-by: Sergey Senozhatsky <senozhatsky@chromium.org>
Suggested-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Brian Geffon <bgeffon@google.com>
Cc: Minchan Kim <minchan@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

Sergey Senozhatsky and committed by
Andrew Morton
657a81fe 9082f24b

+8 -25
+8 -24
drivers/block/zram/zram_drv.c
··· 902 902 903 903 static void zram_account_writeback_rollback(struct zram *zram) 904 904 { 905 - lockdep_assert_held_read(&zram->init_lock); 905 + lockdep_assert_held_write(&zram->init_lock); 906 906 907 907 if (zram->wb_limit_enable) 908 908 zram->bd_wb_limit += 1UL << (PAGE_SHIFT - 12); ··· 910 910 911 911 static void zram_account_writeback_submit(struct zram *zram) 912 912 { 913 - lockdep_assert_held_read(&zram->init_lock); 913 + lockdep_assert_held_write(&zram->init_lock); 914 914 915 915 if (zram->wb_limit_enable && zram->bd_wb_limit > 0) 916 916 zram->bd_wb_limit -= 1UL << (PAGE_SHIFT - 12); ··· 1264 1264 ssize_t ret = len; 1265 1265 int err, mode = 0; 1266 1266 1267 - guard(rwsem_read)(&zram->init_lock); 1267 + guard(rwsem_write)(&zram->init_lock); 1268 1268 if (!init_done(zram)) 1269 1269 return -EINVAL; 1270 1270 1271 - /* Do not permit concurrent post-processing actions. */ 1272 - if (atomic_xchg(&zram->pp_in_progress, 1)) 1273 - return -EAGAIN; 1274 - 1275 - if (!zram->backing_dev) { 1276 - ret = -ENODEV; 1277 - goto out; 1278 - } 1271 + if (!zram->backing_dev) 1272 + return -ENODEV; 1279 1273 1280 1274 pp_ctl = init_pp_ctl(); 1281 - if (!pp_ctl) { 1282 - ret = -ENOMEM; 1283 - goto out; 1284 - } 1275 + if (!pp_ctl) 1276 + return -ENOMEM; 1285 1277 1286 1278 wb_ctl = init_wb_ctl(zram); 1287 1279 if (!wb_ctl) { ··· 1350 1358 out: 1351 1359 release_pp_ctl(zram, pp_ctl); 1352 1360 release_wb_ctl(wb_ctl); 1353 - atomic_set(&zram->pp_in_progress, 0); 1354 1361 1355 1362 return ret; 1356 1363 } ··· 2610 2619 if (threshold >= huge_class_size) 2611 2620 return -EINVAL; 2612 2621 2613 - guard(rwsem_read)(&zram->init_lock); 2622 + guard(rwsem_write)(&zram->init_lock); 2614 2623 if (!init_done(zram)) 2615 2624 return -EINVAL; 2616 - 2617 - /* Do not permit concurrent post-processing actions. */ 2618 - if (atomic_xchg(&zram->pp_in_progress, 1)) 2619 - return -EAGAIN; 2620 2625 2621 2626 if (algo) { 2622 2627 bool found = false; ··· 2684 2697 if (page) 2685 2698 __free_page(page); 2686 2699 release_pp_ctl(zram, ctl); 2687 - atomic_set(&zram->pp_in_progress, 0); 2688 2700 return ret; 2689 2701 } 2690 2702 #endif ··· 2874 2888 zram->disksize = 0; 2875 2889 zram_destroy_comps(zram); 2876 2890 memset(&zram->stats, 0, sizeof(zram->stats)); 2877 - atomic_set(&zram->pp_in_progress, 0); 2878 2891 reset_bdev(zram); 2879 2892 2880 2893 comp_algorithm_set(zram, ZRAM_PRIMARY_COMP, default_compressor); ··· 3109 3124 zram->disk->fops = &zram_devops; 3110 3125 zram->disk->private_data = zram; 3111 3126 snprintf(zram->disk->disk_name, 16, "zram%d", device_id); 3112 - atomic_set(&zram->pp_in_progress, 0); 3113 3127 zram_comp_params_reset(zram); 3114 3128 comp_algorithm_set(zram, ZRAM_PRIMARY_COMP, default_compressor); 3115 3129
-1
drivers/block/zram/zram_drv.h
··· 143 143 #ifdef CONFIG_ZRAM_MEMORY_TRACKING 144 144 struct dentry *debugfs_dir; 145 145 #endif 146 - atomic_t pp_in_progress; 147 146 }; 148 147 #endif