mirror of
https://github.com/torvalds/linux.git
synced 2026-09-12 12:34:02 +02:00
zram: fix slot lock bit position on big-endian 64-bit
The slot lock is a bit operation on the whole __lock word, which flags and
ac_time alias as two u32s. On little-endian the lock bit lands in the
position ZRAM_ENTRY_LOCK reserves in flags, so the aliasing works out. On
64-bit big-endian it lands in ac_time instead: with
ZRAM_TRACK_ENTRY_ACTIME enabled, storing the access time from
mark_slot_accessed() or slot_free() wipes out the held lock bit, letting
another CPU take the same slot lock; an access time value with that bit
set makes the slot look locked forever.
Shift the lock bit into the flags half of the word on big-endian 64-bit.
Link: https://lore.kernel.org/20260810202241.2436603-1-devnexen@gmail.com
Fixes: 2e8ff2f51d ("zram: use u32 for entry ac_time tracking")
Signed-off-by: David Carlier <devnexen@gmail.com>
Reviewed-by: Sergey Senozhatsky <senozhatsky@chromium.org>
Cc: Minchan Kim <minchan@kernel.org>
Cc: <stable@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This commit is contained in:
parent
cdd719b3f2
commit
a8b5875741
|
|
@ -74,7 +74,7 @@ static __must_check bool slot_trylock(struct zram *zram, unsigned long index)
|
|||
{
|
||||
unsigned long *lock = &zram->table[index].__lock;
|
||||
|
||||
if (!test_and_set_bit_lock(ZRAM_ENTRY_LOCK, lock)) {
|
||||
if (!test_and_set_bit_lock(ZRAM_ENTRY_LOCK_BIT, lock)) {
|
||||
mutex_acquire(&zram->table_lock_map, 0, 1, _RET_IP_);
|
||||
lock_acquired(&zram->table_lock_map, _RET_IP_);
|
||||
return true;
|
||||
|
|
@ -88,7 +88,7 @@ static void slot_lock(struct zram *zram, unsigned long index)
|
|||
unsigned long *lock = &zram->table[index].__lock;
|
||||
|
||||
mutex_acquire(&zram->table_lock_map, 0, 0, _RET_IP_);
|
||||
wait_on_bit_lock(lock, ZRAM_ENTRY_LOCK, TASK_UNINTERRUPTIBLE);
|
||||
wait_on_bit_lock(lock, ZRAM_ENTRY_LOCK_BIT, TASK_UNINTERRUPTIBLE);
|
||||
lock_acquired(&zram->table_lock_map, _RET_IP_);
|
||||
}
|
||||
|
||||
|
|
@ -97,7 +97,7 @@ static void slot_unlock(struct zram *zram, unsigned long index)
|
|||
unsigned long *lock = &zram->table[index].__lock;
|
||||
|
||||
mutex_release(&zram->table_lock_map, _RET_IP_);
|
||||
clear_and_wake_up_bit(ZRAM_ENTRY_LOCK, lock);
|
||||
clear_and_wake_up_bit(ZRAM_ENTRY_LOCK_BIT, lock);
|
||||
}
|
||||
|
||||
static inline bool init_done(struct zram *zram)
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
#ifndef _ZRAM_DRV_H_
|
||||
#define _ZRAM_DRV_H_
|
||||
|
||||
#include <asm/byteorder.h>
|
||||
#include <linux/rwsem.h>
|
||||
#include <linux/zsmalloc.h>
|
||||
|
||||
|
|
@ -57,6 +58,19 @@ enum zram_pageflags {
|
|||
__NR_ZRAM_PAGEFLAGS,
|
||||
};
|
||||
|
||||
/*
|
||||
* The slot lock is a bit-wait lock on the whole __lock word, while
|
||||
* flags and ac_time alias that word as two u32s. The lock bit must
|
||||
* land in the slot that ZRAM_ENTRY_LOCK reserves in attr.flags; on
|
||||
* 64-bit big-endian the flags word maps to the upper half of __lock,
|
||||
* so the bit position has to be shifted up.
|
||||
*/
|
||||
#if defined(CONFIG_64BIT) && defined(__BIG_ENDIAN)
|
||||
#define ZRAM_ENTRY_LOCK_BIT (ZRAM_ENTRY_LOCK + 32)
|
||||
#else
|
||||
#define ZRAM_ENTRY_LOCK_BIT ZRAM_ENTRY_LOCK
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Allocated for each disk page. We use bit-lock (ZRAM_ENTRY_LOCK bit
|
||||
* of flags) to save memory. There can be plenty of entries and standard
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user