Patch "zram: permit only one post-processing operation at a time" has been added to the 6.12-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    zram: permit only one post-processing operation at a time

to the 6.12-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     zram-permit-only-one-post-processing-operation-at-a-.patch
and it can be found in the queue-6.12 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit 4765419ecef2e1c673d628f0236a6868a7725979
Author: Sergey Senozhatsky <senozhatsky@xxxxxxxxxxxx>
Date:   Tue Sep 17 11:09:07 2024 +0900

    zram: permit only one post-processing operation at a time
    
    [ Upstream commit 58652f2b6d21f2874c9f060165ec7e03e8b1fc71 ]
    
    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@xxxxxxxxxxxx
    Signed-off-by: Sergey Senozhatsky <senozhatsky@xxxxxxxxxxxx>
    Cc: Minchan Kim <minchan@xxxxxxxxxx>
    Signed-off-by: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx>
    Stable-dep-of: f364cdeb3893 ("zram: fix NULL pointer in comp_algorithm_show()")
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/Documentation/admin-guide/blockdev/zram.rst b/Documentation/admin-guide/blockdev/zram.rst
index 678d70d6e1c3a..714a5171bfc0b 100644
--- a/Documentation/admin-guide/blockdev/zram.rst
+++ b/Documentation/admin-guide/blockdev/zram.rst
@@ -47,6 +47,8 @@ The list of possible return codes:
 -ENOMEM	  zram was not able to allocate enough memory to fulfil your
 	  needs.
 -EINVAL	  invalid input has been provided.
+-EAGAIN	  re-try operation later (e.g. when attempting to run recompress
+	  and writeback simultaneously).
 ========  =============================================================
 
 If you use 'echo', the returned value is set by the 'echo' utility,
diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
index ad9c9bc3ccfc5..b742dc246b0c1 100644
--- a/drivers/block/zram/zram_drv.c
+++ b/drivers/block/zram/zram_drv.c
@@ -626,6 +626,12 @@ static ssize_t writeback_store(struct device *dev,
 		goto release_init_lock;
 	}
 
+	/* Do not permit concurrent post-processing actions. */
+	if (atomic_xchg(&zram->pp_in_progress, 1)) {
+		up_read(&zram->init_lock);
+		return -EAGAIN;
+	}
+
 	if (!zram->backing_dev) {
 		ret = -ENODEV;
 		goto release_init_lock;
@@ -752,6 +758,7 @@ static ssize_t writeback_store(struct device *dev,
 		free_block_bdev(zram, blk_idx);
 	__free_page(page);
 release_init_lock:
+	atomic_set(&zram->pp_in_progress, 0);
 	up_read(&zram->init_lock);
 
 	return ret;
@@ -1881,6 +1888,12 @@ static ssize_t recompress_store(struct device *dev,
 		goto release_init_lock;
 	}
 
+	/* Do not permit concurrent post-processing actions. */
+	if (atomic_xchg(&zram->pp_in_progress, 1)) {
+		up_read(&zram->init_lock);
+		return -EAGAIN;
+	}
+
 	if (algo) {
 		bool found = false;
 
@@ -1948,6 +1961,7 @@ static ssize_t recompress_store(struct device *dev,
 	__free_page(page);
 
 release_init_lock:
+	atomic_set(&zram->pp_in_progress, 0);
 	up_read(&zram->init_lock);
 	return ret;
 }
@@ -2144,6 +2158,7 @@ static void zram_reset_device(struct zram *zram)
 	zram->disksize = 0;
 	zram_destroy_comps(zram);
 	memset(&zram->stats, 0, sizeof(zram->stats));
+	atomic_set(&zram->pp_in_progress, 0);
 	reset_bdev(zram);
 
 	comp_algorithm_set(zram, ZRAM_PRIMARY_COMP, default_compressor);
@@ -2381,6 +2396,7 @@ static int zram_add(void)
 	zram->disk->fops = &zram_devops;
 	zram->disk->private_data = zram;
 	snprintf(zram->disk->disk_name, 16, "zram%d", device_id);
+	atomic_set(&zram->pp_in_progress, 0);
 
 	/* Actual capacity set using sysfs (/sys/block/zram<id>/disksize */
 	set_capacity(zram->disk, 0);
diff --git a/drivers/block/zram/zram_drv.h b/drivers/block/zram/zram_drv.h
index cfc8c059db636..8acf9d2ee42b8 100644
--- a/drivers/block/zram/zram_drv.h
+++ b/drivers/block/zram/zram_drv.h
@@ -139,5 +139,6 @@ struct zram {
 #ifdef CONFIG_ZRAM_MEMORY_TRACKING
 	struct dentry *debugfs_dir;
 #endif
+	atomic_t pp_in_progress;
 };
 #endif




[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux