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>
This commit is contained in:
Mike Galbraith 2016-10-20 11:15:22 +02:00 committed by Alibek Omarov
parent c6cc729f9a
commit bc7cc87312
3 changed files with 15 additions and 4 deletions

View File

@ -113,12 +113,20 @@ 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 = *get_local_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);
put_local_ptr(zstrm);
}
int zcomp_compress(struct zcomp_strm *zstrm,
@ -168,6 +176,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;
}

View File

@ -10,6 +10,7 @@ struct zcomp_strm {
/* compression/decompression buffer */
void *buffer;
struct crypto_comp *tfm;
spinlock_t zcomp_lock;
};
/* dynamic per-device compression frontend */

View File

@ -1257,6 +1257,7 @@ static int __zram_bvec_read(struct zram *zram, struct page *page, u32 index,
unsigned long handle;
unsigned int size;
void *src, *dst;
struct zcomp_strm *zstrm;
zram_slot_lock(zram, index);
if (zram_test_flag(zram, index, ZRAM_WB)) {
@ -1287,6 +1288,7 @@ static int __zram_bvec_read(struct zram *zram, struct page *page, u32 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);
@ -1294,14 +1296,13 @@ static int __zram_bvec_read(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. */