* [PATCH v3 1/3] zram: Replace bit spinlocks with a spinlock_t.
2024-07-05 12:49 [PATCH v3 0/3] zram: Replace bit spinlocks with a spinlock_t Sebastian Andrzej Siewior
@ 2024-07-05 12:49 ` Sebastian Andrzej Siewior
2024-07-05 12:49 ` [PATCH v3 2/3] zram: Remove ZRAM_LOCK Sebastian Andrzej Siewior
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Sebastian Andrzej Siewior @ 2024-07-05 12:49 UTC (permalink / raw)
To: linux-block, linux-kernel
Cc: Jens Axboe, Mike Galbraith, Minchan Kim, Sergey Senozhatsky,
Thomas Gleixner, Alexander Lobakin, Sebastian Andrzej Siewior
From: Mike Galbraith <umgwanakikbuti@gmail.com>
The bit spinlock disables preemption. The spinlock_t lock becomes a sleeping
lock on PREEMPT_RT and it can not be acquired in this context. In this locked
section, zs_free() acquires a zs_pool::lock, and there is access to
zram::wb_limit_lock.
Add a spinlock_t for locking. Keep the set/ clear ZRAM_LOCK bit after
the lock has been acquired/ dropped. The size of struct zram_table_entry
increases by 4 bytes due to lock and additional 4 bytes padding with
CONFIG_ZRAM_TRACK_ENTRY_ACTIME enabled.
Signed-off-by: Mike Galbraith <umgwanakikbuti@gmail.com>
Reviewed-by: Sergey Senozhatsky <senozhatsky@chromium.org>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
drivers/block/zram/zram_drv.c | 20 +++++++++++++++++---
drivers/block/zram/zram_drv.h | 1 +
2 files changed, 18 insertions(+), 3 deletions(-)
diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
index 3acd7006ad2cc..72006e6e34883 100644
--- a/drivers/block/zram/zram_drv.c
+++ b/drivers/block/zram/zram_drv.c
@@ -57,19 +57,32 @@ static void zram_free_page(struct zram *zram, size_t index);
static int zram_read_page(struct zram *zram, struct page *page, u32 index,
struct bio *parent);
+static void zram_meta_init_table_locks(struct zram *zram, size_t num_pages)
+{
+ for (size_t index = 0; index < num_pages; index++)
+ spin_lock_init(&zram->table[index].lock);
+}
+
static int zram_slot_trylock(struct zram *zram, u32 index)
{
- return bit_spin_trylock(ZRAM_LOCK, &zram->table[index].flags);
+ int ret;
+
+ ret = spin_trylock(&zram->table[index].lock);
+ if (ret)
+ __set_bit(ZRAM_LOCK, &zram->table[index].flags);
+ return ret;
}
static void zram_slot_lock(struct zram *zram, u32 index)
{
- bit_spin_lock(ZRAM_LOCK, &zram->table[index].flags);
+ spin_lock(&zram->table[index].lock);
+ __set_bit(ZRAM_LOCK, &zram->table[index].flags);
}
static void zram_slot_unlock(struct zram *zram, u32 index)
{
- bit_spin_unlock(ZRAM_LOCK, &zram->table[index].flags);
+ __clear_bit(ZRAM_LOCK, &zram->table[index].flags);
+ spin_unlock(&zram->table[index].lock);
}
static inline bool init_done(struct zram *zram)
@@ -1226,6 +1239,7 @@ static bool zram_meta_alloc(struct zram *zram, u64 disksize)
if (!huge_class_size)
huge_class_size = zs_huge_class_size(zram->mem_pool);
+ zram_meta_init_table_locks(zram, num_pages);
return true;
}
diff --git a/drivers/block/zram/zram_drv.h b/drivers/block/zram/zram_drv.h
index 35e3221446292..dcc3c106ce713 100644
--- a/drivers/block/zram/zram_drv.h
+++ b/drivers/block/zram/zram_drv.h
@@ -69,6 +69,7 @@ struct zram_table_entry {
unsigned long element;
};
unsigned long flags;
+ spinlock_t lock;
#ifdef CONFIG_ZRAM_TRACK_ENTRY_ACTIME
ktime_t ac_time;
#endif
--
2.45.2
^ permalink raw reply related [flat|nested] 5+ messages in thread* [PATCH v3 2/3] zram: Remove ZRAM_LOCK
2024-07-05 12:49 [PATCH v3 0/3] zram: Replace bit spinlocks with a spinlock_t Sebastian Andrzej Siewior
2024-07-05 12:49 ` [PATCH v3 1/3] " Sebastian Andrzej Siewior
@ 2024-07-05 12:49 ` Sebastian Andrzej Siewior
2024-07-05 12:49 ` [PATCH v3 3/3] zram: Shrink zram_table_entry::flags Sebastian Andrzej Siewior
2024-08-08 9:03 ` [PATCH v3 0/3] zram: Replace bit spinlocks with a spinlock_t Sebastian Andrzej Siewior
3 siblings, 0 replies; 5+ messages in thread
From: Sebastian Andrzej Siewior @ 2024-07-05 12:49 UTC (permalink / raw)
To: linux-block, linux-kernel
Cc: Jens Axboe, Mike Galbraith, Minchan Kim, Sergey Senozhatsky,
Thomas Gleixner, Alexander Lobakin, Sebastian Andrzej Siewior
The ZRAM_LOCK was used for locking and after the addition of spinlock_t
the bit set and cleared but there no reader of it.
Remove the ZRAM_LOCK bit.
Reviewed-by: Sergey Senozhatsky <senozhatsky@chromium.org>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
drivers/block/zram/zram_drv.c | 11 ++---------
drivers/block/zram/zram_drv.h | 4 +---
2 files changed, 3 insertions(+), 12 deletions(-)
diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
index 72006e6e34883..e683a9fc68b6c 100644
--- a/drivers/block/zram/zram_drv.c
+++ b/drivers/block/zram/zram_drv.c
@@ -65,23 +65,16 @@ static void zram_meta_init_table_locks(struct zram *zram, size_t num_pages)
static int zram_slot_trylock(struct zram *zram, u32 index)
{
- int ret;
-
- ret = spin_trylock(&zram->table[index].lock);
- if (ret)
- __set_bit(ZRAM_LOCK, &zram->table[index].flags);
- return ret;
+ return spin_trylock(&zram->table[index].lock);
}
static void zram_slot_lock(struct zram *zram, u32 index)
{
spin_lock(&zram->table[index].lock);
- __set_bit(ZRAM_LOCK, &zram->table[index].flags);
}
static void zram_slot_unlock(struct zram *zram, u32 index)
{
- __clear_bit(ZRAM_LOCK, &zram->table[index].flags);
spin_unlock(&zram->table[index].lock);
}
@@ -1297,7 +1290,7 @@ static void zram_free_page(struct zram *zram, size_t index)
zram_set_handle(zram, index, 0);
zram_set_obj_size(zram, index, 0);
WARN_ON_ONCE(zram->table[index].flags &
- ~(1UL << ZRAM_LOCK | 1UL << ZRAM_UNDER_WB));
+ ~(1UL << ZRAM_UNDER_WB));
}
/*
diff --git a/drivers/block/zram/zram_drv.h b/drivers/block/zram/zram_drv.h
index dcc3c106ce713..262fa960a0783 100644
--- a/drivers/block/zram/zram_drv.h
+++ b/drivers/block/zram/zram_drv.h
@@ -45,9 +45,7 @@
/* Flags for zram pages (table[page_no].flags) */
enum zram_pageflags {
- /* zram slot is locked */
- ZRAM_LOCK = ZRAM_FLAG_SHIFT,
- ZRAM_SAME, /* Page consists the same element */
+ ZRAM_SAME = ZRAM_FLAG_SHIFT, /* Page consists the same element */
ZRAM_WB, /* page is stored on backing_device */
ZRAM_UNDER_WB, /* page is under writeback */
ZRAM_HUGE, /* Incompressible page */
--
2.45.2
^ permalink raw reply related [flat|nested] 5+ messages in thread* [PATCH v3 3/3] zram: Shrink zram_table_entry::flags.
2024-07-05 12:49 [PATCH v3 0/3] zram: Replace bit spinlocks with a spinlock_t Sebastian Andrzej Siewior
2024-07-05 12:49 ` [PATCH v3 1/3] " Sebastian Andrzej Siewior
2024-07-05 12:49 ` [PATCH v3 2/3] zram: Remove ZRAM_LOCK Sebastian Andrzej Siewior
@ 2024-07-05 12:49 ` Sebastian Andrzej Siewior
2024-08-08 9:03 ` [PATCH v3 0/3] zram: Replace bit spinlocks with a spinlock_t Sebastian Andrzej Siewior
3 siblings, 0 replies; 5+ messages in thread
From: Sebastian Andrzej Siewior @ 2024-07-05 12:49 UTC (permalink / raw)
To: linux-block, linux-kernel
Cc: Jens Axboe, Mike Galbraith, Minchan Kim, Sergey Senozhatsky,
Thomas Gleixner, Alexander Lobakin, Sebastian Andrzej Siewior
The zram_table_entry::flags member is of type long and uses 8 bytes on a
64bit architecture. With a PAGE_SIZE of 256KiB we have PAGE_SHIFT of 18
which in turn leads to __NR_ZRAM_PAGEFLAGS = 27. This still fits in an
ordinary integer.
By reducing it the size of `flags' to four bytes, the size of the struct
goes back to 16 bytes. The padding between the lock and ac_time (if
enabled) is also gone.
Make zram_table_entry::flags an unsigned int and update the build test
to reflect the change.
Reviewed-by: Sergey Senozhatsky <senozhatsky@chromium.org>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
drivers/block/zram/zram_drv.c | 3 ++-
drivers/block/zram/zram_drv.h | 2 +-
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
index e683a9fc68b6c..dde45a084733f 100644
--- a/drivers/block/zram/zram_drv.c
+++ b/drivers/block/zram/zram_drv.c
@@ -2410,9 +2410,10 @@ static void destroy_devices(void)
static int __init zram_init(void)
{
+ struct zram_table_entry zram_te;
int ret;
- BUILD_BUG_ON(__NR_ZRAM_PAGEFLAGS > BITS_PER_LONG);
+ BUILD_BUG_ON(__NR_ZRAM_PAGEFLAGS > sizeof(zram_te.flags) * 8);
ret = cpuhp_setup_state_multi(CPUHP_ZCOMP_PREPARE, "block/zram:prepare",
zcomp_cpu_up_prepare, zcomp_cpu_dead);
diff --git a/drivers/block/zram/zram_drv.h b/drivers/block/zram/zram_drv.h
index 262fa960a0783..531cefc666682 100644
--- a/drivers/block/zram/zram_drv.h
+++ b/drivers/block/zram/zram_drv.h
@@ -66,7 +66,7 @@ struct zram_table_entry {
unsigned long handle;
unsigned long element;
};
- unsigned long flags;
+ unsigned int flags;
spinlock_t lock;
#ifdef CONFIG_ZRAM_TRACK_ENTRY_ACTIME
ktime_t ac_time;
--
2.45.2
^ permalink raw reply related [flat|nested] 5+ messages in thread* Re: [PATCH v3 0/3] zram: Replace bit spinlocks with a spinlock_t.
2024-07-05 12:49 [PATCH v3 0/3] zram: Replace bit spinlocks with a spinlock_t Sebastian Andrzej Siewior
` (2 preceding siblings ...)
2024-07-05 12:49 ` [PATCH v3 3/3] zram: Shrink zram_table_entry::flags Sebastian Andrzej Siewior
@ 2024-08-08 9:03 ` Sebastian Andrzej Siewior
3 siblings, 0 replies; 5+ messages in thread
From: Sebastian Andrzej Siewior @ 2024-08-08 9:03 UTC (permalink / raw)
To: linux-block, linux-kernel
Cc: Jens Axboe, Mike Galbraith, Minchan Kim, Sergey Senozhatsky,
Thomas Gleixner, Alexander Lobakin
On 2024-07-05 14:49:13 [+0200], To linux-block@vger.kernel.org wrote:
Hi,
> this is follow up to the previous posting, making the lock
> unconditionally. The original problem with bit spinlock is that it
> disabled preemption and the following operations (within the atomic
> section) perform operations that may sleep on PREEMPT_RT. Mike expressed
> that he would like to keep using zram on PREEMPT_RT.
>
> v2…v3 https://lore.kernel.org/all/20240620153556.777272-1-bigeasy@linutronix.de/
> - Do "size_t index" within the for loop.
Can this be applied, please? Or v2 ;)
Sebastian
^ permalink raw reply [flat|nested] 5+ messages in thread