98 lines
3.0 KiB
Diff
98 lines
3.0 KiB
Diff
From: Mike Galbraith <umgwanakikbuti@gmail.com>
|
|
Date: Thu, 20 Oct 2016 11:15:22 +0200
|
|
Subject: [PATCH] drivers/zram: Don't disable preemption in
|
|
zcomp_stream_get/put()
|
|
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.19/older/patches-4.19.1-rt3.tar.xz
|
|
|
|
In v4.7, the driver switched to percpu compression streams, disabling
|
|
preemption via get/put_cpu_ptr(). Use a per-zcomp_strm lock here. We
|
|
also have to fix an lock order issue in zram_decompress_page() such
|
|
that zs_map_object() nests inside of zcomp_stream_put() as it does in
|
|
zram_bvec_write().
|
|
|
|
Signed-off-by: Mike Galbraith <umgwanakikbuti@gmail.com>
|
|
[bigeasy: get_locked_var() -> per zcomp_strm lock]
|
|
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
|
---
|
|
drivers/block/zram/zcomp.c | 12 ++++++++++--
|
|
drivers/block/zram/zcomp.h | 1 +
|
|
drivers/block/zram/zram_drv.c | 5 +++--
|
|
3 files changed, 14 insertions(+), 4 deletions(-)
|
|
|
|
--- a/drivers/block/zram/zcomp.c
|
|
+++ b/drivers/block/zram/zcomp.c
|
|
@@ -116,12 +116,19 @@ ssize_t zcomp_available_show(const char
|
|
|
|
struct zcomp_strm *zcomp_stream_get(struct zcomp *comp)
|
|
{
|
|
- return *get_cpu_ptr(comp->stream);
|
|
+ struct zcomp_strm *zstrm;
|
|
+
|
|
+ zstrm = *this_cpu_ptr(comp->stream);
|
|
+ spin_lock(&zstrm->zcomp_lock);
|
|
+ return zstrm;
|
|
}
|
|
|
|
void zcomp_stream_put(struct zcomp *comp)
|
|
{
|
|
- put_cpu_ptr(comp->stream);
|
|
+ struct zcomp_strm *zstrm;
|
|
+
|
|
+ zstrm = *this_cpu_ptr(comp->stream);
|
|
+ spin_unlock(&zstrm->zcomp_lock);
|
|
}
|
|
|
|
int zcomp_compress(struct zcomp_strm *zstrm,
|
|
@@ -171,6 +178,7 @@ int zcomp_cpu_up_prepare(unsigned int cp
|
|
pr_err("Can't allocate a compression stream\n");
|
|
return -ENOMEM;
|
|
}
|
|
+ spin_lock_init(&zstrm->zcomp_lock);
|
|
*per_cpu_ptr(comp->stream, cpu) = zstrm;
|
|
return 0;
|
|
}
|
|
--- a/drivers/block/zram/zcomp.h
|
|
+++ b/drivers/block/zram/zcomp.h
|
|
@@ -14,6 +14,7 @@ struct zcomp_strm {
|
|
/* compression/decompression buffer */
|
|
void *buffer;
|
|
struct crypto_comp *tfm;
|
|
+ spinlock_t zcomp_lock;
|
|
};
|
|
|
|
/* dynamic per-device compression frontend */
|
|
--- a/drivers/block/zram/zram_drv.c
|
|
+++ b/drivers/block/zram/zram_drv.c
|
|
@@ -1014,6 +1014,7 @@ static int __zram_bvec_read(struct zram
|
|
unsigned long handle;
|
|
unsigned int size;
|
|
void *src, *dst;
|
|
+ struct zcomp_strm *zstrm;
|
|
|
|
if (zram_wb_enabled(zram)) {
|
|
zram_slot_lock(zram, index);
|
|
@@ -1048,6 +1049,7 @@ static int __zram_bvec_read(struct zram
|
|
|
|
size = zram_get_obj_size(zram, index);
|
|
|
|
+ zstrm = zcomp_stream_get(zram->comp);
|
|
src = zs_map_object(zram->mem_pool, handle, ZS_MM_RO);
|
|
if (size == PAGE_SIZE) {
|
|
dst = kmap_atomic(page);
|
|
@@ -1055,14 +1057,13 @@ static int __zram_bvec_read(struct zram
|
|
kunmap_atomic(dst);
|
|
ret = 0;
|
|
} else {
|
|
- struct zcomp_strm *zstrm = zcomp_stream_get(zram->comp);
|
|
|
|
dst = kmap_atomic(page);
|
|
ret = zcomp_decompress(zstrm, src, size, dst);
|
|
kunmap_atomic(dst);
|
|
- zcomp_stream_put(zram->comp);
|
|
}
|
|
zs_unmap_object(zram->mem_pool, handle);
|
|
+ zcomp_stream_put(zram->comp);
|
|
zram_slot_unlock(zram, index);
|
|
|
|
/* Should NEVER happen. Return bio error if it does. */
|