| From ae3dac1d820f0d8e02b3956c7565a1530e47e271 Mon Sep 17 00:00:00 2001 |
| 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() |
| |
| 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> |
| |
| diff --git a/drivers/block/zram/zcomp.c b/drivers/block/zram/zcomp.c |
| index 12046f4f00e4..39c8f80aafb6 100644 |
| --- a/drivers/block/zram/zcomp.c |
| +++ b/drivers/block/zram/zcomp.c |
| @@ -118,12 +118,19 @@ ssize_t zcomp_available_show(const char *comp, char *buf) |
| |
| 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, |
| @@ -173,6 +180,7 @@ int zcomp_cpu_up_prepare(unsigned int cpu, struct hlist_node *node) |
| 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; |
| } |
| diff --git a/drivers/block/zram/zcomp.h b/drivers/block/zram/zcomp.h |
| index 41c1002a7d7d..d424eafcbf8e 100644 |
| --- 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 */ |
| diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c |
| index b758e3db2e30..7282653dbaca 100644 |
| --- a/drivers/block/zram/zram_drv.c |
| +++ b/drivers/block/zram/zram_drv.c |
| @@ -562,6 +562,7 @@ static int zram_decompress_page(struct zram *zram, struct page *page, u32 index) |
| unsigned long handle; |
| unsigned int size; |
| void *src, *dst; |
| + struct zcomp_strm *zstrm; |
| |
| if (zram_same_page_read(zram, index, page, 0, PAGE_SIZE)) |
| return 0; |
| @@ -570,6 +571,7 @@ static int zram_decompress_page(struct zram *zram, struct page *page, u32 index) |
| handle = zram_get_handle(zram, index); |
| 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); |
| @@ -577,14 +579,12 @@ static int zram_decompress_page(struct zram *zram, struct page *page, u32 index) |
| 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. */ |
| -- |
| 2.1.4 |
| |