]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
zram: protect recomp_algorithm_show() with ->init_lock
authorSergey Senozhatsky <senozhatsky@chromium.org>
Tue, 5 Aug 2025 10:19:29 +0000 (19:19 +0900)
committerAndrew Morton <akpm@linux-foundation.org>
Fri, 12 Sep 2025 00:24:37 +0000 (17:24 -0700)
sysfs handlers should be called under ->init_lock and are not supposed to
unlock it until return, otherwise e.g.  a concurrent reset() can occur.
There is one handler that breaks that rule: recomp_algorithm_show().

Move ->init_lock handling outside of __comp_algorithm_show() (also drop it
and call zcomp_available_show() directly) so that the entire
recomp_algorithm_show() loop is protected by the lock, as opposed to
protecting individual iterations.

The patch does not need to go to -stable, as it does not fix any
runtime errors (at least I can't think of any).  It makes
recomp_algorithm_show() "atomic" w.r.t.  zram reset() (just like the
rest of zram sysfs show() handlers), that's a pretty minor change.

Link: https://lkml.kernel.org/r/20250805101946.1774112-1-senozhatsky@chromium.org
Signed-off-by: Sergey Senozhatsky <senozhatsky@chromium.org>
Reported-by: Seyediman Seyedarab <imandevel@gmail.com>
Suggested-by: Seyediman Seyedarab <imandevel@gmail.com>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Minchan Kim <minchan@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
drivers/block/zram/zram_drv.c

index f31652085adcb6494543bdeaf191519d2712fdaa..78b56cd7698e6e231d54925f02c286cde8543945 100644 (file)
@@ -1225,18 +1225,6 @@ static void comp_algorithm_set(struct zram *zram, u32 prio, const char *alg)
        zram->comp_algs[prio] = alg;
 }
 
-static ssize_t __comp_algorithm_show(struct zram *zram, u32 prio,
-                                    char *buf, ssize_t at)
-{
-       ssize_t sz;
-
-       down_read(&zram->init_lock);
-       sz = zcomp_available_show(zram->comp_algs[prio], buf, at);
-       up_read(&zram->init_lock);
-
-       return sz;
-}
-
 static int __comp_algorithm_store(struct zram *zram, u32 prio, const char *buf)
 {
        char *compressor;
@@ -1387,8 +1375,12 @@ static ssize_t comp_algorithm_show(struct device *dev,
                                   char *buf)
 {
        struct zram *zram = dev_to_zram(dev);
+       ssize_t sz;
 
-       return __comp_algorithm_show(zram, ZRAM_PRIMARY_COMP, buf, 0);
+       down_read(&zram->init_lock);
+       sz = zcomp_available_show(zram->comp_algs[ZRAM_PRIMARY_COMP], buf, 0);
+       up_read(&zram->init_lock);
+       return sz;
 }
 
 static ssize_t comp_algorithm_store(struct device *dev,
@@ -1412,14 +1404,15 @@ static ssize_t recomp_algorithm_show(struct device *dev,
        ssize_t sz = 0;
        u32 prio;
 
+       down_read(&zram->init_lock);
        for (prio = ZRAM_SECONDARY_COMP; prio < ZRAM_MAX_COMPS; prio++) {
                if (!zram->comp_algs[prio])
                        continue;
 
                sz += sysfs_emit_at(buf, sz, "#%d: ", prio);
-               sz += __comp_algorithm_show(zram, prio, buf, sz);
+               sz += zcomp_available_show(zram->comp_algs[prio], buf, sz);
        }
-
+       up_read(&zram->init_lock);
        return sz;
 }